数据结构笔记(6)排序

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

    int i,j,Increment;//增量
    int Tmp;

    for(Increment=N/2;Increment>0;Increment/=2)//希尔增量
        for(i=Increment;i<N;i++)//从中间元素开始,游标向后行进
        {//开始i仅为中间部分,当游标行进至末尾部分时会对前面所有符合增量间隔的元素进行重新排序,但前面已经比较过的元素不会交换了
            Tmp=A[i];//比较的值之一
            for(j=i;j>=Increment;j-=Increment)//向前推进,如果前面相隔增量hk的元素较大,则将其添加到当前位置,如果较小则不动
                if(Tmp<A[j-Increment])
                    A[j]=A[j-Increment];
                else break;
            A[j]=Tmp;//将Tmp添加到最后空着的位置
            //当前面发生互换位置时,j=j-Increment为空位置
            //当前面未发生互换位置时,j=i
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值