算法之七种排序
Posted jzssuanfa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法之七种排序相关的知识,希望对你有一定的参考价值。
插入排序
public static void insertSort(int[] t){ for(int i=1; i<t.length; i++){ //将第i个数提取出来 int temp = t[i]; int j; for(j=i-1; j>=0 && temp<t[j]; j--){ //假设提取出来的那个数小于t[j],数据里面的数就往后移。 t[j+1] = t[j]; } //提取出来的数大于或等于t[j]。就插入到t[j]的后一个位置上(即t[j+1]) t[j+1] = temp; } }
时间复杂度:最好情况为O(n); 最坏情况为:O(n^2),是稳定的。
希尔排序
public static void shellSort(int[] t){ //不断缩小比較数据之间的位置,直到变成插入排序 for(int delta=t.length/2; delta>0; delta/=2){ //原理和插入排序一样, //仅仅是将1换成delta而已 for(int i=delta; i<t.length; i++){ int temp=t[i]; int j; for(j=i-delta; j>=0 && temp<t[j]; j-=delta){ t[j+delta] = t[j]; } t[j+delta] = temp; } } }
基本思想是分组的直接插入排序。时间复杂度为:O(n(㏒2n)2)。那个2是指下标的2(下同),是不稳定的。
冒泡排序
public static void bubbleSort(int[] t){ //是否交换的标记 boolean exchange = true; //每循环一次,就会得到一个最大值 for(int i=1; i<t.length && exchange; i++){ exchange = false; for(int j=0; j<t.length-i; j++){ if(t[j]>t[j+1]){ int temp = t[j+1]; t[j+1] = t[j]; t[j] = temp; exchange = true; } } } }
基本思想是:比較相邻两个元素的keyword值,假设反序。则交换。
假设按升序排序,每一趟将被扫描的数据序列中的最大元素交换到最后位置。就像气泡从水里冒出一样。
时间复杂度:最好情况:O(n)。 最坏情况:O(n2),是稳定的
高速排序
public static void quickSort(int[] t){ quickSort(t,0,t.length-1); } private static void quickSort(int[] t, int begin, int end) { //推断序列是否有效 if(begin<end){ int i=begin, j=end; //提取基准值 int vot = t[i]; while(i!=j){ //从后面寻找较小值 while(i<j && vot <= t[j]){ j--; } if(i<j){ //较小值往前移动 t[i++] = t[j]; } //从前面寻找较大值 while(i<j && t[i]<=vot){ i++; } if(i<j){ //较大值往后移动 t[j--] = t[i]; } } //确定基准值的位置 t[i]=vot; //前端子序列在排序,递归调用 quickSort(t,begin,j-1); //后端子序列在排序,递归调用 quickSort(t,i+1,end); } }
基本思想是:在数据序列中选择一个值作为比較的基准值。每趟从数据序列的两端開始交替进行,将小于基准值的元素交换到序列前端,将大于基准值的元素交换到序列后端。介于两者之间的位置则成为基准值的终于位置。
同一时候,序列被划分成两个子序列。再用相同的方法分别对两个子序列进行排序。直到子序列的长度为1,则完毕排序。
时间复杂度:最好的情况:O(n*㏒2n); 最坏的情况:O(n2);是不稳定的。
直接选择排序
public static void selectSort(int[] t){ for(int i=0; i<t.length-1; i++){ //标记最小值的位标 int min=i; //遍历寻找最小值 for(int j=i+1; j<t.length; j++){ if(t[j]<t[min]){ min=j; } } //将最小值交换到前面 if(min!=i){ int temp = t[i]; t[i] = t[min]; t[min] = temp; } } }
基本思想:第一趟从n个元素的数据序列中选出keyword最小(或最大)的元素并放到最前(或最后)位置,下一趟再从n-1个元素中选出最小(大)的元素并放到次前(后)位置。以此类推,经过n-1趟完毕排序。
时间复杂度:最好情况:O(n2); 最坏情况:O(n2); 是不稳定的。
堆排序
//将以begin为根的子树调整成最小堆 private static void sift(int[] t,int begin, int end){ //j为i结点的左孩子 int i=begin, j=2*i+1; //子树根节点的值 int temp=t[i]; while(j<=end){ //比較左右孩子。将j定位到最小那个 if(j<end && t[j]>t[j+1]){ j++; } if(temp>t[j]){ //若子树根节点的值较大, //较小的孩子结点上移 t[i]=t[j]; //使i,j向下一层 i=j; j=2*i+1; }else{ break; } } //当前子树的原根值调整后的位置 t[i]=temp; } public static void heapSort(int[] t){ int n=t.length; //创建最小堆 for(int j=n/2-1; j>=0; j--){ sift(t,j,n-1); } //每趟将最小值交换到后面。再调整成堆 for(int j=n-1; j>0; j--){ int temp = t[0]; t[0] = t[j]; t[j] = temp; sift(t,0,j-1); } }
基本思想:首先和直接选择排序对照一下。在直接选择排序中。每趟从数据序列中选出一个最小值交换到前面,其余n-1个元素原地不动,下一趟须要再次比較这些元素,因此直接选择排序算法的反复比較非常多。假设每趟可以利用前一趟的比較结果,则会降低一些反复比較,从而提高算法效率。
堆排序就是利用全然二叉树的特性,每趟仅仅需遍历树中的一条路径即可了。而不是所有元素。
时间复杂度:最好最坏情况都是:O(n*㏒2n)。 是不稳定的。
归并排序
//对子序列元素的操作, //m和r各自是相邻的两个已排序子序列的起始下标, //n为子序列的长度 private static void merge(int[] X, int[] Y, int m, int r, int n){ int i=m, j=r, k=m; //将X中两个相邻子序列归并到Y中 while(i<r && j<r+n && j<X.length){ if(X[i] < X[j]){ //将较小值拷贝到Y中 Y[k++] = X[i++]; }else{ Y[k++] = X[j++]; } } //将前一个子序列剩余元素拷贝到Y中 while(i<r){ Y[k++] = X[i++]; } //将后一个子序列剩余元素拷贝到Y中 while(j<r+n && j<X.length){ Y[k++] = X[j++]; } } //对子序列的操作 private static void mergepass(int[] X, int[] Y, int n){ int i = 0; while(i < X.length-n*2+1){ merge(X, Y, i, i+n, n); i += 2*n; } //对于剩余不够2n的子序列的操作 if(i+n < X.length){ //虽然后一个子序列长度不够n。 //但还是能够再来一次merge merge(X, Y, i, i+n, n); }else{ for(int j=i; j<X.length; j++){ Y[j]=X[j]; } } } //对数组的操作 public static void mergeSort(int[] X){ int[] Y = new int[X.length]; int n = 1; //一次while循环完毕两趟并归, //数据序列从X到Y,再从Y到X, //使排序后的数据序列仍在数组X中 while(n<X.length){ mergepass(X,Y,n); n*=2; mergepass(Y,X,n); n*=2; } }
基本思想:n个元素的数据序列可看成是由n个长度为1的排序子序列组成,重复讲相邻的两个子序列归并成一个排序的子序列,直到合并成一个序列,则排序完毕。
时间复杂度:最好最坏的情况都是:O(n*㏒2n)。 是稳定的。
測试方法
public static void main(String[] args) { //创建一个数组 int[] y = new int[10]; //向数组赋值 for(int i=0; i<y.length; i++){ int a = new Random().nextInt(100); y[i] = a; } //运行排序方法 selectSort(y); //打印排序后的数组 for(int i=0; i<y.length; i++){ System.out.println(y[i]); } }
假设读者有什么更好的建议或疑问,欢迎在以下评论,一起交流进步。
以上是关于算法之七种排序的主要内容,如果未能解决你的问题,请参考以下文章