基于比较的排序——前提:
- 每个算法都将接收一个含有元素的数组和一个包含元素个数的整数
- 元素个数N是被检查过的、合法的
- 所有的排序,数据都将在位置0处开始
- ‘>’和 ‘<’运算符存在
选择排序
- 算法:
- 找到数组中最小的元素
- 把它和数组的第一个元素交换位置
- 在剩下的元素中找到最小的元素
- 与数组的第二个元素交换位置
- 直到排序完成
- 算法特点:
- 运行时间与输入无关:前一遍扫描出的最小元不能为下一遍提供帮助,一个已经拍好的数组、一个所有元素相等的数组和乱序的数组所需要的排序时间一样长。
- 数据移动是最少的:每次交换都会改变两个数组元素的值,选择排序用了N次交换。交换次数和数组的大小是线性关系。
- 代码实现
void chooseSort(int A[],int N)
{
int i,j=0;;
int min=0;
while (j!=N)
{
for(i=j;i<N;i++)
if(A[i]<A[min])
{
min=i;
}
/** 交换元素 */
int tmp=A[j];
A[j]=A[min];
A[min]=tmp;
/** 更新最小元的信息,从第二个元素开始查找 */
j++;
min=j;
}
}
插入排序(insertion sort)
- 算法:
- 检查当前元素在前置序列中的位置,假定前置序列已经有序,将当前元素插入到正确位置。当索引到达数组右端时,排序完成。
- 算法特点:
- 插入排序所需的时间取决于输入中元素的初始顺序。对一个有序/接近有序的数组执行排序所需的时间将会比随机顺序或倒序的数组小很多。
- 最坏的情况下(倒序),耗时O(n^2)
- 最好的情况下(有序),耗时O(n),每次检查时直接退出内层循环。
- 代码实现:
void insertSort(int A[],int N)
{
int j,p;
int tmp;
for(p=1;p<N;p++)
{
tmp=A[p];
for(j=p;j>0&&A[j-1]>tmp;j--)
A[j]=A[j-1];
A[j]=tmp;
}
}
希尔排序(Shellsort)(冲破二次时间屏障的第一批算法之一)
- 算法:
- 概述:通过比较相距一定间隔的元素来工作;各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止。
- 在使用增量为hk的一趟排序之后,对于每一个i我们都可以得到A[i]<=A[i+hk]的结果——>所有相隔hk的元素都被排序。
- 缩小hk,重复进行排序步骤,直到所有的排序完成。
- 时间复杂度分析:
- 使用希尔增量时希尔排序的最坏情形运行时间为O(N^2)。
- 希尔增量:ht=[N/2],hk=[h(k+1)/2]
- 使用Hibbard增量的希尔排序最坏情形运行时间为O(N^(3/2))。
- 图例:
- 代码实现:
void Shellsort(int A[],int N)
{
int i,j,Increment;
int Tmp;
for(Increment=N/2;Increment>0;Increment/=2)
for(i=Increment;i<N;i++)
{
Tmp=A[i];
for(j=i;j>=Increment;j-=Increment)
if(Tmp<A[j-Increment])
A[j]=A[j-Increment];
else break;
A[j]=Tmp;
}
}