排序总结
插入排序
1.简单插入,前面排好了序,后面往前插
//时间复杂度O(n^2),稳定,逆序的时候花费时间最长 public void InsertSort(int a[]) { int n=a.length; for(int i=1;i<n;i++) { int temp=a[i]; int j=i-1; while(j>=0&&temp<a[j]) { a[j+1]=a[j]; j--; } a[j+1]=temp; } }
2.折半插
1 //折半插入,时间复杂度不变,比较次数少了很多 2 public void InsertSort1(int a[]) { 3 int n=a.length; 4 int low,mid,high; 5 for(int i=1;i<n;i++) { 6 int temp=a[i]; 7 low=0;high=i-1; 8 while(low<=high) { 9 mid=(low+high)/2; 10 if(a[mid]>temp) 11 high=mid-1; 12 else 13 low=mid+1; 14 } 15 for(int j=i-1;j>=high+1;j--) 16 a[j+1]=a[j]; 17 a[high+1]=temp; 18 } 19 }
3.希尔排序
//希尔排序,时间复杂度O(n^1.3),不稳定 public void ShellSort(int a[]) { int n=a.length,j; int d=n/2; while(d>0) { for(int i=d;i<n;i++) { int temp=a[i]; j=i-d; while(j>=0&&temp<a[j]) { a[j+d]=a[j]; j=j-d; } a[j+d]=temp; } d/=2; } }
选择排序:
1.简单选择排序:不断的从后面找最小的
//简单选择排序,O(n^2),不稳定 public void SelectSort(int a[]) { int n=a.length; for(int i=0;i<n-1;i++) { int k=i; for(int j=i+1;j<n;j++) { if(a[j]<a[k]) k=j; } if(k!=i) { int temp=a[i]; a[i]=a[k]; a[k]=temp; } } }
2.堆排序
//堆排序,时间复杂度 O(n*log2(n),不稳定 public void HeapSort(int a[]) { int n=a.length; for(int i=(n-1)/2;i>=0;i--) { shift(a,i,n-1); }//初始化,从第一个不是单节点的位置开始 for(int i=n-1;i>0;i--) { int temp=a[i]; a[i]=a[0]; a[0]=temp; shift(a,0,i-1); } } public void shift(int a[],int low,int high) { int i=low,j=i*2+1;//j是i的左节点 int temp=a[i]; while(j<=high) { if(j<high&&a[j+1]>a[j])//右节点更大 j++; if(temp<a[j]) { a[i]=a[j]; i=j; j=i*2+1; } else break; } a[i]=temp; }
交换排序:
1.冒泡排序:
//冒泡排序,时间复杂度O(n^2),稳定 public void BubbleSort(int a[]) { int n=a.length,exchange; for(int i=0;i<n-1;i++) { exchange=0; for(int j=n-1;j>i;j--) { if(a[j]<a[j-1]) { int temp=a[j]; a[j]=a[j-1]; a[j-1]=temp; exchange=1; } } if(exchange==0) return; } }
2.快速排序
//快速排序,O(n*log2(n)),不稳定 void QuickSort(int a[],int s,int t) { int i=s,j=t; if(s<t) { int temp=a[s]; while(i!=j) { while(j>i&&temp<=a[j]) j--; a[i]=a[j]; while(j>i&&temp>=a[i]) i++; a[j]=a[i]; } a[i]=temp; QuickSort(a,s,i-1); QuickSort(a,i+1,t); } }
二路快排:
int partition(int arr[],int l,int r) { int v=arr[l]; int i=l+1,j=r; while(true) { while(arr[i]<v&&i<r) i++; while(j>=l+1&&arr[j]>v)j--; if(i>j)break; swap(arr,i,j); i++; j--; } swap(arr,l,j); return j; } void __quicksort2(int arr[],int l,int r) { if(l>=r) return ; int off=partition(arr,l,r); __quicksort2(arr,l,off-1); __quicksort2(arr,off+1,r); }
归并排序:
//归并排序,时间复杂度O(n*log2(n)),稳定 void MergeSort(int a[],int low,int high) { if(low>=high) return ; int mid=(low+high)/2; MergeSort(a,low,mid); MergeSort(a,mid+1,high); merge(a,low,mid,high); } void merge(int a[],int low,int mid,int high) { int[] temp=new int[high-low+1]; int i=low,j=mid+1,k=0;; while(i<=low&&j<=high) { if(a[i]<=a[j]) temp[k++]=a[i++]; else temp[k++]=a[j++]; while(i <= mid) temp[k++] = a[i++]; while(j <= high) temp[k++] = a[j++]; for(int m=0;m<high-low+1;m++) { a[m+low]=temp[m]; } } }
基数排序 O(d*(n+r)),稳定,d是位数,n是个数,r是基数
基数排序适用于位数比较短
具体过程就是生成基数长度个链表,根据每一位位数的大小来判断链到哪一个链表上,然后从小到大把这个r个链表链成一个链表,就完成了一次排序的过程。
一般是从个位开始比较,然后再重复上面的操作,一直到最高位。基本上是不需要比较关键字大小的一种排序方法。
桶排序:空间复杂度很高,时间复杂度O(n).待排序的数中最大的数多大,就需要多大的空间
int[] bucket_sort(int[] unsorted, int maxNumber) { int[] sorted = new int[maxNumber + 1]; for (int i = 0; i < unsorted.Length; i++) { sorted[unsorted[i]] = unsorted[i]; } return sorted; }
用桶排序解决这样一个问题:时间复杂度要求O(n)
有一个无序整型数组,如何求出该数组排序后的任意两个相邻元素的最大差值?
public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int[] a=new int[n]; int maxNum=0; for(int i=0;i<n;i++) { a[i]=sc.nextInt(); maxNum=Math.max(maxNum, a[i]); } int[] res=bucket_sort(a, maxNum); int pre=-1; int maxRes=0; for(int i=0;i<=maxNum;i++) { if(pre==-1&&res[i]!=0) { pre=i; } else if(res[i]!=0) { maxRes=Math.max(maxRes, i-pre); pre=i; } } System.out.println(maxRes); } static int[] bucket_sort(int[] unsorted, int maxNumber) { int[] sorted = new int[maxNumber + 1]; for (int i = 0; i < unsorted.length; i++) { sorted[unsorted[i]] = unsorted[i]; } return sorted; }
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10513961.html