歸併排序-逆序對的求解

Problem 2.4

Inversions

Let A[1.n] be an array of n distinct numbers. If i<j and A[i]>A[j]     , then the pair (i,j)    is called an inversion of A.


1. The five inversions

2,13,18,68,1 and 6,1.

2. Array with most inversions

It is the reversed array, that is n,n1,,1. It has (n1)+(n2)++1=n(n1)2 inversions.

3. Relationship with insertion sort

Insertion sort performs the body of the inner loop once for each inversion. Due to the nature of the algorithm, on each k-th iteration, if A[1..k] has m inversions with A[k], they are in A[km..k1] (since the elements before k are sorted). Thus, the inner loop needs to execute its body mtimes. This process does not introduce new inversions and each outer loop iteration resolves exactly m inversions, where m is the distance the element is "pushed towards the front of the array".

Thus, the running time is Θ(n+d), where d is the number of inversions (n comes from the outer loop).

4. Calculating inversions

We just modify merge sort (in exercise 2.3.2) to return the number of inversions:

MERGE-SORT(A, p, r):
  if p < r
      inversions = 0
      q = (p + r) / 2
      inversions += merge_sort(A, p, q)
      inversions += merge_sort(A, q + 1, r)
      inversions += merge(A, p, q, r)
      return inversions
  else
      return 0

MERGE(A, p, q, r)
  n1 = q - p + 1
  n2 = r - q
  let L[1..n₁] and R[1..n₂] be new arrays
  for i = 1 to n₁
      L[i] = A[p + i - 1]
  for j = 1 to n₂
      R[j] = A[q + j]
  i = 1
  j = 1
  for k = p to r
      if i > n₁
          A[k] = R[j]
          j = j + 1
      else if j > n₂
          A[k] = L[i]
          i = i + 1
      else if L[i] ≤ R[j]
          A[k] = L[i]
          i = i + 1
      else
          A[k] = R[j]
          j = j + 1
          inversions += n₁ - i
  return inversions

C code

#include <stdio.h>

int merge(int A[], int p, int q, int r) {
    int i, j, k, inversions = 0;

    int n1 = q - p + 1;
    int n2 = r - q;

    int L[n1];
    int R[n2];

    for (i = 0; i < n1; i++) L[i] = A[p + i];
    for (j = 0; j < n2; j++) R[j] = A[q + j + 1];

    for(i = 0, j = 0, k = p; k <= r; k++) {
        if (i == n1) {
            A[k] = R[j++];
        } else if (j == n2) {
            A[k] = L[i++];
        } else if (L[i] <= R[j]) {
            A[k] = L[i++];
        } else {
            A[k] = R[j++];
            inversions += n1 - i;
        }
    }

    return inversions;
}

int merge_sort(int A[], int p, int r) {
    if (p < r) {
        int inversions = 0;
        int q = (p + r) / 2;
        inversions += merge_sort(A, p, q);
        inversions += merge_sort(A, q + 1, r);
        inversions += merge(A, p, q, r);
        return inversions;
    } else {
        return 0;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章