面试常考之排序算法
来源:互联网 发布:淘宝点击率是什么意思 编辑:程序博客网 时间:2024/05/29 07:30
总结一下面试常常遇到的基础排序算法(默认升序),方便接下来复习:
1.选择排序
思想:每一趟选出最小值
复杂度分析:最坏情况O(n^2),最好情况O(n^2),平均情况O(n^2),额外空间O(1)
稳定性:不稳定
例子:9 3 6 2 8 7
- 2 3 6 9 8 7 (第一趟)
- 2 3 6 9 8 7 (第二趟)
- 2 3 6 9 8 7 (第三趟)
- 2 3 6 7 8 9 (第四趟)
- 2 3 6 7 8 9 (第五趟)
- 2 3 6 7 8 9 (第六趟)
代码:
void selectSort(int *a,int len){ if(len <= 0) return; for(int i=0;i<len-1;i++) { int min = a[i]; //这个循环选出第i趟最小值 for(int j=i+1;j<len;j++) { if(min>a[j]) { min = a[j]; } } if(min != a[i]) { swap(a,min,a[i]); } }}
2.插入排序
思想:插入第i个元素时,与前面已经排好序的i-1个元素比较,如果它不是插入到最后一个位置,那么大于它的序列就要顺序向后移动一个位置。
复杂度分析:最坏情况O(n^2),最好情况O(n),平均情况O(n^2),额外空间O(1)
稳定性:稳定
例子:9 3 6 2 8 7
- 9 3 6 2 8 7(第一趟)
- 3 9 6 2 8 7(第二趟)
- 3 6 9 2 8 7(第三趟)
- 2 3 6 9 8 7(第四趟)
- 2 3 6 8 9 7(第五趟)
- 2 3 6 7 8 9(第六趟)
代码:
void insertSort(int *a,int len){ if(len <= 0) return; for(int i=1;i<len;i++) { int j = i-1; //要插入的元素 int temp = a[i]; while(j>=0 && temp<a[j]) { //后移 a[j+1] = a[j]; j--; } a[j+1] = temp; //多执行了一次j--,所以要+1 }}
3.希尔排序(递减增量排序)
思想:相距增量(d)的元素为一组,内部采用插入排序方法使组内有序。然后增量减小一个单位,再组内排序,迭代直到增量为1。
复杂度分析:最坏情况O(n^1.3),最好情况O(n),平均情况O(n^2),额外空间O(1)
稳定性:不稳定
例子:9 3 6 2 8 7 (初始:元素个数为6,设置d= 6/2=3,那么9和2为一组,3和8为一组,6和7为一组)
- 2 3 6 9 8 7(第一趟d=3,9和2交换位置,其他两组已经有序)
- 2 3 6 7 8 9(第二趟d=2,2 6 8一组,3 9 7一组,9和7交换)
- 2 3 6 7 8 9(第三趟d=1,只剩一组,已经有序)
代码:
void shellSort(int *a,int len){ if(len <= 0) return; for(int d=len/2;d>=1;d--) { for(int i=d;i<len;i++) { //每一组内部采取插入排序 if(a[i-d]>a[i]) { int temp = a[i]; int k = i-d; while(k>=0 && a[k]>= temp) { a[k+d] = a[k]; k = k-d; } a[k+d] = temp; } } }}
4.冒泡排序
思想:每一趟相邻元素两两比较,逆序则交换(想象成泡泡往上冒),每一次保证最大的到达顶部,排好序的最大元素不纳入下一趟排序。
复杂度分析:最坏情况O(n^2),最好情况O(n),平均情况O(n^2),额外空间O(1)
稳定性:稳定
例子:9 3 6 2 8 7
- 3 6 2 8 7 9(第一趟)
- 3 2 6 7 8 9 (第二趟)
- 2 3 6 7 8 9 (第三趟)
- 2 3 6 7 8 9 (第四趟)
- 2 3 6 7 8 9 (第五趟)
- 2 3 6 7 8 9 (第六趟)
代码:
void bubbleSort(int *a,int len){ if(len <= 0) return; for(int i=len-1;i>0;i--) { for(int j=0;j<=i;j++) { if(a[j]>a[j+1]) { swap(a,a[j],a[j+1]); } } }}
5.快速排序
思想:确定pivot之后(一般取第一位元素作为pivot),扫描一趟,比pivot小的放左边,比pivot大的放右边。再对左子序列和右子序列分别调用函数本身(递归),直到不能再分出左子序列和右子序列。
复杂度分析:最坏情况O(n^2),最好情况O(nlogn),平均情况O(nlogn),额外空间O(nlogn)
稳定性:不稳定
例子:4 8 2 6 5 3
- 2 3 4 8 6 5(第一趟)
- 2 3 4 6 5 8(第二趟)
- 2 3 4 5 6 8(第三趟)
代码:
void quickSort(int *a,int left,int right){ if(right <= left) return; int pivot = a[left]; int i = left; int j = right; while(i < j) { while(j>i && a[j]>= pivot) //从右到左找比pivot小的 { j--; } if(j>i) { a[i] = a[j]; i++; } while(j>i && a[i]<= pivot) //从左到右找比pivot小的 { i++; } if(j>i) { a[j] = a[i]; j--; } } a[i] = pivot; //完成一趟 quickSort(a,l,i-1); //左子序列 quickSort(a,i+1,r); //右子序列}
6.归并排序
思想:
复杂度分析:最坏情况O(nlog),最好情况O(nlogn),平均情况O(nlogn),额外空间O(n)
稳定性:稳定
例子:4 8 2 6 5 3
- 4 8 2 | 6 5 3
- 4 | 8 2 | 6 | 5 3
代码:
void mergeSort(int *a,int first,int last, int *temp){ if(first < last) { int mid = (first + last)/2; mergeSort(a,first,mid,temp); //对左子序列排序 mergeSort(a,mid+1,last,temp); //对右子序列排序 mergeArray(a,first,mid,last,temp); //合并 }}//两个有序子序列合并成一个新的序列void mergeArray(int *a,int left,int mid,int right,int *temp){ int i = left, j = right; int k = 0; //循环挑出相对较小的放入临时数组temp中从而保证有序 while(i<=mid && j<=right) { if(a[i] < a[j]) { temp[k++] = a[i++]; }else { temp[k++] = a[j++]; } } while(i <= mid) //如果左子序列还有剩,按序填入 { a[k++] = a[i++]; } while(j <= right) //如果右子序列还有剩,按序填入 { a[k++] = a[j++]; } //把temp中放回原数组 for(int m=0; m<k;m++) { a[first+m] = temp[m]; }}
7.堆排序
思想:
复杂度分析:最坏情况O(nlogn),最好情况O(nlogn),平均情况O(nlogn),额外空间O(1)
稳定性:不稳定
性质:
1.节点的性质:i表示当前节点,则父节点为(i-1)/2,左孩子节点为(2*i+1),右孩子节点为(2 *i+2);
2.最大堆的父节点要大于等于子节点,(最小堆相反);
3.在新建堆的过程中,采用AdjustDown堆化数组,从n/2节点开始,因为大于n/2的是叶子节点。
代码:
//以最大堆为例//堆调整void AdjustDown(int a[],int k,int len)//将元素a[k]向下调整{ a[0] = a[k]; //a[0]暂存,相当于temp for(int i=2*k; i<=len; i*=2) { if(i<len && a[i]<a[i+1]) { i++; //取值较大的i的下标 } if(a[0]>=a[i]) { break; //a[0]>子节点中最大的值,结束筛选 }else { a[k] = a[i]; //否则交换 k = i; //跟踪k的下标 } } a[k] = a[0]; //调整结束后,把a[k]的值补上}//新建堆void BuildMaxHeap(int a[],int len){ for(int i=len/2;i>0;i--) //从i=len/2 - 1,反复调整堆 { AdjustDown(a,i,len); //从上往下调整直到子树满足最大堆 }}//堆排序--调用前两个函数void HeapSort(int a[],int len){ BuildMaxHeap(a,len); //初始建堆 for(int i=len;i>1;i--) { swap(a[i],a[1]); //可得到堆顶元素 AdjustDown(a,1,i-1); //整理剩余的i-1个元素 }}
写到后面有点晕掉了,…(◎ロ◎)… ,休息一下…
- 面试常考之排序算法
- 笔试面试常考排序算法总结
- 面试常考排序
- 常考排序算法
- [面试常考]排序算法总结
- 程序员面试常考,最通俗易懂的排序算法详解
- 面试常考8种排序算法的总结
- 面试常考算法题
- 面试常考数据结构算法
- js面试常考算法
- C++基础之快速排序实现(面试常考)
- 计算机网络之面试常考
- 操作系统之面试常考
- 计算机网络之面试常考
- 计算机网络之面试常考
- 计算机网络之面试常考
- 计算机网络之面试常考
- 计算机网络之面试常考
- Choices of the Gadgets
- xShell 5外观(背景、文字等)设置方案
- 手机暗屏下,后台不能使用蓝牙,后台gps不能定位
- JAVA回调机制(CallBack)详解
- 【C】用VS编写C程序
- 面试常考之排序算法
- 西加云杉700E设备AAA认证之Portal服务器与AC的交互
- JavaBean规范
- maven配置和更新本地库
- 算法练习笔记(十)——动态规划之回文子列的查找
- 西加云杉700E设备AAA认证之Radius服务器与AC的交互
- Git代码管理终极简单使用篇
- HDU 3605 Escape (二分图多重匹配模板)
- 服务器搭建日志之ftp服务器