数据结构中的排序方法
- 冒泡排序
冒泡排序是排序算法中思想最简单的一种排序方法,通过比较相邻的两个数据,移动相邻数据中的较大者(后移)。第一趟在A[0]-A[n-1]中从前往后进行两个相邻元素的比较,若后者小则交换,比较n-1次;第一趟比较结束,最大的元素确定位置,下一趟则在剩下的n-1个元素中继续上述操作。举个例子:初始序列(48,36,68,72,12,48,02),第一次比较(36,48,68,72,12,48,02),第二次比较(36,48,68,72,12,48,02),第三次比较(36,48,68,72,12,48,02),第四次比较(36,48,68,12,72,48,02),第五次比较(36,48,68,12,48,72,02),第6次比较(36,48,68,12,48,02,)72。以上只是外循环的一次比较,每次内循环都两两比较。最好情况下时间复杂度为O(n),最坏情况下时间复杂度为
O(n2)。该算法的执行时间与元素的初始排列有关。冒泡排序经过一趟排序后,能确定一个元素的最终位置。冒泡排序是稳定的排序方法。代码使用JAVA实现。
public class BubbleSort { public static void bubbleSort(int[] arr){ if(arr == null ||arr.length == 0) return; for(int i = 0;i<arr.length-1;i++){ for(int j = arr.length-1;j>i;j--){ if(arr[j-1]>arr[j]){ swap(arr,j-1,j); } } } } public static void swap(int[] arr,int i,int j){ int temp = arr[j]; arr[j] = arr[i]; arr[i] = temp; } public static void main(String[] args) { // TODO Auto-generated method stub int[] a = {33,15,54,64,63}; //BubbleSort bubble= new BubbleSort(); bubbleSort(a); for(int i = 0;i<a.length;i++){ System.out.println("Sort:"+i+" a "+a[i]); } } }
2.选择排序
简单选择排序的基本思想是:将初始序列(A[0]~A[n-1])作为待排序序列,第一趟在待排序序列中找最小值元素,与该列的第一个元素A[0]交换,这样序列A[0]有序,下一趟排序在待排序子序列(A[1]~A[N-1])中进行。第i趟排序在待排序子序列(A[i]~A[n-1]中,找最小值元素,与该子序列中第一个元素A[i-1]交换。经过n-1趟排序后使得初始序列有序。简单选择排序执行时间与元素的初始排列无关。不论初始排列如何,该算法都必须执行n-1趟,每趟执行n-i-1次关键字的比较,这样总得比较次数为n(n-1)/2次。因此简单选择排序的最好、最坏、平均时间复杂度都为O(n2),经过一趟排序后该算法可以确定一个元素的最终位置。简单选择排序是不稳定的排序方法。
public class SelectSort { public static void select(int[] arr){ if(arr == null||arr.length == 0){ return; } int minIndex = 0; for(int i = 0;i<arr.length-1;i++){ minIndex = i; for(int j = arr.length-1;j>i;j--){ if(arr[j]<arr[minIndex]){ minIndex = j; } } if(i != minIndex){ swap(arr,i,minIndex); } } } public static void swap(int[] arr,int i,int j){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void main(String[] args) { // TODO Auto-generated method stub int[] a = {5,8,3,4,6}; select(a); for(int i = 0;i<a.length;i++){ System.out.println("sort"+i+" a "+a[i]); } }
3、直接插入排序
直接插入排序的思想非常简单,将序列中第一个元素作为一个有序序列,然后将剩下的n-1个元素按关键字大小依次插入该有序序列,每插入一个元素后依然保持该序列有序,经过n-1趟排序后即为有序序列。
在将一个元素插入到有序表中时,首先将其存入临时变量target中,然后从后往前查找插入位置。当target大于等于表中元素或者到了有序表的第一个元素时结束,这时就可将target存入刚后移的元素的位置了。直接插入排序法必须进行n-1趟,最好时间复杂度为O(n),最坏情况时间复杂度为O(n2)。直接插入排序法在排序结束前都不能确定任何一个元素的最终位置。因此该算法是稳定的排序算法。若将arr[j-1] > target条件改成“arr[j-1] > =target”该算法就变成不稳定的了(不稳定的算法忽略相同数值的元素在排序中的顺序)。
public class InsertSort { public static void insert(int[] arr){ if(arr == null||arr.length == 0){ return; } for(int i = 1;i<arr.length;i++){ int j = i; int target = arr[i];//已将后位的值保存进target while(j > 0 && arr[j-1] > target){ arr[j] = arr[j-1];//后移 j--; } arr[j] = target; //将保存的前面的值赋给target } } public static void main(String[] args) { // TODO Auto-generated method stub int[] a = {5,3,8,6,4}; insert(a); for(int i = 0;i<a.length;i++){ System.out.println("Sort "+i+" a "+a[i]); } } }
4.快速排序
快速排序的思想是:对任意给定的序列中某个元素R,经过一趟排序后,将原序列分割成两个子序列(RP(0),...,RP(S-1))和(RP(s+1),...,RP(n-1)),其中前一个子序列中的所有元素的关键字值均小于或等于该关键字值KP(s),后一个子序列中的所有元素的关键字值均大于关键字值KP(s),然后分别对低端序列和高端序列进行快速排序,直到子序列为空或只有一个元素为止。
当初始序列有序时,快速排序的效率最低,时间复杂度为O(n2)。平均和最好情况下,快速排序的时间复杂度度为O(nlog2n).快速排序算法是不稳定的算法。
public class QuickSort { //一次划分 public static int Partition(int[] arr,int left,int right){ int proKey = arr[left]; int proindex = left; while(left<right){ while(left<right && arr[right]>=proKey) right--; while(left<right && arr[left]<=proKey) left++; swap(arr,left,right);//把大的交换到右边,小的交换到左边 } swap(arr,proindex,left);//最后把proKey交换到中间 return left; } public static void quickSort(int[] arr,int left,int right){ if(left>=right) return; int proindex = Partition(arr,left,right); quickSort(arr,left,proindex-1); quickSort(arr,proindex+1,right); } public static void swap(int[] arr,int left,int right){ int temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; } public static void main(String[] args) { // TODO Auto-generated method stub int[] a = {33,15,54,64,63}; quickSort(a,0,a.length-1); for(int i = 0;i<a.length;i++){ System.out.println("Sort:"+i+" a "+a[i]); }
未完待续!!!!!!!!!!!!!!!!!!!