专题 排序的基本原理

概念解释

前言

OI竞赛中常用的排序算法共有以下几种,我们分为两类:

  • 基于比较;
  • 基于计数。

我们这篇文章重点讨论排序的逻辑实现以及代码的实现细节。

特别注意

  • 本文中使用的数组下标默认从1开始;
  • 本文中默认排序是进行升序排序操作。

算法分析

1.冒泡排序

核心思想

基于比较,一句话总结:

小数上浮,或者大数下沉。无非起起伏伏。

笔者给出算法步骤:

  • 轮换 \(n-1\) 次,进行这么多次的交换;
  • 在每一次交换中,看看两个指针对应的数组元素是否需要交换,若是,则进行交换。

参考代码

for(int i=1;i<=n-1;i++)
{
	flag=true;
	for(int j=1;i+j<=n;j++)
		if(a[j]>a[j+1])
		{
			a[0]=a[j];//a[0]作为临时变量
			a[j]=a[j+1];
			a[j+1]=a[0];
			flag=false;
		}
	if(!flag) break;
}

细节研讨

上面的代码中有着一个优化,就是flag标记。这个是由于。每一次进行交换,如果成功交换,那么就置为false。这样可以提前结束循环,但事实上,带来的只是常数的优化。而且正常竞赛中也没有人会手写排序,何况是这种 \(O(n^{2})\) 的效率低的算法呢。

2.选择排序

核心思想

一句话总结:

基本思想是每一趟从待排序的数据元素中选出最小(或最大) 的一个元素,顺序放在待排序序列的最前面,直到全部数据有序。

事实上,这已经很明显了,很简单的操作:

  • 选择一个最大值,(这一步是要遍历整个数组元素的,所以效率低下);
  • 插入所求位置(这里依照前文约定,应是最后一个位置)。

参考程序

for(int i=1;i<=n-1;i++)
{
	mark=i;
	for(int j=i+1;j<=n;j++)
		if(a[mark]>a[j]) mark=j;
//增设一个变量,找出最值
	if(mark!=i)
	{
		a[0]=a[mark];
		a[mark]=a[i];
		a[i]=a[0];
	}
}

细节研讨

大体框架与冒泡相同,只是注意一下,循环的范围,这里外一层是控制比较的轮次的。

3.插入排序

总结归纳

posted @ 2025-08-03 10:04  枯骨崖烟  阅读(16)  评论(0)    收藏  举报