排序算法:快速排序和归并排序

快排

快排模板

//快排模板
void quick_sort(int q[], int l, int r)
{
    if (l >= r) return; // 不能是==, 因为区间可能没有数

    int i = l - 1, j = r + 1, x = q[l + r >> 1]; //第12行如果用j,这一行x不能用x=q[r],会导致死循环
    while (i < j) // 注意,循环结束i=j 或者 i=j+1 !
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j); 
    quick_sort(q, j + 1, r);
}

题目1

785.快速排序 https://www.acwing.com/problem/content/787/

private static void quick_sort(int[] nums, int l, int r){
	if(l >= r) return; //判断递归结束条件 >= 
	int i=l-1, j =r+1; //给出左右指针的起始位置
	int x = nums[l]; // 指定x。(或者用 nums[l+r>>2])
	while(i < j){ //循环结束条件<
		do i++; while(nums[i] < x); //<
		do j--; while(nums[j] > x); //>
		if(i < j){ // if <
			int tmp = nums[i];
			nums[i] = nums[j];
			nums[j] = tmp;
		}
	}
	quick_sort(nums, l, j);
	quick_sort(nums, j+1, r);
}

题目2

786.第k小的数 https://www.acwing.com/problem/content/788/

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), k = sc.nextInt();
        int[] nums = new int[n];
        for(int i=0; i<n; i++)
            nums[i] = sc.nextInt();
        System.out.println(qs(nums, 0, n-1, k));
    }
    
    private static int qs(int[] nums, int l, int r, int k){
        if(l == r) //因为保证第k小的数肯定在lr中间,所以这里可以用l==r 
            return nums[l];
        int i = l-1, j = r+1;
        int x = nums[l];
        while(i<j){
            while(nums[++i] < x);
            while(nums[--j] > x);
            if(i<j){
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
        }
        if(k <= j-l+1) 
            return qs(nums, l, j, k);
        else
            return qs(nums, j+1, r, k-(j-l+1));
    }
}

归并排序

归并排序模板

int q[N], tmp[N];
void merge_sort(int q[], int l, int r)
{
    if (l >= r) return;
    int mid = l + r >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);

    int k = 0, i = l, j = mid + 1; //k指针 i左半边起点 j右半边起点
    while (i <= mid && j <= r) //i<=左半边边界 且 j<=右半边边界
        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
        else tmp[k ++ ] = q[j ++ ];

    while (i <= mid) tmp[k ++ ] = q[i ++ ];
    while (j <= r) tmp[k ++ ] = q[j ++ ];

    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}

题目1

  1. 归并排序 https://www.acwing.com/problem/content/789/
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n];
        int[] tmp = new int[n];
        for(int i=0; i<n; i++)
            nums[i] = sc.nextInt();
        merge_sort(nums,tmp, 0, n-1);
        for(int i=0; i<n; i++)
            System.out.print(nums[i]+" ");
    }
    
    private static void merge_sort(int[] nums, int[] tmp, int l, int r){
        if(l >= r) return;
        int mid = l+r >> 1;
        merge_sort(nums,tmp, l, mid); 
        merge_sort(nums,tmp, mid+1, r);
        int i = l, j=mid+1, k=0;
        while(i<=mid && j<=r){
            if(nums[i] <= nums[j]) 
                tmp[k++] = nums[i++];
            else tmp[k++] = nums[j++];
        }
        while(i<=mid) tmp[k++] = nums[i++];
        while(j<=r) tmp[k++] = nums[j++];
        for(i=l, j=0; i<=r; i++, j++) nums[i] = tmp[j];
    }
}

题目2

  1. 逆序对的数量 https://www.acwing.com/problem/content/790/
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] nums = new int[n];
        int[] tmp = new int[n];
        for(int i=0; i<n; i++)
            nums[i] = sc.nextInt();
        System.out.println(merge_sort(nums, tmp, 0, n-1));
    }
    
    private static long merge_sort(int[] nums, int[] tmp, int l, int r){
        if(l >= r) return 0; //可以是==
        int mid = l+r >>1;
        long res = 0;
        res += merge_sort(nums, tmp, l, mid);
        res += merge_sort(nums, tmp, mid+1, r);
        int i=l, j=mid+1, k=0;
        while(i<=mid && j<=r){
            if(nums[i] <= nums[j]) tmp[k++] = nums[i++];
            else{
                tmp[k++] = nums[j++];
                res += mid-i+1;
            }
        }
        while(i<=mid) tmp[k++] = nums[i++];
        while(j<=r) tmp[k++] = nums[j++];
        for(i=l, j=0; i<=r; i++, j++) nums[i] = tmp[j];
        return res;
    }
}

测试一下三级目录

测试一下四级目录

posted @ 2019-08-12 21:00  sqqq  阅读(414)  评论(0编辑  收藏  举报