排序之插入排序

/*
名称:直接插入排序、折半插入排序、希尔排序
说明:本程序比较了插入排序的几种方法。
(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];
            }
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值