排序 之 快排、歸並、插入 - <時間復雜度>----掌握思想和過程


 

  俗話說天下武功無堅不破,唯快不破。對於算法當然也是要使用時間最短、占用空間最小的算法來實現了。

  注意:我代碼里面打的備注僅供參考,建議不要背模板(因為沒有固定的模板),可以寫一個數列按着代碼跑兩圈或者把代碼改一下輸出每次排序后的結果。

 總之,師傅領進門,修行在個人。奮斗把!騷年!

 

冒泡排序、選擇排序:(不穩定,時間復雜度 O(n^2))

 1 #include "cstdio"
 2 #include "iostream"
 3 using namespace std;
 4 
 5 void bubble_sort (int *a, int n) {
 6     int t;
 7     for (int i = 0; i < n - 1; ++i) {
 8         for (int j = 0; j < n - i - 1; ++j) {
 9             if (a[j] > a[j + 1]) {
10                 t = a[j];
11                 a[j] = a[j + 1];
12                 a[j + 1] = t;
13             }
14         }
15     }
16 }
17 
18 int main () {
19     int n, a[999];
20     cin >> n;
21     for (int i = 0; i < n; ++i)
22         cin >> a[i];
23     bubble_sort (a, n);
24     for (int i = 0; i < n; ++i)
25         cout << a[i] << " ";
26     cout << endl;
27     return 0;
28 }
bubble sort
 1 #include "cstdio"
 2 #include "iostream"
 3 using namespace std;
 4 
 5 void selection_sort (int *a, int n) {
 6     int t;
 7     for (int i = 0; i < n; ++i) {
 8         for (int j = i; j < n; ++j) {
 9             if (a[i] > a[j]) {
10                 t = a[j];
11                 a[j] = a[i];
12                 a[i] = t;
13             }
14         }
15     }
16 }
17 
18 int main () {
19     int n, a[999];
20     cin >> n;
21     for (int i = 0; i < n; ++i)
22         cin >> a[i];
23     selection_sort (a, n);
24     for (int i = 0; i < n; ++i)
25         cout << a[i] << " ";
26     cout << endl;
27     return 0;
28 }
selection sort

  如果說冒泡和選擇排序都沒有弄明白的話,那你對於排序可以只記個C++STL中的sort函數和頭文件就行了。

  #include <algorithm>

  sort (要排序數組的首地址, 要排序一共的個數);

  //  默認是升序,如果想要降序的話,寫一個compare函數   bool compare(int a, int b) { return a > b;}

  // a < b;升序   a > b;降序

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int cmp(int a, int b) {
 6     return a > b;
 7 }
 8 
 9 int main () {
10     int a[] = {1, 2, 3, 2, 1};
11     // sort (a, a+5, [](int a, int b){return a > b;});
12     // 這是閉包的格式, 適合函數體較短的時候使用。
13     
14     sort (a, a+5, cmp);
15     
16     for (int i = 0; i < 5; ++i) {
17         cout << a[i] << " ";
18     }
19     cout << endl;
20     return 0;
21 }
C++ STL sort

   sort排結構體(可以使用pair更方便)

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 struct node {
 7     int x, y;
 8 }t[10];
 9 
10 bool cmp (const node a, const node b) {
11     if (a.x > b.x) {
12         return 1;
13     } else if (a.x==b.x && a.y<b.y) {
14         return 1;
15     } else {
16         return 0;
17     }
18 }
19 
20 int main () {
21     t[0].x = 1;
22     t[0].y = 2;
23     
24     t[1].x = 1;
25     t[1].y = 1;
26     
27     t[2].x = 1;
28     t[2].y = 3;
29     
30     t[3].x = 2;
31     t[3].y = 3;
32     
33     t[4].x = 3;
34     t[4].y = 2;
35     
36     t[5].x = 2;
37     t[5].y = 1;
38     
39     sort (t, t+5, cmp);
40     for (int i = 0; i < 6; ++i) {
41         cout << t[i].x <<  ' ' << t[i].y << endl;
42     }
43     return 0;
44 }
45 
46 
47 
48 
49 /*
50 3 2
51 2 3
52 1 1
53 1 2
54 1 3
55 2 1
56 */
sort排結構體數組

 

基礎快排1----選擇左右兩邊為基准排序:(不穩定,時間復雜度 最理想 O(nlogn) 最差時間O(n^2))

 1 #include <bits/stdc++.h>//萬能頭文件
 2 using namespace std;
 3 
 4 void quick_sort (int a[], int l, int r) {
 5     if (l >= r) return ;
 6     int i = l, j = r;
 7     int key = a[l];
 8     while (i < j) {    ///這里不能帶等號,,死循環
 9         while (i < j && a[j] >= key) {//<=是找有相同數字的時候
10             j --;    //選的左邊作為key,所以就從右邊開始.
11         }
12         a[i] = a[j];    //找到一個該交換的時候退出交換。
13         while (i < j && a[i] <= key) { //<=是找有相同數字的時候
14             i ++;
15         }
16         a[j] = a[i];    //同上
17     }
18     a[i] = key;
19     quick_sort (a, l, i - 1);////應該可以交換位置,因為這兩個是等效的,
20     quick_sort (a, i + 1, r);////就是排序上次key兩的的值
21 }
22 
23 int main () {
24     int n;
25     int a[999];
26     scanf ("%d", &n);
27     for (int i = 0; i < n; ++i)
28     {
29         scanf ("%d", &a[i]);
30     }
31     quick_sort (a, 0, n - 1);
32     for (int i = 0; i < n; ++i)
33     {
34         printf("%d ", a[i]);
35     }
36     printf("\n");
37     return 0;
38 }
Quick_sort_by_left
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 void quick_sort (int a[], int l, int r) {
 5     if (l >= r) return ;
 6     int i = l, j = r;
 7     int key = a[r];
 8     while (i < j) {    ///這里不能帶等號,,死循環
 9         while (i < j && a[i] <= key) {//<=是找有相同數字的時候
10             i ++;    //選的右邊作為key,所以就從左邊開始.
11         }
12         a[j] = a[i];    //找到一個該交換的時候退出交換。
13         while (i < j && a[j] >= key) { //<=是找有相同數字的時候
14             j --;
15         }
16         a[i] = a[j];    //同上
17     }
18     a[j] = key;//-----先替換的a[j],所以在這里補上.
19     quick_sort (a, l, i - 1);////可以交換位置,是等效的
20     quick_sort (a, i + 1, r);////就是排序上次key兩的的值
21 }
22 
23 int main () {
24     int n;
25     int a[999];
26     scanf ("%d", &n);
27     for (int i = 0; i < n; ++i)
28     {
29         scanf ("%d", &a[i]);
30     }
31     quick_sort (a, 0, n - 1);
32     for (int i = 0; i < n; ++i)
33     {
34         printf("%d ", a[i]);
35     }
36     printf("\n");
37     return 0;
38 }
Quick_sort_by_right

  注意:快排函數最后遞歸的時候可以按j也可以按i,因為最后滿足 i == j; 理解代碼里面等號的取舍!

 

基礎快排2----選擇任意數字為基准排序:(不穩定,時間復雜度 最理想 O(nlogn) 最差時間O(n^2))

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 
 5 void quick_sort (int *a, int l, int r) {
 6     int i = l, j = r, key = a[l + (r - l) / 2];
 7     //int key = a[r]; 
 8     //從數列里面任意找一個key就行
 9     int t;
10     while (i < j) {
11         while (i < r && a[i] < key)    i ++;
12         //不能寫成a[i] <= key,會跳過一些數字,導致不能排序
13         while (j > l && a[j] > key)    j --;
14         //這兩個while可以交換位置,以左右為基准的快排不能交換
15         if (i <= j) {
16             t = a[i];
17             a[i] = a[j];
18             a[j] = t;
19 
20             i ++;
21             j --;
22         }
23     }
24     if (i < r)    quick_sort (a, i, r);
25     if (j > l)    quick_sort (a, l, j);
26 }
27 
28 int main () {
29     int n;
30     int a[999];
31     cin >> n;
32     for (int i = 0; i < n; ++i)
33         cin >> a[i];
34     quick_sort (a, 0, n - 1);
35     for (int i = 0; i < n; ++i)
36         cout << a[i] << " ";
37     cout << endl;
38     return 0;
39 }
40 
41 Quick_sort_anyone
Quick_sort_by_anyone

   簡述:快速排序是對冒泡排序的一種本質改進。它的基本思想是通過一趟掃描后,使得排序序列的長度能大幅度地減少。在冒泡排序中,一次掃描只能確保最大數值的數移到正確位置,而待排序序列的長度可能只減少1。快速排序通過一趟掃描,就能確保某個數(以它為基准點吧)的左邊各數都比它小,右邊各數都比它大。然后又用同樣的方法處理它左右兩邊的數,直到基准點的左右只有一個元素為止。

***另外一種快排的寫法(從藍橋杯上學習到的,思想都是一樣的,只是實現有點不一樣)

 1 #include <stdio.h>
 2 
 3 void swap(int a[], int i, int j)
 4 {
 5     int t = a[i];
 6     a[i] = a[j];
 7     a[j] = t;
 8 }
 9 
10 int partition(int a[], int p, int r)
11 {
12     int i = p;
13     int j = r + 1;
14     int x = a[p];
15     while(1){
16         while(i<r && a[++i]<x);
17         while(a[--j]>x);
18         if(i>=j) break;
19         swap(a,i,j);
20     }
21     swap(a, p, j);
22     return j;
23 }
24 
25 void quicksort(int a[], int p, int r)
26 {
27     if(p<r){
28         int q = partition(a,p,r);
29         quicksort(a,p,q-1);
30         quicksort(a,q+1,r);
31     }
32 }
33     
34 int main()
35 {
36     int i;
37     int a[] = {5,13,6,24,2,8,19,27,6,12,1,17};
38     int N = 12;
39     
40     quicksort(a, 0, N-1);
41     
42     for(i=0; i<N; i++) printf("%d ", a[i]);
43     printf("\n");
44     
45     return 0;
46 }
藍橋杯 

 

基礎快排3----調用stdlib.h中的qsort函數。

  語法:

  #include <stdlib.h>

  void qsort( void *buf, size_t num, size_t size, int (*compare)(const void *, const void *) );

  buf: 要排序片段的首地址。

  num: 要排序片段的個數。

  size:要排序元素占的字節,可以使用sizeof來求。

  compare:如果函數compare 的第一個參數小於第二個參數,返回負值(升序);如果等於返回零值(不變);如果大於返回正值(降序)(函數參數必須為const void *類型)

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int cmp(const void *a, const void *b) {
 5     return *(char*)a - *(char*)b;
 6     // 如果數組是int類型的話,這里的char就是用int
 7     // 下面對應sizeof(int).
 8 }
 9 
10 int main() {
11     char b[] = {"12321"};
12     qsort(b, 5, sizeof(char), cmp);
13     printf("%c", b[0]);
14     for(int i = 1; i < 5; i++)
15         printf(" %c", b[i]);
16     printf("\n");
17     return 0;
18 }
Qsort

 

歸並排序:(穩定,時間復雜度 O(nlog n))

 1 #include <stdio.h>//歸並排序
 2 #include <stdlib.h>
 3 void merge(int a[],int b[], int f, int mid, int e)
 4 {//合並兩個數組
 5     int i = f, j = mid + 1, k = f;
 6     while(i <= mid && j <= e)//注意銜接
 7     {
 8         if(a[i] >= a[j])    //誰大就不把誰裝到前面
 9             b[k++] = a[j++];
10         else
11             b[k++] = a[i++];
12     }
13     while(i <= mid)//前半個有剩余
14         b[k++] = a[i++];
15     while(j <= e)//后半個有剩余
16         b[k++] = a[j++];
17     for(i = f; i <= e; i++)    //最后再還給a
18         a[i] = b[i];
19 }
20 void mergesort(int a[], int b[], int f, int e)//內部使用遞歸
21 {
22     if(f < e)
23     {
24         int mid = (e + f) / 2;
25         mergesort(a, b, f, mid);    //拆分到很小很小
26         mergesort(a, b, mid + 1, e);
27         merge(a, b, f, mid, e);
28     }
29 }
30 int main(){
31     int n;
32     int a[999];
33     int i, b[999];
34     scanf ("%d", &n);
35     for (int i = 0; i < n; ++i)
36         scanf ("%d", &a[i]);
37     mergesort(a, b, 0, n - 1);
38     for(i = 0; i < n; i++)
39         printf("%d ", a[i]);
40     printf("\n");
41     return 0;
42 }
Order_by_merging

 簡述:將數組拆分為兩組,對於一個數組來說,兩個數組要好排的多...依次類推,當分到只要一個元素的時候,我們就認為是有序的,然后再挨個合並相鄰的數組。我們可以先遞歸分解,然后再歸並排序。

 

插入排序:

 1 /*
 2  *   > File Name: test.cpp
 3  *   > Author: Ddlm2wxm
 4  *   > Mail: Ddlm2wxm@163.com 
 5  *   > Created Time: 2016年10月20日 星期四 07時35分53秒
 6  *********************************************************/
 7 
 8 #include <iostream>
 9 #include <cstdio>
10 using namespace std;
11 
12 void Insert_sort (int a[], int n) {
13     int i, j;
14     for (i = 1; i < n; ++i) {
15         int t = a[i];
16         for (j = i-1; j >= 0&&t<a[j]; --j)
17             a[j+1] = a[j];
18         a[j+1] = t;
19     }
20 }
21 
22 int main() {
23     int n;
24     int a[999];
25     cin >> n;
26     for (int i = 0;i < n; ++i) {
27         cin >> a[i];
28     }
29     Insert_sort (a, n);
30     for (int i =0;i < n; ++i) {
31         cout << a[i] << " ";
32     }
33     cout << endl;
34     return 0;
35 }
Insert_sort

簡述:個人認為插入排序是最簡單的,就是從第一個開始,認為第一個數是有序的,然后依次取后面的數字,通過遍歷前面的排序好了的數組尋找取到元素的位置。

 

 歡迎碼友評論,一起成長。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com