zoukankan      html  css  js  c++  java
  • 数据结构:冒泡排序及其改进、插入排序和希尔排序

    前提

    void X_Sort ( ElementType A[], int N )

    • 大多数情况下,为简单起见,讨论从小大的整数排序
    • N是正整数
    • 只讨论基于比较的排序(> = < 有定义)
    • 只讨论内部排序(若内存小于数据大小,则需要外部排序)
    • 稳定性:任意两个相等的数据,排序前后的相对位置不发生改变
    • 没有一种排序是任何情况下都表现最好的

    简单排序

    冒泡排序

    基础冒泡

    • 从第1个泡泡开始,大的下沉,沉到不能沉为止,此时第n个泡泡最大。
    • 从第i个泡泡开始,大的下沉,沉到不能沉为止,比较到n-i个泡泡即可。
    void Bubble_Sort( ElementType A[], int N )
    { for ( P=N-1; P>=0; P-- ){
    for( i=0; i<P; i++ ) { /* 一趟冒泡*/
    if ( A[i] > A[i+1] ) {
    Swap(A[i], A[i+1]);
    }
    }
    }
    }
    

    加强版冒泡

    • 用一个flag来标记,若一趟下来,不发生交换,则说明排序完成。
    void Bubble_Sort( ElementType A[], int N )
    { for ( P=N-1; P>=0; P-- ){
    flag = 0;
    for( i=0; i<P; i++ ) { /* 一趟冒泡*/
    if ( A[i] > A[i+1] ) {
    Swap(A[i], A[i+1]);
    flag = 1; /* 标识发生了交换*/
    }
    }
    if ( flag==0 ) break; /* 全程无交换*/
    }
    }
    

    优缺点分析

    • 最好情况:顺序T = O( N )
    • 最坏情况:逆序T = O( N^2 )

    优点

    • 易于实现
    • 对数组 链表都没问题
    • 稳定的

    缺点

    • 复杂度过高

    插入排序

    • 摸出第1张牌,从第n张开始比较,若大小关系错误,则第n张后移一位,再与n-1相比较,直到大小关系正确,插入该位置。
    • 摸出第i张牌,从第n张开始比较,若大小关系错误,则第n张后移一位,再与n-1相比较,直到大小关系正确,插入该位置。
    void Insertion_Sort( ElementType A[], int N )
    { for ( P=1; P<N; P++ ) {
    Tmp = A[P]; /* 摸下一张牌*/
    for ( i=P; i>0 && A[i-1]>Tmp; i-- )
    A[i] = A[i-1]; /* 移出空位*/
    A[i] = Tmp; /* 新牌落位*/
    }
    }
    

    优缺点分析

    最好情况:顺序T = O( N )
    最坏情况:逆序T = O( N2 )

    优点

    • 易于实现
    • 比冒泡好,每一步都少一些步骤
    • 稳定的

    缺点

    • 复杂度高

    插入排序的改进:希尔排序

    • 定义增量序列 Dm>Dm-1>……>D1=1
    • 对每个Dk进行“Dk-间隔”排序(K=m,m-1,……1)
    • 注意:Dk间隔有序的序列,在执行“Dk-1间隔”排序后,仍然是Dk间隔有序的。

    一个例子

    一个坏例子

    • 原始希尔排序DM = 向下取整( N / 2 ) , Dk = 向下取整( Dk+1 / 2 )。
    • 最坏情况: T = θ( N2 )
    void Shell_sort( ElementType A[], int N )
    { for ( D=N/2; D>0; D/=2 ) { /* 希尔增量序列*/
    for ( P=D; P<N; P++ ) { /* 插入排序*/
    Tmp = A[P];
    for ( i=P; i>=D && A[i-D]>Tmp; i-=D )
    A[i] = A[i-D];
    A[i] = Tmp;
    }
    }
    }
    

    更多增量序列

    基于比较的排序

    时间复杂度下界

    • 对于下标i<j,如果A[i]>A[j],则称(i,j)是
      一对逆序对(inversion)
    • 问题:序列{34, 8, 64, 51, 32, 21}中有多少逆序对?
    • (34, 8) (34, 32) (34, 21) (64, 51) (64, 32) (64, 21) (51, 32) (51, 21) (32, 21)
    • 交换2个相邻元素正好消去1个逆序对!
    • 插入排序:T(N, I) = O( N+I )
    • 如果序列基本有序,则插入排序简单且高效

    相关定理

    • 定理:任意N个不同元素组成的序列平均具有
      N ( N - 1 ) / 4 个逆序对。
    • 定理:任何仅以交换相邻两元素来排序的算
      法,其平均时间复杂度为Ω ( N2 ) 。
    • 这意味着:要提高算法效率,我们必须每次消去不止1个逆序对!
    • 每次交换相隔较远的2个元素!
  • 相关阅读:
    88. Merge Sorted Array
    87. Scramble String
    86. Partition List
    85. Maximal Rectangle
    84. Largest Rectangle in Histogram
    83. Remove Duplicates from Sorted List
    82. Remove Duplicates from Sorted List II
    81. Search in Rotated Sorted Array II
    80. Remove Duplicates from Sorted Array II
    计算几何——点线关系(叉积)poj2318
  • 原文地址:https://www.cnblogs.com/vancasola/p/8043710.html
Copyright © 2011-2022 走看看