常用排序算法总结
来源:互联网 发布:加工中心倒角编程实例 编辑:程序博客网 时间:2024/06/06 01:26
1.排序算法
1.1 插入排序
1.1.1 概念
1.1.2 代码
void insertionSort(int arr[], int len){ int insertPosi; for (int i = 0; i < len; i++) { insertPosi = 0; //can't find the bigger position then keep the insertPosi 0 //find the insert position for (int j = i - 1; j >= 0; j--) { if (arr[j] <= arr[i]) { insertPosi = j + 1; //insert at arr[j + 1], minimum of inserPosi is 1 int the loop; break; } } //same position as i, just keep it if (insertPosi == i) continue; //copy from [j + 1, i - 1] -> [j + 2, i] //namely copy from [insertPosi, i) -> [insertPosi + 1], i + 1) int temp = arr[i]; for (int k = i - 1; k >= insertPosi; k--) { arr[k + 1] = arr[k]; } arr[insertPosi] = temp; }}
1.1.3 时间复杂度分析
查找插入位置的效率 在 O(1)~O(n)浮动
1)当输入序列已经有序时,该算法中的查找插入位置仅需O(1)时间,
即第一次判断 arr[j] <= arr[i],就成立了,就完成搜索了;
累计需要O(n)的时间,n*O(1)。
2)当输入序列完全逆序,则各次查找插入位置需要线性时间;
即每次都要判断线性长度次,比如将第i个元素插入到前面[0,i)的有序
序列中,需要搜索 i-1 次。
这样搜索完所有的长度,累计需要
另外,向后复制的次数和搜索的向前遍历的次数是一样的,所以,总的时间是
2倍于搜索所需时间,常数2可以抹去。
总结
1)在等概率条件下,平均仍需要
2)输入敏感性很强,时间取决于逆序对的数目!!!
1.2 归并排序
1.2.1 概念
1.2.2 代码
/***************sort 2: mergeSort**************************************************************/void mergeSort(int arr[], int len){ mergeSortCore(arr, 0, len);}/*[lo, hi)*/void mergeSortCore(int arr[], int lo, int hi){ if (hi - lo < 2) return; int mi = (lo + hi) / 2; mergeSortCore(arr, lo, mi); mergeSortCore(arr, mi, hi); merge(arr, lo, mi, hi);}/*二路有序数组的归并,[lo, mi)[mi, hi)复杂度分析:每经过一次迭代,j和k至少有一个会+1,merge总体迭代不会超过O(n)*/void merge(int arr[], int lo, int mi, int hi){ int* A = arr + lo; int lb = mi - lo; int* B = new int[lb]; for (int i = 0; i < lb; B[i] = A[i++]); int lc = hi - mi; int* C = arr + mi; //1.精简实现 //循环条件是复制出来的B序列还没全部插入排序 //如果B已经全部插入排序,C序列本身与A序列共享内存,不需要再做搬运复制工作 for (int i = 0, j = 0, k = 0; j < lb; ) { //C序列还没全部插入,并且比B序列当前的小 if (k < lc && C[k] < B[j]) A[i++] = C[k++]; //C序列已经全部插入,或者 B序列当前的比C序列的小 if (lc <= k || B[j] <= C[k]) A[i++] = B[j++]; } //2.复杂实现 // for (int i = 0, j = 0, k = 0; (j < lb) || (k < lc); ) // { // if ((j < lb) && (!(k < lc) || (B[j] <= C[k]))) // A[i++] = B[j++]; // if ((k < lc) && (!(j < lb) || (C[k] < B[j]))) // A[i++] = C[k++]; // } delete [] B;}
1.2.3 时间复杂度分析
归并排序
=>
1.3 选择排序
selectMax()每次必须遍历整个无序前缀,耗时线性正比于前缀长度,累计需要
输入不敏感,不论逆序对是多少,时间是固定的,即最好和最坏情况下的渐进效率相同,都为
在列表形式实现中,与“冒泡排序”相比,比较次数是一样的,但是交换次数不一样。
void selectionSort(int arr[], int len){ int maxIdx = 0; for (int i = len; i > 1; i--) { maxIdx = selectMax(arr, i); swap(arr[i - 1], arr[maxIdx]); }}int selectMax(int arr[], int len){ int maxIdx = 0; for (int i = 1; i < len; i++) { if (arr[i] > arr[maxIdx]) maxIdx = i; } return maxIdx;}
1.4 桶排序
/**********sort 4 : bucketSort*******
O(n)
************************************/
void bucketSort(int arr[], int len){ int cntArr[GRADE_NUM]; memset(cntArr, 0, GRADE_NUM * sizeof(int)); for (int i = 0; i < len; i++) { ++cntArr[arr[i]]; } //rebuild int index = 0; for (int i = 0; i < GRADE_NUM; i++) { for (int j = 0; j < cntArr[i]; j++) { arr[index++] = i; } }}
1.5 快速排序
1.5.1 概念
1)构造轴点,使得在轴点左边的小于轴点,在轴点右边的大于等于轴点
轴点位置就是排序后所在的位置
2)根据轴点分左右两段,两段独立,可以分别递归构造新轴点
1.5.2 代码
效率最高的构造轴点解法(partition):
void quickSort(int arr[], int len){ quickSortCore(arr, 0, len);}/*[lo, hi][lo] (lo, mi] (mi, k) [k, hi]pivot Less Greater Unsorted返回轴点位置*/int partition(int arr[], int lo, int hi){ //随机选择候选轴点,并将其交换到 arr[lo]位置 //轴点总是最大或者最小元素的时候,快速排序会退化为冒泡排序, //为了减少这种退化的可能性,应该增加选取轴点的随机性 int randIdx = lo + rand() % (hi - lo + 1); swap(arr[lo], arr[randIdx]); //整体移位 => 用头尾交换来实现 int mi = lo; //指向Less的最后一个元素 int pivot = arr[lo]; for (int k = lo + 1; k <= hi; k++) { if (pivot > arr[k]) swap(arr[++mi], arr[k]); //Greater部分整体后移一个单位,然后在Less 和 Greater之间插入元素 } swap(arr[mi], arr[lo]); //Less部分整体前移一个单位,然后将pivot插入到真正的轴点位置 return mi;}//[lo, hi)void quickSortCore(int arr[], int lo, int hi){ if (hi - lo < 2) return; int mi = partition(arr, lo, hi - 1); //[lo, hi - 1] quickSortCore(arr, lo, mi); //[lo, mi) quickSortCore(arr, mi + 1, hi); //[m + 1, hi)}
1.5.3 时间复杂度分析
partition算法的时间复杂度为
根据partition算法估计总的快速排序的时间,通过递推式推算
下图
最好
最差
等概率下,平均还是
无论是算法A还是算法C都不是稳定排序
1.6 希尔排序
2. 排序算法性能总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法 总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 常用排序算法总结
- 商城项目实战 | 8.2 SwipeRefreshLayout 实现可以下拉刷新和加载更多的热门商品列表
- BZOJ 1078([SCOI2008]斜堆-结论题)
- C语言字符串的分割
- 关于STM32F4定时器时钟频率问题
- iOS开发:Category的具体使用详解
- 常用排序算法总结
- 二分图匹配——BZOJ1854/Luogu1640 [SCOI2010]连续攻击游戏
- git-completion.bash
- iOS开发-97种项目源代码
- PHP Curl post上传图片版本不兼容而引起服务器端接收不到图片问题/考虑 PHP 5.0~5.6 各版本兼容性的 cURL 文件上传
- js 整数、手机号正则表达式
- mysql5.7.18 ERROR 2027 (HY000): Malformed packet问题总括
- android中间件笔记
- Serlet 环境设置