归并排序及拓展

  1. 请在较短的时间内写出归并排序的程序。
  2. 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组, 求出该数组中的逆序对的总数。

1、思路:

  二叉树后序遍历的思想,即先递归排序左右子树,然后才是根节点。时间复杂度O(nlogn),空间复杂度O(n)。

《归并排序及拓展》
《归并排序及拓展》
MergeSort

 1 #include <stdio.h>
 2 #include <assert.h>
 3 
 4 void PrintArray(int* data, int length)
 5 {
 6     for (int i = 0; i < length; i++)
 7         printf("%d ", data[i]);
 8     printf("\n");
 9 }
10 
11 static int MergeArray(int* data, int left, int mid, int right)
12 {
13     int length = right - left + 1;
14     int* temp = new int[length];
15     int i = left;
16     int j = mid + 1;
17     int t = 0;
18     while (i <= mid && j <= right)
19     {
20         if (data[i] > data[j])
21             temp[t++] = data[j++];
22         else
23             temp[t++] = data[i++];
24     }
25     for (; i <= mid; i++)
26         temp[t++] = data[i];
27     for (; j <= right; j++)
28         temp[t++] = data[j];
29     for (int k = 0; k < length; k++)
30     {
31         data[left] = temp[k];
32         left++;
33     }
34     delete[] temp;
35 }
36 
37 void MergeSort(int *data, int left, int right)
38 {
39     assert(data);
40     if (left >= right)
41         return;
42     int mid = (left + right) / 2;
43     MergeSort(data, left, mid);
44     MergeSort(data, mid + 1, right);
45     MergeArray(data, left, mid, right);
46 }
47     
48 
49 int main()
50 {
51     int test[7] = {23, 13, 49, 6, 31, 19, 28};
52     PrintArray(test, 7);
53     MergeSort(test, 0, 6);
54     PrintArray(test, 7);
55 }

 

2、思路:

  参考归并排序思路,只是在合并的时候返回来,从后往前比较,当左边的数大于右边的数,则计数往上加(右边递归结束是排完序的,所以说右边之前的数都要小于该数)。

《归并排序及拓展》
《归并排序及拓展》
InversePairs

 1 #include <stdio.h>
 2 #include <assert.h>
 3 
 4 void PrintArray(int* data, int length)
 5 {
 6     for (int i = 0; i < length; i++)
 7         printf("%d ", data[i]);
 8     printf("\n");
 9 }
10 
11 static int MergePairs(int* data, int left, int mid, int right)
12 {
13     int length = right - left + 1;
14     int* temp = new int[length];
15     int i = mid;
16     int j = right;
17     int t = length - 1;
18     int count = 0;
19     while (i >= left && j >= mid + 1)
20     {
21         if (data[i] > data[j])
22         {
23             temp[t--] = data[i--];
24             count += j - mid;
25         }
26         else
27             temp[t--] = data[j--];
28     }
29     
30     for (; i >= left; i--)
31         temp[t--] = data[i];
32     for (; j >= mid + 1; j--)
33         temp[t--] = data[j];
34     for (int k = 0; k < length; k++)
35         data[left++] = temp[k];
36     delete[] temp;
37     return count;
38 }
39 
40 int InversePairs(int* data, int left, int right)
41 {
42     assert(data);
43     if (left >= right)
44         return 0;
45     int mid = (left + right) / 2;
46     int lc = InversePairs(data, left, mid);
47     int rc = InversePairs(data, mid + 1, right);
48     int mc = MergePairs(data, left, mid, right);
49     return lc + rc + mc;
50 }
51 
52 int main()
53 {
54     int test[4] = {5, 6, 4, 3};
55     PrintArray(test, 4);
56     int result = InversePairs(test, 0, 3);
57     PrintArray(test, 4);
58     printf("%d\n", result);
59 }

 

 3、思路:

  参考:http://zhedahht.blog.163.com/

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/wangpengjie/archive/2013/03/30/2990859.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞