交换排序
冒泡排序
void sort(int[] array){
boolean isCharge=false;
for(int i=0;i<array.length;i++){
isCharge=false;
for(int j=1;j<array.length-i;++j){
if(array[j-1]>array[j]){
swap(arr,j-1,j);
isCharge=true;
}
}
if(!isCharge){
return;
}
}
}
时间复杂度 | 空间复杂度 | 稳定性 | 适合场景 |
---|---|---|---|
O(N^2) | O(1) | 稳定 | 元素基本有序,数量较小 |
快排
递归
- 从待排序区间选择一个数,作为基准值key;
- partion: 遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基准值大的(可以包含相等的)放到基准值的右边;
- 采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度 == 1,代表已经有序,或者小区间的长度 == 0,代表没有数据。
void quickSort(int[] arr,int left,int right){
if((right-left)<16){
//其他排序方式优化
} else{
int div=partion2(arr,left,right);
quicksort(arr,left,div-1);
quicksort(arr,div+1,right);
}
}
//三数取中
int getIndexOfMiddle(int[] array,int left,int right){
int mid=left+((right-left)>>1);
if(array[left]<array[right]){
if(array[mid]<array[left]){
return left;
}else if(array[mid]>array[right]){
return right;
}else{
return mid;
}
}else{
if(array[mid]>array[left]){
return left;
}else if(array[mid]<array[right]){
return right;
}else{
return mid;
}
}
}
// hoare
int partion(int[]arr,int left,int right){
int key=right;
while(left<right){
while(left<right&&arr[left]<=arr[key]){
left++;
}
while(left<right&&arr[right]>=arr[key]){
right--;
}
if(left<right){
swap(arr,left,right);
}
}
swap(arr,key,left);
return left;
}
//挖坑法
void partion1(int[] arr,int left,int right){
int mid=getIndexOfMiddle(arr,left,right);
swap(arr,mid,left);
int key=arr[left];
while(left<right){
while(left<right&&arr[right]>key){
right--;
}
arr[left]=arr[right];
while(left<right&&arr[left]<key){
left++;
}
arr[right]=arr[left];
}
arr[left]=key;
return left;
}
int partion2(int[] arr,int left,int right){
int cur=left;
int prev=cur-1;
int key=arr[right];
while(cur<right){
if(arr[cur]<key&&++prev!=cur){
swap(arr,prev,cur);
}
++cur;
}
if(++prev!=right){
swap(arr,prev,right);
}
return prev;
}
非递归
void quicksort(int[] array){
Stack<Integer> s=new Stack<>();
s.push(array.length-1);
s.push(0);
while(!s.isEmpty()){
int left=s.pop();
int right=s.pop();
if(right-left>0){
int div=partion2(array,left,right);
s.push(right);
s.push(div+1);
s.push(div-1);
s.push(left);
}
}
}
时间复杂度 | 空间复杂度 | 稳定性 | 适合场景 |
---|---|---|---|
O(NlogN) | O(logN) | 不稳定 | 元素数量较大 |
归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
void sort(int[] arr) {
mergeSort(arr,0,arr.length-1);
}
void mergeSort(int[] arr, int start, int end) {
if(end-start>0){
int mid=start+((end-start)>>1);
mergeSort(arr,start,mid);
mergeSort(arr,mid+1,end);
merge(arr,start,mid,end);
}
}
void merge(int[] arr,int left,int mid,int right){
int[] tmp=new int[right-left+1];
int index=0;
int p1=left;
int p2=mid+1;
while(p1<=mid&&p2<=right){
if(arr[p1]<=arr[p2]){
tmp[index++]=arr[p1++];
}else{
tmp[index++]=arr[p2++];
}
}
while(p1<=mid){
tmp[index++]=arr[p1++];
}
while(p2<=right){
tmp[index++]=arr[p2++];
}
System.arraycopy(tmp,0,arr,left,tmp.length);
}
非递归
void mergeSort1(int[]arr){
int gap=1;
while(gap<arr.length){
for(int i=0;i<arr.length;i+=gap*2){
int left=i;
int right=left+gap*2-1;
int mid=left+((right-left)>>1);
if(mid>=arr.length){
mid=arr.length-1;
}
if(right>=arr.length){
right=arr.length-1;
}
merge(arr,left,mid,right);
}
gap<<=1;
}
}
时间复杂度 | 空间复杂度 | 稳定性 | 适合场景 |
---|---|---|---|
O(NlogN) | O(N) | 不稳定 | 元素数量较大 |
计数排序
void countSort(int[]array){
int min=array[0];
int max=array[0];
for(int i = 0; i <array.length ; i++) {
if(array[i]>max){
max=array[i];
}
if(array[i]<min){
min=array[i];
}
}
int range=max-min+1;
int[] arrayCount=new int[range];
for(int i = 0; i <array.length ; i++) {
arrayCount[array[i]-min]++;
}
int index=0;
for(int i = 0; i <range ; i++) {
while(arrayCount[i]!=0){
array[index++]=i+min;
arrayCount[i]--;
}
}
}