冒泡+直接插入+ 快速排序

一,冒泡法

(按從小到大排序舉例)

原理:通俗的講,就是一遍一遍地,不斷地把較大的數往下沉。

途徑:交換兩個數的位置。

舉例:


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的地方),插入,完成排序。
     }
}
}

三、快速排序

編輯時間:2015.9.9.14.35
1、採用 分治 的策略, 劃分成 多個 子塊,各個子塊 再進行各自排序;
2、把首元素 作爲標誌數,把序列 按標誌數 劃分成  兩個子序列, 左邊 都是 小於標誌數的, 右邊是大於標誌數的;
3、對前子序列 left…… i-1  回調, 對後子序列 i+1…… right 也進行回調。
4、程序2 也可以, 不知爲什麼,細節還未研究, 就是比較次數多一點,留待時間充足再追究 分析。
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;
}




 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章