Java经典面试题——手写快速排序和归并排序

题目链接: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]);
            else
                System.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在两次递归之前,一个在两次递归之后,因为归并是先拆后再合并,而快速排序我们需要知道哨兵的位置,所以需要先进行局部排序找到哨兵。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值