排序 O(nlogn)

1.

堆排序是一种优秀的排序算法,时间复杂度O(nlogn),主要思想是用数组构造一个最大堆,满足跟节点的value>子节点的value,然后将堆顶元素(value最大)与最后一个叶子节点交换,再调整堆,使其满足最大堆的性质,重复上述步骤n-1次后就得到一个有序序列。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define MAX 111111
 5 #define LEFT(i) (i << 1)
 6 #define RIGHT(i) (i << 1|1)
 7 using namespace std; 
 8 int a[MAX], Heap_Size, a_Length; 
 9 void Max_Heapify(int i){
10     int largest, l, r; 
11     l = LEFT(i); 
12     r = RIGHT(i); 
13     if(l <= Heap_Size && a[l] > a[i]) largest = l; 
14     else largest = i; 
15     if(r <= Heap_Size && a[r] > a[largest]) largest = r; 
16     if(largest != i){
17         int temp = a[i]; 
18         a[i] = a[largest]; 
19         a[largest] = temp; 
20         Max_Heapify(largest); 
21     }
22     return; 
23 }
24 void Build_Heap(){
25     for(int i = a_Length/2; i >= 1; i --)
26         Max_Heapify(i); 
27     return; 
28 }
29 void Heap_Sort(){
30     Build_Heap(); 
31     for(int i = a_Length; i >= 2; i --){
32         int temp = a[1]; 
33         a[1] = a[i]; 
34         a[i] = temp; 
35         Heap_Size--; 
36         Max_Heapify(1); 
37     }
38     return ; 
39 }
40 int main(){
41     freopen("data.cpp", "r", stdin); 
42     freopen("out.cpp", "w", stdout); 
43     while(~scanf("%d", &a_Length)){
44         Heap_Size = a_Length; 
45         for(int i = 1; i <= a_Length; i ++) scanf("%d", a+i); 
46         Heap_Sort(); 
47         printf("Length = %d\n", a_Length); 
48         for(int i = 1; i < a_Length; i ++) printf("%d ", a[i]); 
49         printf("%d\n\n\n", a[a_Length]); 
50     }
51     return 0; 
52 }

 

2.

快速排序:主要思想就是随机选定一个数x,以该数为基准,将数组划分,左边都小于或等于它,右边都大于它,这样就将数组划分成左右两部分,而数x则是处于正确位置,然后再重复上述过程分别处理左右部分,直到数组有序。时间复杂度O(nlogn).

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #define MAX 111111
 6 using namespace std; 
 7 int a[MAX], a_length; 
 8 int Rand_Partition(int p, int r){
 9     int x = a[r], i = p-1; 
10     for(int j = p; j < r; j ++){
11         if(a[j] <= x){
12             i ++; 
13             int temp = a[i]; 
14             a[i] = a[j]; 
15             a[j] = temp; 
16         }
17     }
18     a[r] = a[i+1]; 
19     a[i+1] = x; 
20     return i+1; 
21 }
22 void Qucik_Sort(int p, int r){
23     if(p < r){                //与调用Rand_Partition()函数效果一样;
24         int i = p-1; 
25         for(int j = p; j < r; j ++){
26             if(a[j] <= a[r]){
27                 i ++; 
28                 swap(a[i], a[j]); 
29             }
30         }
31         swap(a[r], a[i+1]); 
32         int q = i+1;             //end;
33         /* int q = Rand_Partition(p, r); */  
34         Qucik_Sort(p, q-1); 
35         Qucik_Sort(q+1, r); 
36     }
37 }
38 int main(){
39     freopen("data.cpp", "r", stdin); 
40     freopen("Quick_sort_out.cpp", "w", stdout); 
41     while(~scanf("%d", &a_length)){
42         printf("Length = %d\n", a_length); 
43         for(int i = 0; i < a_length; i ++) scanf("%d", a+i); 
44         Qucik_Sort(0, a_length-1); 
45         for(int i = 0; i < a_length-1; i ++) printf("%d ", a[i]); 
46         printf("%d\n\n\n", a[a_length-1]); 
47     }
48     return 0; 
49 }

 

3.

归并排序,采用分治策略,主要思想是假定数组a和b已经是有序的,那么可以在O(n)的时间内将他们合并成一个有序序列,现在将数组平均分成两部分,但这两部分并不是有序的,因此需要再次将这两个部分再分,使问题规模逐渐变小,继续递归划分,当子数组足够小时(即只有一个元素),可以直接求解,因为此时一个元素就是有序的。然后就可以合并这两个部分了,合并完之后就形成一个局部有序序列(我们最终要得到整个有序序列),此时向上回溯与其他有序部分进行合并,当回溯到跟节点时,整个序列就合并完毕,因此得到一个有序序列。

分治策略一般分为三步:(1):分解原问题使问题规模变小以便我们直接处理,对于上述问题就是将原序列分解,当分解到子序列只有一个元素时就可直接求解(因为一个元素的序列已经是有序的了);(2)治,即解决问题;(3)合并,将子问题解决之后要向上合并从而得到原问题的解。

分治策略一般使用递归来实现。

 1 #include<stdio.h>
 2 #include<string.h>
 3 int a[1000005]; 
 4 int l[100005]; 
 5 int r[100005]; 
 6 void merge(int p, int mid, int q)
 7 {
 8     int nl = mid - p + 1; 
 9     int nr = q - mid; 
10     int i, j, k; 
11     for(i = 0; i < nl; i ++)
12         l[i] = a[p+i]; 
13     for(i = 1; i <= nr; i ++)
14         r[i - 1] = a[mid+i]; 
15     l[nl] = 1 << 30; 
16     r[nr] = 1 << 30; 
17     i = 0; 
18     j = 0; 
19     for(k = p; k <= q; k ++)
20     {
21         if(l[i] <= r[j])
22             a[k] = l[i++]; 
23         else
24             a[k] = r[j++]; 
25     }
26 }
27 
28 void merge_sort(int l, int r)
29 {
30     if(l < r)
31     {
32         int mid = (l + r) >> 1; 
33         merge_sort(l, mid); 
34         merge_sort(mid + 1, r); 
35         merge(l, mid, r); 
36     }
37 }
38 
39 int main(int argc, char const *argv[]) 
40 {
41     int n, i; 
42     freopen("data.cpp", "r", stdin); 
43     freopen("Merge_out.cpp", "w", stdout); 
44     while(~scanf("%d", &n))
45     {
46         printf("Length = %d\n", n); 
47         for(i = 0; i < n; i ++)
48             scanf("%d", &a[i]); 
49         merge_sort(0, n-1); 
50         for(i = 0; i < n-1; i ++)
51             printf("%d ",a[i]);
52         printf("%d\n\n\n", a[i]); 
53     }
54     return 0; 
55 }

 4.

最后一个是用二叉搜索树通过中序遍历得到的有序序列,时间复杂度也是O(nlogn)较简单和容易理解。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<stack>
 5 using namespace std; 
 6 typedef struct Node{
 7     int key; 
 8     Node *left; 
 9     Node *right; 
10     Node(){
11         left = NULL; 
12         right = NULL; 
13     }
14 }Node; 
15 Node *root; 
16 stack<Node*>s; 
17 void Insert(int key){
18     Node *tmp = new Node(); 
19     tmp->key = key; 
20     Node *ff = root;
21     Node *flag = NULL; 
22     while(ff){
23         flag = ff; 
24         if(key <= ff->key) ff = ff->left; 
25         else ff = ff->right; 
26     }
27     if(flag == NULL){
28         root = new Node(); 
29         root->key = key; 
30         return; 
31     }
32     if(flag->key >= key) flag->left = tmp; 
33     else flag->right = tmp; 
34 }
35 
36 void Visist_Treee_1(Node *tmp){
37     if(tmp){
38         Visist_Treee_1(tmp->left); 
39         printf("%d ", tmp->key); 
40         Visist_Treee_1(tmp->right); 
41     }
42 }
43 
44 /* void Visist_Treee_2(Node *tmp){ */
45 /*     while(!s.empty()) s.pop(); */ 
46 /*     s.push(tmp); */ 
47 /*     while(!s.empty()){ */
48 /*         Node *p = s.top(); */ 
49 /*         s.pop(); */ 
50 /*         while(p->left) s.push(p), p = p->left; */ 
51 /*         Node *q = s.top(); */ 
52 /*         s.pop(); */ 
53 /*         printf("%d ", q->key); */ 
54 /*         if(q->right) s.push(q); */ 
55 /*     } */
56 /* } */
57 
58 int main(){
59     int n, temp; 
60     freopen("data.cpp", "r", stdin); 
61     freopen("Binary_Tree_out.cpp", "w", stdout); 
62     while(~scanf("%d", &n)){
63         root = NULL; 
64         printf("Length = %d\n", n); 
65         for(int i = 0; i < n; i ++){
66             scanf("%d", &temp); 
67             Insert(temp); 
68         }
69         Visist_Treee_1(root); 
70         printf("\n\n\n"); 
71         /* Visist_Treee_2(root); */ 
72     }
73 }

 

posted on 2014-04-02 23:22  ~Love()  阅读(241)  评论(0编辑  收藏  举报

导航