插入排序、快速排序、堆排序
来源:互联网 发布:端口出现感叹号 编辑:程序博客网 时间:2024/06/06 01:27
1. 直接插入排序
算法如下:
void insertSort(int A[], int n) //A[1..n], A[0]用作哨兵{ int i, j; for (i = 2;i <= n;i++) { if (A[i] >= A[i - 1]) continue; A[0] = A[i]; //复制为哨兵 A[i] = A[i - 1]; for (j = i -2;A[j] > A[0];j--) A[j + 1] = A[j]; //记录后移 A[j + 1] = A[0]; //插入到正确位置 }}
算法的时间复杂度为O(n^2)。
当数组A[]中的元素有序时,算法进行的关键字比较次数大到最小值n-1,此时不需要移动记录。
2. 快速排序
算法如下:
int partition(int A[], int low, int high){ int pivotkey, temp; pivotkey = low; //pivotkey = mid{A[low], A[(high + low) / 2], A[high]} if (A[low + (high - low) / 2] > A[low]) { pivotkey = low + (high - low) / 2; } if (A[high] > A[low + (high - low) / 2]) { pivotkey = high; } temp = A[low]; A[low] = A[pivotkey]; A[pivotkey] = temp; pivotkey = A[low]; //枢轴记录关键字 while (low < high) //从表的两端交替的向中间扫面 { while (low < high && A[high] >= pivotkey) //将比枢轴记录小的记录移到低端 high--; A[low] = A[high]; while (low < high && A[low] <= pivotkey) //将比枢轴大的记录移到高端 low++; A[high] = A[low]; } A[low] = pivotkey; //枢轴记录到位 return low; //返回枢轴位置}void qsort(int A[], int low, int high){ int pivotloc; if (low < high) { pivotloc = partition(A, low, high); if (pivotloc - low < high - pivotloc){ //先对长度短的子序列中的记录进行快速排序 qsort(A, low, pivotloc - 1); qsort(A, pivotloc + 1, high); } else { qsort(A, pivotloc + 1, high); qsort(A, low, pivotloc - 1); } }}
算法平均时间复杂度为O(nlogn)。就平均时间而言,快速排序是目前被认为最好的一种排序方法。
当序列基本有序时,算法变成冒泡排序,时间复杂度为O(n^2)。
最好每次划分能得到两个相等的子序列,即每趟排序之后,pivotkey的位置应靠中间位置,因此pivotkey的选择影响算法的时间复杂度。因此pivotkey采用”三者取中“的办法,即取A[low]、A[(low + high) / 2]、A[high]三者中的中值作为枢轴值。经验证明采用三者取中的规则可大大改善快速排序在最坏情况下的性能。
在递归调用的过程中,若每趟排序之后,枢轴位置均偏向子序列的一端,则递归调用的深度大到最大值n。在调用的过程中若先对短的子序列中的记录进行快速排序,栈的最大深度可降为O(logn)
3. 堆排序(利用数组模拟堆)
代码如下:
/**已知A[s..m]中的关键字除A[s]之外均满足堆的定义,此函数调整A[s]使A[s..m]成为一个大顶堆*/void heapAdjust(int A[], int s, int m){ int rc, j; rc = A[s]; for (j = s << 1;j <= m;j <<= 1)//沿关键字较大的孩子结点向下筛选 { if (j < m && A[j + 1] > A[j]) j++; //j为关键字较大的记录的下标 if (rc >= A[j]) //当rc大于等于较大的关键字时结束 break; A[s] = A[j]; //移动关键字 s = j; } A[s] = rc;}/**对顺序表A[1..n]进行堆排序*/void heapSort(int A[], int n){ int i, temp; for (i = n >> 1;i >= 1;i--) //构建堆 heapAdjust(A, i, n); for (i = n;i > 1;i--) { temp = A[1]; //将堆顶记录和和当前未经排序子序列A[1..i]中的 //最后一个记录相互交换 A[1] = A[i]; A[i] = temp; heapAdjust(A, 1, i - 1);//将A[1..i-1]重新调整为一个大顶堆 }}
调整一个结点的过程的时间复杂度为O(logn)。
建立初始堆的过程就是反复调整结点的过程,时间复杂度为O(nlogn)。
对建好的对进行排序过程时间复杂度为O(nlog)。
因此总的时间复杂度为O(nlogn)。
在在最坏情况下的时间复杂度为O(nlogn),要好于快速排序。
- 插入排序、快速排序、堆排序
- 冒泡排序 快速排序 插入排序 堆排序 选择排序
- 插入排序、选择排序、冒泡排序、快速排序、堆排序
- 插入排序、希尔排序、堆排序、归并排序、快速排序
- 快速排序,堆排序,希尔排序,插入排序
- 插入排序,快速排序,堆排序,归并排序
- 插入排序、合并排序、堆排序和快速排序
- 排序:插入,希尔,堆,快速,归并排序
- 插入排序、冒泡排序、选择排序、Shell排序、快速排序、归并排序、堆排序
- C# 插入排序 冒泡排序 选择排序 快速排序 堆排序 归并排序 基数排序 希尔排序
- 冒泡排序 快速排序 选择排序 堆排序 直接插入排序 希尔排序 归并排序
- 冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序java实现
- 插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序
- 冒泡排序,插入排序,快速排序,归并排序,堆排序,选择排序,希尔排序
- 插入排序、二分插入排序、希尔排序、选择排序、冒泡排序、鸡尾酒排序、快速排序、堆排序、归并排序
- 快速排序/堆排序
- 快速排序、希尔排序、插入排序、选择排序、归并排序、堆排序总结
- 插入排序、冒泡排序、选择排序、快速排序、堆排序、归并排序算法比较
- 2012 Multi-University Training Contest 5:Mark the Rope
- ZOJ 1051 A New Growth Industry
- 相关 /dev/null 2>&1 详解
- 程序员求职之道(《程序员面试笔试宝典》)之数据结构与算法(排序算法)?
- nyoj 517 最小公倍数(大数+求最小公倍数思想)
- 插入排序、快速排序、堆排序
- Android Service被关闭后自动重启,解决被异常kill 服务
- [iOS]深入浅出ObjC之消息
- [Python] 找寻A文件中有而B文件中没有的记录
- 贪心算法 - 哈夫曼编码 Huffman
- 带环的链表
- 范围搜索 (Range Query)
- 黑马程序员_SQL总结一
- Problems occurred when invoking code from plug-in: "org.eclipse.jface".