一,冒泡法
(按從小到大排序舉例)
原理:通俗的講,就是一遍一遍地,不斷地把較大的數往下沉。
途徑:交換兩個數的位置。
舉例:
7 2 5 8 3
第一遍,把a[0] 與 a[1]比較,7 > 2, so, swap.
then, a[1] , a[2] 比較, 7 > 5 , 再交換。
……
第一遍結果是 8 存到了最下邊。
僞代碼細節: 若數組有n = 5,個元素,第一遍相鄰兩兩之間要比較n - 1 次 才能把最大的數 沉到 最下邊。
最大的數沉到最下邊之後,就不用再管該數了。
第二遍時,比較前4個數,這4個數相鄰兩兩之間比較,要比較3 次,才能把次大的數 填充 在倒數第二個框中。
遍歷 次數的問題: 每遍歷一次,確定一個元素的位置;當遍歷4次時,就剩下最頂端的一個元素;一個元素就不相鄰之間 相互比較了。
所以,需要遍歷 n - 1 遍。
for i = 0; i < n -1 ; i ++ // 遍歷 n-1遍
for j=0;j < n - i -1 ; j++ //第一遍比較n-1次,第二遍比較n-2次 。
代碼實現:
void bubble_sort(int *a, int n)
{
int itmp = 0;
int i = 0,j=0;
for(i = 0; i < n - 1; i++)// 遍歷 n-1遍
{
for(j = 0; j < n - i -1; j ++) //第一遍比較n-1次,第二遍比較n-2次 。
{
if (a[j] > a[ j + 1 ]) //交換順序,不斷把大的沉入 底部。
{
itmp = a[j];
a[j] = a[ j +1 ];
a[ j + 1 ] = itmp;
}
}
}
}
至於空間複雜度等深層次理論東西,有待了解研究。
二、直接插入排序法
思想:假設一段序列,n 個元素, a[ 0 ] 到 a[ n - 1 ], 起初就默認a[ 0 ] 到a[ i -1 ]爲已經排好序的 有序子序列,,現在要把a [ i ] 插入前邊的 有序子序列裏邊。
(p.s 起初 i = 1, 所以 a[ 0 ]就爲 有序子序列; 不斷把 a[ i ] 插入有序子序列,知道 i == n -1)
途徑:把a[ i ] 的值暫存給tmp(tmp = a[ i ]);不斷地遍歷,尋找 a[ i ] 應該插入 有序子序列中的位置;從插入點到 a[ i ],依次把數組後移(a[ i ] = a [ i -1 ]);
然後把tmp賦值給 插入點;完成一個元素插入有序子序列。
舉例:
tmp=a[ i ] (==6) | |||||
1 | 5 | 8 | 6 | 2 | 4 |
1 | 5 | 5 | 8 | 2 | 4 |
1 | 5 | tmp | 8 | 2 | 4 |
如上表格,1,5,8,是有序子序列, 6 是待排序的元素 a [ i ], 因爲 a [ i ] < a [ i - 1 ],所以要把 a [ i ] 插入到前面的有序子序列中;
暫存 a [ i ]給 tmp,然後 有序子序列 向後覆蓋的過程中順便尋找 tmp應該在 有序子序列 中的位置;然後把tmp賦值爲相應的位置。
代碼實現:
void dire_insert_sort(int *a, int n)
{
int i = 0, j = 0, tmp = 0;
for( i = 1; i < n; i ++) //i從一開始,起初把a[ 0]作爲有序子序列。
{
if ( a[ i] < a[ i - 1 ]) //若a[ i ](即 6) 比 有序子序列的最大的一個數(a[ i -1 ],即 8)還小,則 6 要插入 有序子序列,否則直接比較下一個
{
tmp = a[ i ]; //暫存要排序的元素,即 a[ i ].
for( j = i - 1; (j >= 0) && (tmp < a[j]); j-- ) //尋找tmp要插入的地方,一旦 tmp大於 a[j],停止數組右移。
{
a[ j + 1 ] = a[ j ]; // 尋找過程中,數組右移。
}
a[ j +1 ] = tmp; // 找到應該插入的位置(上面表格中,第二個5的地方),插入,完成排序。
}
}
}
三、快速排序
void quick_sort1(int s[], int left, int right)
{
int i = 0, j = 0, tmp = 0, k = 0;
if (left < right)
{
i = left;
j = right;
tmp = s[i]; /*暫存 序列 首元素 爲 標誌數, 以後以該數進行 左右序列劃分*/
while(i < j) /*此while 劃分 以 i 爲分界點,劃分成兩個子序列,左側小於s[i], 右側大於s[i]*/
{
while((i < j) && (s[j] > tmp)) j--;
if (i < j) s[i++] = s[j];
while((i < j) && (s[i] < tmp)) i++;
if (i < j) s[j--] = s[i];
}
s[i] = tmp; /*把標誌數 賦值到 標誌位的地方(原s[i] 是一個 重複於 序列中的一個數 )*/
quick_sort1(s, left, i-1);
quick_sort1(s, i+1, right);
}
return;
}
void quick_sort2(int s[], int left, int right) /*似乎也可以, 但思想混亂, 需要細細研究*/
{
int i = 0, j = 0, tmp = 0, k = 0;
i = left;
j = right;
tmp = s[i];
while(i < j)
{
while((i < j) && (s[j] > tmp)) j--;
if (i < j) s[i++] = s[j];
while((i < j) && (s[i] < tmp)) i++;
if (i < j) s[j--] = s[i];
s[i] = tmp;
quick_sort2(s, left, i-1);
quick_sort2(s, i+1, right);
}
return;
}