通过·归并(合并)排序·求逆序对个数

题目要求:利用归并排序求得排序过程中出现逆序对的个数。如输入数组长度为5的序列,分别为9·1·0·5·4,得到逆序对的个数为6.可通过以下代码得到结果。(可是POJ不通过,这点我搞不明白,可否有高手看看代码处是否出错,不胜感谢!)

 
  
1 #include < stdio.h >
2 #include < stdlib.h >
3   #define MAX 50000
4   /* *
5   * 0 <= p <= q < r, subarray array[p..q] and array[q+1..r] are already sorted.
6   * the merge() function merges the two sub-arrays into one sorted array.
7   */
8 int count = 0 ;
9 void Merge( int array[], int p, int q, int r)
10 {
11 int i,k;
12 int begin1,end1,begin2,end2;
13 int * temp = ( int * )malloc((r - p + 1 ) * sizeof ( int ));
14 begin1 = p;
15 end1 = q;
16 begin2 = q + 1 ;
17 end2 = r;
18 k = 0 ;
19
20 while ((begin1 <= end1) && ( begin2 <= end2))
21 {
22 if (array[begin1] <= array[begin2])
23 {
24 temp[k] = array[begin1];
25 begin1 ++ ;
26
27 }
28 else
29 {
30 temp[k] = array[begin2];
31 begin2 ++ ;
32 // count++;
33 /*
34 *
35 *求逆序对,当array[begin1]中的数比array[begin2]中的数大时;
36 *那么可以推出此数后面的数和array[begin2]这个数大;
37 */
38 count += end1 + 1 - begin1;
39
40 }
41 k ++ ;
42
43 }
44
45 while (begin1 <= end1)
46 {
47 temp[k ++ ] = array[begin1 ++ ];
48
49 }
50
51 while (begin2 <= end2)
52 {
53 temp[k ++ ] = array[begin2 ++ ];
54
55 }
56
57 for (i = 0 ;i < (r - p + 1 );i ++ )
58 array[p + i] = temp[i];
59
60 free(temp);
61
62 }
63 /* *
64 归并操作
65 */
66 void MergeSort( int array[], int first, int last)
67 {
68 int mid = 0 ;
69 if (first < last)
70 {
71 mid = (first + last) / 2 ;
72 MergeSort(array,first,mid);
73 MergeSort(array,mid + 1 ,last);
74 Merge(array,first,mid,last);
75 }
76
77 }
78
79 int main()
80 {
81 int i;
82 int array[MAX];
83 int input;
84 scanf( " %d " , & input);
85 while (input != 0 )
86 {
87 for (i = 0 ;i < input;i ++ )
88 {
89 scanf( " %d " , & array[i]);
90 }
91 MergeSort(array, 0 ,input - 1 );
92 /* for(i=0;i<input;i++)
93 {
94 printf("%d ",array[i]);
95 }
96 */
97 printf( " %d\n " ,count);
98 count = 0 ;
99
100 scanf( " %d " , & input);
101 }
102
103 return 1 ;
104 }

Input:
5
9
1
0
5
4
3
1
2
3
10
2
1
6
5
7
9
11
12
3
8
2
11
11

0


Output:
   1|6
   2|0
   3|11
   4|0

以上4项测试结果没错误。(只通过这几项测试不能证明什么,真的...)

************************************************************分割线**********************************************************

 `通过分析别人的代码和老师的提示,上面的代码运行是没错的,不过当测试的数据长度在500,000数量级上时,上述代码数据溢出。

`我们通过Int64类型来定义整形数(Int64 值类型表示值介于 -9,223,372,036,854,775,808 到 +9,223,372,036,854,775,807 之间的整数。)

`实现代码如下:

 

 
  
1 #include < stdio.h >
2
3
4   /* *
5   * 0 <= p <= q < r, subarray array[p..q] and array[q+1..r] are already sorted.
6   * the merge() function merges the two sub-arrays into one sorted array.
7   */
8 __int64 count;
9 __int64 a[ 500005 ];
10 __int64 temp[ 500005 ];
11   // 防止数据溢出
12   void Merge( int p, int q, int r)
13 {
14 int i,k;
15 int begin1,end1,begin2,end2;
16 k = p;
17 begin1 = p;
18 end1 = q;
19 begin2 = q + 1 ;
20 end2 = r;
21
22
23 while ((begin1 <= end1) && ( begin2 <= end2))
24 {
25 if (a[begin1] <= a[begin2])
26 {
27 temp[k] = a[begin1];
28 begin1 ++ ;
29
30 }
31 else
32 {
33 temp[k] = a[begin2];
34 begin2 ++ ;
35 // count++;
36 /*
37 *
38 *求逆序对,当array[begin1]中的数比array[begin2]中的数大时;
39 *那么可以推出此数后面的数和array[begin2]这个数大;
40 */
41 count += end1 - begin1 + 1 ;
42
43 }
44 k ++ ;
45
46 }
47
48 while (begin1 <= end1)
49 {
50 temp[k ++ ] = a[begin1 ++ ];
51
52 }
53
54 while (begin2 <= end2)
55 {
56 temp[k ++ ] = a[begin2 ++ ];
57
58 }
59
60 for (i = p;i <= r;i ++ ) // 把合并后的数组还原
61
62 a[i] = temp[i];
63
64 }
65
66
67
68 /* *
69 归并操作
70 */
71 void MergeSort( int first, int last)
72 {
73 int mid = 0 ;
74 if (first < last)
75 {
76 mid = (first + last) / 2 ;
77 MergeSort(first,mid);
78 MergeSort(mid + 1 ,last);
79 Merge(first,mid,last);
80 }
81
82 }
83
84 int main()
85 {
86 int i;
87 int input;
88 scanf( " %d " , & input);
89 while (input != 0 )
90 {
91 count = 0 ;
92 for (i = 0 ;i < input;i ++ )
93 {
94 scanf( " %I64d " , & a[i]);
95 }
96
97 MergeSort( 0 ,input - 1 );
98
99 printf( " %I64d\n " ,count);
100
101
102
103 scanf( " %I64d " , & input);
104 }
105
106
107 return 1 ;
108 }

 

 

 

PS:上面代码的改进之处

1,使用了int64定义整数类型,使得输入的整数型能满足系统测试的数据长度。

2,提前定义了备用数组temp,而不需要像第一个代码中每次归并都要开辟一个数组空间。(有好处有坏处,在这里是好处)

3,通过把数组a和temp变为全局变量,而不需要在方法间传递数组参数。

4,到此止步,但自己还是不太完全了解归并排序中的递归过程,只是模糊的认识而已。

 

 

转载于:https://www.cnblogs.com/SCAU_que/articles/1847510.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值