【算法设计与分析课程笔记】并归排序和逆序数计算Merge Sort and Counting Inversions...

感觉不是计算机专业 一直做和编程相关的应用 但是没有上过那些算法的基础课会遇到越来越多的问题。在guokrMOOC学院中看到这门Stanford的算法设计和分析的课程就选了。课程下面有帖子讨论你为什么要选这门课,有很多回复都是说不是从计算机专业毕业但是做应用开发,现在觉得基础确实很重要。课程的量比较大,这里的记录就简略一些,这部分课程内容的编程题是计算一个有100000个数的序列中的逆序数对的个数。

 

并归排序(Merge Sort)是一种使用分治法(Divided-and-Conquer)思路设计的排序算法 

 

并归排序的过程

Divide 将n个元素分成两个包含n/2个元素的的子序列

Conquer 用并归排序对两个子序列进行排序

Merge 将两个已排序的子序列合并得到结果

 

并归排序每次将序列分成长度为原先一半的子序列再进行并归排序 进行logN层Divide之后只剩下长度为1或2的子序列

然后再对这些子序列进行合并就可以,所以我们只要关注Merge的过程

 

先写主体的递归循环

 1 int MergeSort(int a, int b)
 2 {
 3     if (a < b) //判定序列长度是否大于1,不判定会造成无限循环
 4     {
 5         int count = 0; 
 6         int mid = (a + b) / 2;
 7         count += MergeSort(a, mid);
 8         count += MergeSort(mid + 1, b);
 9         count += Merge(a, mid, b);
10         return count;
11     }
12     return 0;
13 }

Merge(int a, int mid,int b)是对两个子序列进行合并的函数

a 和 b分别代表序列下标的开始和结束

对于一个从A[a]到A[b]的序列 我们分割为两个子序列 A[a]到A[mid] 和A[mid+1]到A[b]

这里的返回值count为逆序数

 

接下来的写合并的函数Merge

 

 1 int Merge(int a, int mid, int b)
 2 {
 3     int count = 0;
 4     
 5     int i = a;    //i为第一个序列的索引
 6     int j = mid + 1;     //j为第一个序列的索引
 7     int k = a;     //k为合并后序列的索引
 8 
 9     while (i <= mid&& j <= b)
10     {
11         if (A[i] <= A[j])
12         {
13             T[k++] = A[i++];
14         }
15         else
16         {
17             if (A[i] >= A[j])
18             {
19                 T[k++] = A[j++];
20                 
21                 count += j - k;   //移动一个元素后消除的逆序数
22             }
23         }
24     }
25 
26         //此时两个子序列已经有一个完全被合并 把另一个序列的剩余元素合并
27     while (i<=mid)
28     {
29         T[k++] = A[i++];
30     }
31     while (j <= b)
32     {
33         T[k++] = A[j++];
34     }
35         //将合并后的数组复制到原数组
36     for (int i = a; i <= b; i++)
37     {
38         A[i] = T[i];
39     }
40 
41     return count;//返回此次合并的逆序数
42 }        

 

在并归排序中进行逆序数的计算是逼直接计算逆序数的效率高的 并归排序的时间复杂度是O(n*log(n)) 直接计算是O(n^2)

移动一个元素后消除的逆序数为j - k还是要画图理解一下

 

转载于:https://www.cnblogs.com/yemiyemi/p/4262749.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值