歸並排序&&歸並排序求逆序對
阿新 • • 發佈:2019-03-10
out sta 應用 ann i+1 color pri 步驟 大小
歸並排序
歸並排序(MERGE-SORT)是建立在歸並操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為二路歸並。
算法:
第一步:申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合並後的序列 第二步:設定兩個指針,最初位置分別為兩個已經排序序列的起始位置 第三步:比較兩個指針所指向的元素,選擇相對小的元素放入到合並空間,並移動指針到下一位置 重復步驟3直到某一指針超出序列尾 將另一序列剩下的所有元素直接復制到合並序列尾importjava.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); } }
歸並排序&&歸並排序求逆序對