每組每一個位置的數與它後面的數比較,前面數大於後面的數就交換數值,交換n-1組。c++
每次每組交換的時候,都會把最大的排到後面去,就相似與在水底泡泡慢慢的向上浮出。算法
穩定。數組
#include<stdio.h> int main() { int a[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }; //爲了方便你們理解,我將數值設爲與動圖同樣的數值。 int n = 15; //冒泡排序 for(int i=0;i<n-1;i++)//表明的是要作多少組比對,爲何是n-1呢? //由於計數從0開始並且第一個數和自身沒有比對的必要性。 for(int j=0;j<n-1-i;j++) //表明組裏面的序號,由於要與後面數作比較,而最後一個數沒有與之比較的(可能會越界)因此n-1 //爲何還要-i呢? //由於每排過一遍,這一組最大值就排到後面去了,也就不必再去比較了。 if (a[j] > a[j + 1]) { int temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } for (int i = 0;i < n;i++) printf("%d ", a[i]); return 0; }
設置兩重循環,第一重循環作爲比較的基準,第二重循環找它後面比它小的數,而後與之交換。函數
就是選擇一個它後面的全部比他小的數中的最小的數進行交換,冒泡排序是固定後面的數,而選擇排序是固定前面的數。ui
移動數據的次數已知(n-1 次)。spa
#include<stdio.h> int main() { int a[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }; //爲了方便你們理解,我將數值設爲與動圖同樣的數值。 int n = 15; //選擇排序 for (int i = 0;i < n - 1;i++) // 表明的是要作基數數值的下標,爲何是n - 1呢? //由於計數從0開始並且最後一個數沒得數和它進行比較了。 { int k = i; for (int j = i + 1;j < n;j++)//找到比基數小的數中的最小數的下標 if (a[k] > a[j]) k = j; if (k != i) { int temp = a[k]; a[k] = a[i]; a[i] = temp; } } for (int i = 0;i < n;i++) printf("%d ", a[i]); return 0; }
從第二個數開始,將數字抽出來與前面的數依次比較,大於它的通通向後移動一格。3d
也就是將抽出來的數放到它該在的位置。指針
在大多數元素已經有序的狀況下,插入排序的工做量較小。code
#include<stdio.h> int main() { int a[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }; //爲了方便你們理解,我將數值設爲與動圖同樣的數值。 int n = 15; //選擇排序 for (int i = 1;i < n ;i++) // 表明的是要放回原位數數值的下標 { int front = i- 1;//初始化前一個數的下標 int sum = a[i];//放回原位數數值 while (front >= 0 && a[front] > sum) //防止數組越界而且前面數比後面的數大才能繼續 a[front + 1] = a[front--]; //把前面數向後移動,前一個數的下標-1,,想象動圖中空格的變化 //上個循環結束了,說明空格不能再變化了,將其賦值回去就行了 a[++front] = sum; } for (int i = 0;i < n;i++) printf("%d ", a[i]); return 0; }
可順便處理逆序對的問題。blog
這個算法用動圖充分體現了它的思想,放在下面的是輔助數組,將每部分以兩段兩段的分開進行排序,分開的排好了,再進行總的排序。
#include<stdio.h> int a[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }; //爲了方便你們理解,我將數值設爲與動圖同樣的數值。 int t[20];//輔助數組,中轉站的意思。 void merge_sort(int l, int r) { //若是兩個數組下標相鄰,就沒必要要再進行二分了,再分就只有一個了,沒法比較了。 if (r - l > 1) { int m = l + (r - l >> 1), i = l, j = m, k = l; //m爲分開的的這一段的中間下標,i爲左邊起始點,j爲右邊起始點,k爲輔助數組起始點。 //將總的一段二分。 merge_sort(l, m); merge_sort(m, r); //而後再將這兩段歸併到一塊兒進行排序。 while (i < m || j < r)//防止下標越界 //先放到輔助數組中的確定是小的,因此咱們只須要將兩邊較小的放到輔助數組中就行了。 if (j >= r || (i < m && a[i] <= a[j])) t[k++] = a[i++]; //注意下標越界問題。 else t[k++] = a[j++];//這裏處理逆序對問題。 for (i = l;i < r;i++) a[i] = t[i]; } } int main() { int n = 15; merge_sort(0, n); for (int i = 0;i < n;i++) printf("%d ", a[i]); return 0; }
#include<stdio.h> int a[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }; //爲了方便你們理解,我將數值設爲與動圖同樣的數值。 int t[20];//輔助數組,中轉站的意思。 int ans;//逆序對數量 void merge_sort(int l, int r) { //若是兩個數組下標相鄰,就沒必要要再進行二分了,再分就只有一個了,沒法比較了。 if (r - l > 1) { int m = l + (r - l >> 1), i = l, j = m, k = l; //m爲分開的的這一段的中間下標,i爲左邊起始點,j爲右邊起始點,k爲輔助數組起始點。 //將總的一段二分。 merge_sort(l, m); merge_sort(m, r); //而後再將這兩段歸併到一塊兒進行排序。 while (i < m || j < r)//防止下標越界 //先放到輔助數組中的確定是小的,因此咱們只須要將兩邊較小的放到輔助數組中就行了。 if (j >= r || (i < m && a[i] <= a[j])) t[k++] = a[i++]; //注意下標越界問題。 else t[k++] = a[j++],ans+=m-i;//這裏處理逆序對問題。 for (i = l;i < r;i++) a[i] = t[i]; } } int main() { int n = 15; merge_sort(0, n); printf("%d\n", ans); return 0; }
只要你把
else t[k++] = a[j++];成else t[k++]=a[j++],ans+=m-i;就行了,記得聲明ans變量。
逆序對的定義以下:對於數列的第 i 個和第 j 個元素,若是知足 i < j 且 a[i] > a[j],則其爲一個逆序對;不然不是。
而else剛好符合這個條件只要有一個是從右邊的數加進來的,就說明當前(左邊)下標的 i到m-1都是大於這個數的。
以中間數做爲基數,同時從左右邊開始比較,由於基數是在中間,因此左邊的數要比基數小,右邊的數要比基數大,不然就交換數值,分支遞歸反覆便得出正確的順序。
能夠處理求第幾大的問題;極快,數據移動少;
不穩定。
#include<stdio.h> int a[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }; //爲了方便你們理解,我將數值設爲與以前同樣的數值。 void quick_sort(int l, int r) { if (l < r) {//防止越界 int i = l - 1, j = r + 1, x = a[l + r >> 1]; //-一、+1的緣由是由於下面咱們要用++i、--j。 //爲何不用i++、j++呢?由於咱們要比較數值,要讓i、j與咱們比較的數值下標同步,提早+1或者-1會致使後面的交換髮生錯誤。 //前者是先使用i+1再將i=i+1,後者是先使用i再將i=i+1。 while (i < j) { //雙指針移動不符合就暫停 while (a[++i] < x); while (a[--j] > x); //兩邊都不符合了,交換數值。 if (i < j) {//學了c++後可直接用swap函數。 int t = a[i]; a[i] = a[j]; a[j] = t; } } //再分治,左右兩邊遞歸排序。 quick_sort(l, j);quick_sort(j + 1, r); } } int main() { int n=15; quick_sort(0, n - 1); for (int i = 0;i < n;i++) printf("%d ", a[i]); return 0; }
#include<stdio.h> int a[] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 }; //爲了方便你們理解,我將數值設爲與以前同樣的數值。 int quick_sort(int l, int r, int k) { if (l == r) return a[l]; int i = l - 1, j = r + 1, x = a[l + r >> 1]; //-一、+1的緣由是由於下面咱們要用++i、--j。 //爲何不用i++、j++呢?由於咱們要比較數值,要讓i、j與咱們比較的數值下標同步,提早+1或者-1會致使後面的交換髮生錯誤。 //前者是先使用i+1再將i=i+1,後者是先使用i再將i=i+1。 while (i < j) { //雙指針移動不符合就暫停 while (a[++i] < x); while (a[--j] > x); //兩邊都不符合了,交換數值。 if (i < j) {//學了c++後可直接用swap函數。 int t = a[i]; a[i] = a[j]; a[j] = t; } } int s = j - l + 1;//判斷左邊有多少數,是否包含第k個數 //分治,不斷縮小範圍,直到l==r,輸出答案。 if (k <= s) return quick_sort(l, j, k); //k>s的話說明第K個值在右邊的第k-s 個數中,那麼在右邊的k=k-s; return quick_sort(j + 1, r, k - s); } int main() { int n = 15, k = 5; int ans = quick_sort(0, n - 1, k); printf("%d \n", ans); return 0; }