《算法导论》(一)--插入排序与合并排序

插入排序

书上说的很好,用打牌作比方。就是一边是排好序的,剩下的是待排序的,每次取一个待排序的元素,找到按序的位置,插入已排好序的部分中。元素取完也就结束了。复杂度O(n^2)。

代码:

 
  
1 #include < iostream >
2   using namespace std;
3   #define LENGTH 11
4
5   void insert_sort( int array[], int len)
6 {
7 int i,j;
8
9 for (i = 1 ;i < len;i ++ )
10 {
11 int key = array[i];
12 for (j = i - 1 ;j >= 0 && array[j] > key;j -- )
13 {
14 array[j + 1 ] = array[j];
15 }
16 array[j + 1 ] = key;
17 }
18 }
19   int main()
20 {
21 int array[LENGTH] = { 9 , 3 , 5 , 12 , 7 , 34 , 56 , 28 , 16 , 4 , 10 };
22 int i = 0 ;
23
24 for (i = 0 ;i < LENGTH;i ++ )
25 {
26 cout << array[i] << " " ;
27 }
28 cout << endl;
29
30 insert_sort(array,LENGTH); // sort
31  
32 for (i = 0 ;i < LENGTH;i ++ )
33 {
34 cout << array[i] << " " ;
35 }
36 cout << endl;
37 }

 

 

合并排序

合并排序是一种分治法,实现上用了递归结构。过程是:先将待排序的元素分为两部分,一般是对等长度的两部分,称为左右L、R,先分别将L,R进行合并排序,然后将排序好的L、R合并在一起,则所有元素都有序。复杂度O(nlgn)。

代码

 
  
1 #include < iostream >
2   using namespace std;
3   #define LENGTH 10
4
5   void merge( int array[], int start, int middle, int end)
6 {
7 int i,j,k;
8 int n1 = middle - start + 1 ,n2 = end - middle;
9 int * L = new int [n1 + 1 ], * R = new int [n2 + 1 ];
10
11 for (i = 0 ;i < n1;i ++ )
12 {
13 L[i] = array[start + i];
14 }
15 for (i = 0 ;i < n2;i ++ )
16 {
17 R[i] = array[middle + i + 1 ];
18 }
19 L[n1] = INT_MAX;
20 R[n2] = INT_MAX;
21
22 i = 0 ,j = 0 ;
23 for (k = start;k <= end;k ++ )
24 {
25 if (L[i] <= R[j])
26 {
27 array[k] = L[i];
28 i ++ ;
29 }
30 else
31 {
32 array[k] = R[j];
33 j ++ ;
34 }
35 }
36 }
37
38   void merge_sort( int array[], int start, int end)
39 {
40 int i,j;
41 if (start < end)
42 {
43 int middle = (start + end) / 2 ;
44 merge_sort(array,start,middle);
45 merge_sort(array,middle + 1 ,end);
46 merge(array,start,middle,end);
47 }
48 }
49
50   int main()
51 {
52 int i = 0 ;
53 int array[LENGTH] = { 9 , 12 , 5 , 24 , 8 , 7 , 15 , 10 , 0 , 22 };
54 for (i = 0 ;i < LENGTH;i ++ )
55 {
56 cout << array[i] << " " ;
57 }
58 cout << endl;
59
60 merge_sort(array, 0 ,LENGTH - 1 );
61
62 for (i = 0 ;i < LENGTH;i ++ )
63 {
64 cout << array[i] << " " ;
65 }
66 cout << endl;
67
68 return 0 ;
69 }

 

 

合并排序的扩展应用

对合并排序稍作一些改动,可以以O(nlgn)的复杂度实现其他功能。

思考题2.3.7

思路:

I  对集合S中的元素进行排序,选择复杂度为O(nlgn)的排序算法,这里是合并排序
II 从两头开始遍历排序后S的元素,下标分别为i、j,若S[i]+S[j]==x,返回;若S[i]+S[j]>x,j--;若S[i]+S[j]<x,i++

代码

 
  
1 #include < iostream >
2   using namespace std;
3   #define LENGTH 10
4
5   void merge( int array[], int start, int middle, int end)
6 {
7 int i,j,k;
8 int n1 = middle - start + 1 ,n2 = end - middle;
9 int * L = new int [n1 + 1 ], * R = new int [n2 + 1 ];
10
11 for (i = 0 ;i < n1;i ++ )
12 {
13 L[i] = array[start + i];
14 }
15 for (i = 0 ;i < n2;i ++ )
16 {
17 R[i] = array[middle + i + 1 ];
18 }
19 L[n1] = INT_MAX;
20 R[n2] = INT_MAX;
21
22 i = 0 ,j = 0 ;
23 for (k = start;k <= end;k ++ )
24 {
25 if (L[i] <= R[j])
26 {
27 array[k] = L[i];
28 i ++ ;
29 }
30 else
31 {
32 array[k] = R[j];
33 j ++ ;
34 }
35 }
36 }
37
38   void merge_sort( int array[], int start, int end)
39 {
40 int i,j;
41 if (start < end)
42 {
43 int middle = (start + end) / 2 ;
44 merge_sort(array,start,middle);
45 merge_sort(array,middle + 1 ,end);
46 merge(array,start,middle,end);
47 }
48 }
49
50   bool find_two_ele( int array[], int len, int x, int & x1, int & x2)
51 {
52 int i,j;
53 for (i = 0 ,j = len - 1 ;i < len;)
54 {
55 int sum = array[i] + array[j];
56 if (sum == x)
57 {
58 x1 = array[i];
59 x2 = array[j];
60 return true ;
61 }
62 else
63 if (sum > x)
64 {
65 j -- ;
66 }
67 else
68 {
69 i ++ ;
70 }
71 }
72 return false ;
73 }
74   int main()
75 {
76 int i = 0 ;
77 int array[LENGTH] = { 9 , 12 , 5 , 24 , 8 , 7 , 15 , 10 , 0 , 22 };
78
79 merge_sort(array, 0 ,LENGTH - 1 );
80
81 int x = 15 ,x1,x2;
82
83 if (find_two_ele(array,LENGTH,x,x1,x2))
84 {
85 cout << " Yes. " << x << " = " << x1 << " + " << x2 << endl;
86 } else
87 {
88 cout << " No. " << endl;
89 }
90
91 return 0 ;
92 }

练习题2-4

逆序对问题,可以在合并的时候统计有多少逆序对。

代码

 

 
  
1 /* ***************
2 逆序对问题
3 *************** */
4 #include < iostream >
5   using namespace std;
6   #define LENGTH 10
7
8   int Num = 0 ;
9
10   int merge( int array[], int start, int middle, int end)
11 {
12 int i,j,k,count = 0 ;
13 int n1 = middle - start + 1 ,n2 = end - middle;
14 int * L = new int [n1 + 1 ], * R = new int [n2 + 1 ];
15 for (i = 0 ;i < n1;i ++ )
16 {
17 L[i] = array[start + i];
18 }
19 for (i = 0 ;i < n2;i ++ )
20 {
21 R[i] = array[middle + i + 1 ];
22 }
23 L[n1] = INT_MAX,R[n2] = INT_MAX;
24
25 i = 0 ,j = 0 ;
26 for (k = start;k <= end;k ++ )
27 {
28 if (L[i] < R[j])
29 {
30 array[k] = L[i];
31 i ++ ;
32 }
33 else
34 {
35 array[k] = R[j];
36 count += middle - start - i + 1 ; // count
37   j ++ ;
38 }
39 }
40
41 return count;
42 }
43
44   int merge_sort( int array[], int start, int end)
45 {
46 if (start < end)
47 {
48 int middle = (start + end) / 2 ;
49 merge_sort(array,start,middle);
50 merge_sort(array,middle + 1 ,end);
51 Num += merge(array,start,middle,end);
52
53 return Num;
54 }
55 }
56
57   int main()
58 {
59 int array[LENGTH] = { 9 , 12 , 5 , 24 , 8 , 7 , 15 , 10 , 0 , 22 };
60
61 cout << merge_sort(array, 0 ,LENGTH - 1 ) << endl;
62
63 for ( int i = 0 ;i < LENGTH;i ++ )
64 {
65 cout << array[i] << " " ;
66 }
67 cout << endl;
68
69 return 0 ;
70 }

 

转载于:https://www.cnblogs.com/njucslzh/archive/2010/09/01/1815160.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值