/*
名称:直接插入排序、折半插入排序、希尔排序
说明:本程序比较了插入排序的几种方法。
(1)、直接插入排序:
其适用于顺序存储和链式存储的线性表。它的时间复杂度为O(N2),主要花在比较和移动元素上。
(2)、折半插入排序:
这是在(1)中的方式上做了一点小改变,因为已经排序完成的序列是有序的(好像是废话) 所以每次比较时利用折半的方式,不用挨个比较。它减少了比较的时间。对于元素的移动, 对于(1)来说,它是边比较边移动元素的;而折半插入是找到指定位置后,统一移动元素。元素的总的移动次数并没有改变。所以其时间复杂度也是O(N2)
它是一个稳定的排序算法。
(3)、shell排序:
这是采用分治的思想。把整个序列分为若干个子序列,每次对若干个自序列进行排序。最终在对整体进行一次排序。事实证明,它确实能够大大提高排序的速度。
在本人的机器上进行测试,十万个随机数据,前两种方法大概都用了7s多,可shell排序用了1秒还不到。
它不是一个稳定的算法.
*/
//直接插入排序,n代表元素个数,从elem的下标为1开始存储
void InsertSortDir(int elem[],int n)
{
int i = 0, j = 0;
for( i = 2;i<=n;++i)
{
if(elem[i] < elem[i-1]) //如果当前元素小于前面的元素,说明需要比较前移
{
elem[0] = elem[i]; //elem【0】用作哨兵,不实际存储元素
for(j = i-1; elem[0]<elem[j]; --j) //找到当前元素在此次排序中的位置
elem[j+1] = elem[j];
elem[j+1] = elem[0];
}
}
}
//折半插入排序
void InsertSortBin(int elem[],int n)
{
int i = 0,j = 0;
int high = 0,low = 0,mid = 0;
for(int i = 2;i <= n;++i)
{
if(elem[i] < elem[i-1]) //判断是否需要插入
{
low = 1;
high = i-1;
elem[0] = elem[i];
//寻找待插入位置
while(low <= high)
{
mid = (low + high) / 2;
if(elem[mid] > elem[0])
high = mid -1;
else
low = mid + 1;
}
//向后移动元素
for(j = i; j > high+1;--j)
elem[j] = elem[j-1];
elem[high+1] = elem[0]; //将当前结点插入指定位置
}
}
}
//shell排序
void ShellSort(int elem[],int n)
{
int dk = 0,i = 0,j = 0;
for( dk = n/2; dk >= 1;dk = dk / 2) //dk为递增序列,其值每次减少一半
{
for(i = dk+1; i<=n;++i) //对于每个序列进行排序
{
if(elem[i] < elem[i-dk]) //判断当前的自序列是否需要排序
{
elem[0] = elem[i]; //elem暂存当前元素
for( j = i - dk; j > 0 && elem[j] > elem[0];j = j-dk) //和插入排序有点不同的是,这里的判断条件多了一个j>0,因为每次的递增序列dk不一定是1
elem[j+dk] = elem[j];
elem[j+dk] = elem[0];
}
}
}
}