快排与归并模板

285 阅读2分钟

一道排序题目,数据范围是关键,如果数据范围过大,只能采用O(nlogn)的算法,显然我们可以选择快速排序,归并排序等算法,下面是我整理的快排模板。首先简单展示快排的思想:

2.gif

随机选择好基准值(一般是中间的值或两端的值),采用类似于双指针算法的思想,从两端向中间移动,逐次遍历数组中的值,大于基准值的放在右侧,小于等于基准值的放在左侧。每次确定一个元素的最终位置,这样整个问题的规模缩小为原来的一半。之后仍采用这种方式将问题规模不断缩小,直到所有元素的位置确定。

/**
快排模板
*/
import java.util.*;
import java.io.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n = sc.nextInt();
        int arr[]=new int[n];
        for(int i=0;i<n;i++){
            arr[i]=sc.nextInt();
        }
        quicksort(arr,0,arr.length-1);
        for(int i=0;i<n;i++){
            System.out.print(arr[i]+" ");
        }
    }
    public static void quicksort(int arr[],int l,int r){
        if (l>=r)return;
        int mid=arr[l+r>>1];
        int i=l-1,j=r+1;//这里分别将边界向外扩展一个位置,为了基准值恰好在边界上,进入死循环
        while(i<j){
            do {
            i++;
        }while (arr[i]<mid);

        do{
            j--;
        }while (arr[j]>mid);
        if (i<j){
            int temp=arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
        }
        }
        
        quicksort(arr,l,j);
        quicksort(arr,j+1,r);
    }
}

下面是归并模板,归并排序,它有两大核心操作. 一个是将数组一分为二,一个无序的数组成为两个数组. 另外一个操作就是,合二为一,将两个有序数组合并成为一个有序数组.

3.gif

import java.util.*;
public class Main{
    public static void main(String args[]){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int arr[]=new int[n];
        for (int i=0;i<n;i++){
            arr[i]=sc.nextInt();
        }
        MergeSort(arr,0,n-1);
        for (int i=0;i<n;i++){
            System.out.print(arr[i]+" ");
        }
    }

    public static void MergeSort(int arr[],int l,int r){
        if(l>=r)return;
        int mid=l+r>>1;
        MergeSort(arr,l,mid);
        MergeSort(arr,mid+1,r);
        Merge(arr,l,mid,r);
    }
    public static void Merge(int arr[],int l,int mid,int r){
        int len=r-l+1;
        int temp[]=new int[len];
        int p=l,q=mid+1;
        int t=0;
        while(p<=mid&&q<=r){
            if(arr[p]<arr[q]){
                temp[t++]=arr[p++];
            }else{
                temp[t++]=arr[q++];
            }
        }//合并
        
        while(p<=mid){
            temp[t++]=arr[p++];
        }
        while(q<=r){
            temp[t++]=arr[q++];
        }
        for(int i=0,j=l;j<=r;i++,j++){
            arr[j]=temp[i];
        }
    }
    
}