1. 程式人生 > >歸並排序&&歸並排序求逆序對

歸並排序&&歸並排序求逆序對

out sta 應用 ann i+1 color pri 步驟 大小

歸並排序

歸並排序(MERGE-SORT)是建立在歸並操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為二路歸並。

算法:

第一步:申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合並後的序列 第二步:設定兩個指針,最初位置分別為兩個已經排序序列的起始位置 第三步:比較兩個指針所指向的元素,選擇相對小的元素放入到合並空間,並移動指針到下一位置 重復步驟3直到某一指針超出序列尾 將另一序列剩下的所有元素直接復制到合並序列尾
 

import
java.util.*; public class Main1 { static int a[] = new int[10010]; static int b[] = new int[10010]; public static void sort(int a[], int l, int r) { if (r - l > 0) { int mid = (r + l) / 2; int i = l; int p = l; int q = mid + 1; sort(a, l, mid); sort(a, mid
+ 1, r); while (p <= mid || q <= r) {                   if (q > r || (p <= mid && a[p] <= a[q]))      //這一點是簡化代碼,包含了當後邊數組沒有比前一半大的時候 b[i++] = a[p++]; else { b[i++] = a[q++]; } }
for (i = l; i <= r; i++) a[i] = b[i]; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for (int i = 1; i <= n; i++) { a[i] = sc.nextInt(); } sort(a, 1, n); for (int i = 1; i <= n; i++) System.out.printf("%d ", a[i]); System.out.println(ans); } }

歸並排序求逆序對

求序列的逆序對,先看下面的例子:

設有數列{6,202,100,301,38,8,1}

初始狀態:6,202,100,301,38,8,1

第一次歸並後:{6,202},{100,301},{8,38},{1},比較次數:3;

第二次歸並後:{6,100,202,301},{1,8,38},比較次數:4;

第三次歸並後:{1,6,8,38,100,202,301},比較次數:4;

總的比較次數為:3+4+4=11;

逆序數為14;

根據歸並排序的特性(左右兩部分的有序序列合並時,假設i在左邊,j在右邊,對於右邊的j,統計左邊比它大的元素個數s(j),則s(j) = mid-i+1 ,合並萬所有的序列時即可得出答案,即f(j)之和便是答案),只需將上面的代碼修改一處:把“else b[i++] = a[q++];”改成“ else {b[i++] = a[q++]; ans += mid-p+1;}" ,註意在調用之前將ans清零。

package demo2;

import java.util.*;

public class Main1 {
    static int a[] = new int[10010];
    static int b[] = new int[10010];
    static int ans = 0;

    public static void sort(int a[], int l, int r) {
        if (r - l > 0) {
            int mid = (r + l) / 2;
            int i = l;
            int p = l;
            int q = mid + 1;
            sort(a, l, mid);
            sort(a, mid + 1, r);
            while (p <= mid || q <= r) {
                if (q > r || (p <= mid && a[p] <= a[q]))
                    b[i++] = a[p++];
                else {
                    b[i++] = a[q++];
                    ans += mid - p + 1;
                }
            }
            for (i = l; i <= r; i++)
                a[i] = b[i];
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            a[i] = sc.nextInt();
        }
        sort(a, 1, n);
        for (int i = 1; i <= n; i++)
            System.out.printf("%d ", a[i]);
        System.out.println(ans);
    }
}

歸並排序&&歸並排序求逆序對