题目链接:https://www.luogu.com.cn/problem/P1177
输入模板:
5
4 2 4 5 1
快速排序
技巧:交换数组中的两个位置
a[l] = a[l] + a[r] - (a[r] = a[l]);
稳定不稳定?:不稳定
注意找哨兵那里内循环的等于号不能漏,不然能出不来循环了,因为如果数值都一样,那么l和r一直保持不变了
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] a = new int[1000005];for(int i = 1; i<= n;i++)a[i] = scanner.nextInt();scanner.close();quickSort(a,1,n);for(int i=1;i<=n;i++){if(i==1) System.out.print(a[i]);elseSystem.out.print(" "+a[i]);}return ;}//数组的传递时通过引用进行传递的public static void quickSort(int[] a, int left, int right){//设置一个哨兵,分治排序,使得小于哨兵的所有节点都小于他,大于哨兵的所有//节点都大于他if(left>=right)return ; int solder = partSort(a, left, right);quickSort(a, left, solder-1);quickSort(a, solder+1, right);return ;}public static int partSort(int[] a,int left,int right){int pivot=a[left];while(left<right) {//起初,一定要从右边指针开始,因为arr[low]的值已经扔给了pivot,arr[low]//想象成无数字的空位while(left<right&&pivot<=a[right])--right;//把比pivot的小的数扔到左边指针//把arr[high]扔到arr[low]这个空位上//然后,high位置可以想象成无数字的空位a[left]=a[right];while(left<right&&a[left]<=pivot)++left;//把比pivot大的数扔到右边//把arr[low]扔到arr[high]这个空位上//然后,low位置可以想象成是无数字的空位a[right]=a[left];}//此时low==high,return high也一样a[left]=pivot;return left;}
}
归并排序
归并比快排好写
import java.util.*;public class Main {public static void main(String[] args) {//手写一个快排,分治排序Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] array = new int[n];for(int i = 0;i<=n-1;i++)array[i] = scanner.nextInt();QuickSort(array,0,n-1);for(int x:array)System.out.print(x+" ");}public static void QuickSort(int[] array,int left, int right){//System.out.println(left+" "+right);if(left>=right)return ;else{int mid = (left+right)/2;QuickSort(array, left, mid);QuickSort(array, mid+1, right);MergeArray(array,left,right,mid+1);}return ;}public static void MergeArray(int[] array,int left,int right,int mid){int[] temp = new int[array.length];int p = left,q = mid;for(int i=left;i<=right;i++){if(q>right||p<mid&&array[p]<array[q]){temp[i]=array[p];p++;}else{temp[i]=array[q];q++;}}for(int i=left;i<=right;i++){array[i] = temp[i];}return ;}
}
通过对比归并排序和快速排序,我们可以发现,归并排序和快速排序的区别在于
//快速排序
int solder = partSort(array, left, right);
QuickSort(array, left, solder-1);
QuickSort(array, solder+1, right);
//归并排序
QuickSort(array, left, mid);
QuickSort(array, mid+1, right);
MergeArray(array,left,right,mid+1);
一个的QuickSort在两次递归之前,一个在两次递归之后,因为归并是先拆后再合并,而快速排序我们需要知道哨兵的位置,所以需要先进行局部排序找到哨兵。