排序算法(一)--插入排序之直接插入排序和希尔排序

来源:互联网 发布:提前上班被开除 知乎 编辑:程序博客网 时间:2024/05/16 10:37
排序的基本概念
排序:排序是将一个任意序列排列成一个按关键码有序的序列
排序算法的稳定性:在经过排序后,序列中相同关键码的记录相对位置没有发生改变称为稳定
单键,多键排序:根据一个关键码排序叫做单键排序;根据多个关键码进行排序叫做多键排序.
排序的分类:根据待排序列是否全部放置在内存中:内排序,外排序.根据排序是否建立在关键码比较的基础上分为基于比较的排序和不基于比较的排序.

根据排序过程中依据的原则对基于比较的内排序大致分为:插入排序,交换排序,选择排序,归并排序四类。

直接插入排序
算法的基本思想:每次将待排序序列中的一个元素插入到一个有序序列中,直到全部记录排序好.
插入排序类似于我们整理扑克牌的过程.
插入排序过程:
将序列第一个元素作为初始有序序列,从第二个元素开始,依次与前面的元素比较,找到合适的插入位置。直到所有元素找到位置为止.

// 不带哨兵的插入排序
template <class T>void InsertSort(T array[], int aryLen){for (int i = 1; i<aryLen; i++){T num = array[i];int j = 0;for (j = i-1; j>=0; j--){if (num < array[j]){array[j+1] = array[j];}else //{break;}}array[++j] = num;}}// 带哨兵的插入排序template <class T>void InsertSort2(T array, int nLen){for (int i = 2; i< nLen; i++){array[0] = array[i];int j = 0;for (j = i-1; array[0]<array[j];j--){array[j+1] = array[j];}array[++j] = array[0];}}

插入排序的算法性能分析
插入排序一共有两层循环,外层执行n-1次,内层在最好情况下,序列为正序,每次比较1次,移动元素两次.总共比较n-1次,移动2(n-1)次,所以时间复杂度为O(n);
最坏情况下逆序:每次需要比较i次,总共比较(n+2)(n-1)/2,记录需要每次移动i+1次,(n+4)(n-1)/2时间复杂度为O(n^2);
平均情况下,插入第i个元素需要比较有序区记录一半,所以总的比较次数为n(n-1)/4,移动次数(n+4)(n-1)/2所以时间复杂度为O(n^2)
插入排序是一种稳定的算法。当序列中的记录基本有序或待排序列记录较少时,它是最佳的排序算法.基本有序不等于局部有序,局部有序并不能提供插入排序算法的性能。

 希尔排序
 希尔排序是对插入排序的一种改进,改进的着眼点是:1)若待排序列记录按关键码基本有序,直接插入排序的效率很高;
 2)由于直接插入排序算法简单,当待排序序列记录个数较少时效率也很高.
 基本思想:将待排序序列分成若干个子序列,在子列内分别进行插入排序,待整个序列基本有序,在对全体记录进行一次
 直接插入排序.
 具体排序过程:取d<n,将所有相距d的记录构成一组,在每个字序列内进行直接插入排序,再取d<d,继续直到d=1,进行
一次全部记录的直接插入排序。

希尔提出的增量取法:d1 = n/2 d2 = d1/2... 没有除1之外的公因子,并且最后一个增量必须是1.

template <class T>void ShellSort(T array[], int nLen){for (int d = nLen/2; d>=1; d = d/2){for (int i = d; i<nLen; i++) // 对所有相距d的序列进行直接插入排序.{int temp = array[i];int j = i;for (j = i-d; j>=0; j-=d){if (temp < array[j]){array[j+d] = array[j];}else{break;}}array[j+d] = temp;}}}
希尔排序的性能在O(n^2)~~O(n*log2N)之间.当n在某个特定范围内时,希尔排序的时间性能为O(n^1.3);
希尔排序是一种不稳定的排序算法.

0 0