1. 參考資料:

1 )譚浩強 c 程序設計》 124

2 )數據結構自考網( very good

http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.3.1.1.htm

?

2. 算法分析:

假如有以下數據: 5 2 4 3 ;人是如何排序的呢?如果按從小到大排序,肯定是每次找出一個最小的數,直到排好序;(注:選擇排序就是這個思路,每次找出一個最小值放到合適位置;)類似,計算機實現也是這樣的,最簡單的冒泡排序方法就是如此,每次找出一個最大的值沉底,第一次 5 沉底,第二此 4 沉底,經過 N-1 次后排序完成。

?

3 .具體編碼實現時關鍵是要確定循環次數:

3.1 思路一:

外層循環: n-1 (每次找出一個最大的)

內層循環: n-i

外層 i=1, 內層需要 n-1 次兩兩比較才能找出最大值;

外層 i=2, 內層需要 n-2 次兩兩比較才能找出最大值;

……

歸納得到,內層循環需要 n-i

?

如此反復,直到排好序為止(若在某一趟冒泡過程中,沒有發現一個逆序,則可結束冒泡排序),所以 冒泡過程最多進行 n-1 趟。

?

代碼實現如下:

				
?1?void??BubbleSort(RecordType?r[],?int?length?)
?2?/*對記錄數組r做冒泡排序,length為數組的長度*/
?3?{
?4?n=length;????change=TRUE;
?5?for?(?i=1?;?i<=?n-1?&&?change?;++i?)?
?6?{
?7??????change=FALSE;
?8??for?(?j=1?;?j<=?n-i?;?++j)?
?9??if?(r[j].key>?r[j+1].key?)??
10?{
11????????????x=?r[j];
12????????????r[j]=?r[j+1];
13????????????r[j+1]=?x;
14?change=TRUE;
15??????}?
16?}
17?}?/*??BubbleSort??*/?
18?

代碼來自:

西北大學 數據結構 精品教程

交換類排序法 冒泡排序 ?

http://jpkc.nwu.edu.cn/datastr/study_online/test_paper.htm

?

3.2 思路二:

以下內容來自:

數據結構自考網

http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.3.1.1.htm

或者

http://www.wjzyzx.com/rjxy/sjjg/gailun/gailun1.3.2.htm

?

提示:注意有序區、無序區的這種思考方法。

冒泡排序

1
、排序方法
???
 將被排序的記錄數組 R[1..n] 垂直排列,每個記錄 R[i] 看作是重量為 R[i].key 的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數 R :凡掃描到違反本原則的輕氣泡,就使其向上 " 飄浮 " 。如此反復進行,直到最后任何兩個氣泡都是輕者在上,重者在下為止。
1 )初始
  ??? R[1..n] 為無序區。

2 )第一趟掃描
  ??? 從無序區底部向上依次比較相鄰的兩個氣泡的重量,若發現輕者在下、重者在上,則交換二者的位置。即依次比較 (R[n] R[n-1]) (R[n-1] R[n-2]) , (R[2] R[1]) ;對于每對氣泡 (R[j+1] , R[j]) ,若 R[j+1].key<R[j].key ,則交換 R[j +1] R[j] 的內容。
???
 第一趟掃描完畢時, " 最輕 " 的氣泡就飄浮到該區間的頂部,即關鍵字最小的記錄被放在最高位置 R[1] 上。

3 )第二趟掃描
  ??? 掃描 R[2..n] 。掃描完畢時, " 次輕 " 的氣泡飄浮到 R[2] 的位置上 ……
???
 最后,經過 n-1? 趟掃描可得到有序區 R[1..n]
?
注意:
  ??? i 趟掃描時, R[1..i-1] R[i..n] 分別為當前的有序區和無序區。掃描仍是從無序區底部向上直至該區頂部。掃描完畢時,該區中最輕氣泡飄浮到頂部位置 R[i] 上,結果是 R[1..i] 變為新的有序區。

2
、冒泡排序過程示例
???
 對關鍵字序列為 49 38 65 97 76 13 27 49 的文件進行冒泡排序的過程

3
、排序算法
1 )分析
???
 因為每一趟排序都使有序區增加了一個氣泡,在經過 n-1 趟排序之后,有序區中就有 n-1 個氣泡,而無序區中氣泡的重量總是大于等于有序區中氣泡的重量,所以整個冒泡排序過程至多需要進行 n-1 趟排序。
???
 若在某一趟排序中未發現氣泡位置的交換,則說明待排序的無序區中所有氣泡均滿足輕者在上,重者在下的原則,因此,冒泡排序過程可在此趟排序后終止。為 此,在下面給出的算法中,引入一個布爾量 exchange ,在每趟排序開始前,先將其置為 FALSE 。若排序過程中發生了交換,則將其置為 TRUE 。各趟 排序結束時檢查 exchange ,若未曾發生過交換則終止算法,不再進行下一趟排序。

2 )具體算法
? void BubbleSort(SeqList R)
?? { //R
l..n) 是待排序的文件,采用自下向上掃描,對 R 做冒泡排序
???? int i
j ;
???? Boolean exchange
; // 交換標志
???? for(i=1;i<n;i++){ //
最多做 n-1 趟排序
?????? exchange=FALSE
// 本趟排序開始前,交換標志應為假
?????? for(j=n-1;j>=i
; j--) ?// 對當前無序區 R[i..n] 自下向上掃描
??????? if(R[j+1].key<R[j].key){//
交換記錄
????????? R[0]=R[j+1]
//R[0] 不是哨兵,僅做暫存單元
????????? R[j+1]=R[j]
;
????????? R[j]=R[0]

????????? exchange=TRUE
; // 發生了交換,故將交換標志置為真
???????? }
?????? if(!exchange) //
本趟排序未發生交換,提前終止算法
???????????? return

???? } //endfor(
外循環 )
??? } //BubbleSort

?

4. 算法分析

冒泡排序算法分析:最壞情況下,待排序記錄按關鍵字的逆序進行排列,此時,每一趟冒泡排序需進行i次比較,3i次移動。經過n-1趟冒泡排序后,總的比較次數為n(n-1)/2;總的移動次數為3 n(n-1)/2 次,因此該算法的時間復雜度為O(n2);空間復雜度為O(1)。另外,冒泡排序法是一種穩定的排序方法。

注:

1) 關鍵語句總執行次數的計算:

外層i=1:內層j=n-1;

i=2:j=n-2; ……;

所以,交換語句的總執行次數是(n-1+(n-2)+(n-3)++1=n(n-1)/2;

2) 時間復雜度的概念:

一般情況下,算法中基本操作重復執行的次數是問題規模 n 的某個函數,用 T(n) 表示,若有某個輔助函數 f(n), 使得當 n 趨近于無窮大時, T n)/f (n) 的極限值為不等于零的常數,則稱 f(n) T(n) 的同數量級函數。記作 T(n)=O(f(n)), O(f(n)) 為算法的漸進時間復雜度,簡稱時間復雜度。

在各種不同算法中,若算法中語句執行次數為一個常數,則時間復雜度為 O(1), 另外,在時間頻度不相同時,時間復雜度有可能相同,如 T(n)=n2+3n+4 T(n)=4n2+2n+1 它們的頻度不同,但時間復雜度相同,都為 O(n2)

3) 空間復雜度:

與時間復雜度類似,空間復雜度是指算法在計算機內執行時所需存儲空間的度量。記作 :
S(n)=O(f(n))
我們一般所討論的是除正常占用內存開銷外的輔助存儲單元規模。

?

冒泡排序的O(1)表示只需要一個輔助的temp存儲單元來實現交換數據,所以空間復雜度為常量。

?

4 )平均時間復雜度:

設每種情況的出現的概率為 pi, 則為 sum(pi*f(n)) ;

以下內容來自:

請教關于“平均時間復雜度 T(n) ”的推導

http://topic.csdn.net/t/20031209/21/2546177.html

問題: ?
? ? ?
今假設 a 中初始輸入數據可能出現 ? n! ? 種的排列的概率相等,則 關鍵語句 的平均執行次數為多少?希望給出具體的推導過程! ?
?
(書上沒給出具體答案,只寫了平均時間復雜度 T(n) ? = ? O(n 平方 ) ?

解答:

如果 a 中初始輸入數據可能出現 ? n! ? 種的排列的概率相等 ?
?
if( ? a[j] ? > ? a[j+1] ? ) 句成立的概率為 50% ?
?
故內層循環執行次數為 i/2 。 ?
?
在不考慮 change 的影響是有 T(n)=(1+2+....+n-1)/(2*2) ? = ? (n-1)*n/4 ? = ? O(n^2)

?

5. 算法改進
???
 上述的冒泡排序還可做如下的改進:
(1)
記住最后一次交換發生位置 lastExchange 的冒泡排序
  在每趟掃描中,記住最后一次交換發生的位置 lastExchange ,(該位置之前的相鄰記錄均已有序)。下一趟排序開始時, R[1.. lastExchange-1] 是有序區, R[lastExchange..n] 是無序區。這樣,一趟排序可能使當前有序區擴充多個記錄,從而減少排序的 趟數。具體算法【參見習題】。

(2)
改變掃描方向的冒泡排序
?
冒泡排序的不對稱性
  能一趟掃描完成排序的情況:
???
 只有最輕的氣泡位于 R[n] 的位置,其余的氣泡均已排好序,那么也只需一趟掃描就可以完成排序。
【例】對初始關鍵字序列 12 , 18 , 42 , 44 45 , 67 , 94 , 10 就僅需一趟掃描。
需要 n-1 趟掃描完成排序情況:
  ??? 當只有最重的氣泡位于 R[1] 的位置,其余的氣泡均已排好序時,則仍需做 n-1 趟掃描才能完成排序。
【例】對初始關鍵字序列: 94 10 , 12 18 , 42 , 44 , 45 , 67 就需七趟掃描。
?
造成不對稱性的原因
  每趟掃描僅能使最重氣泡 " 下沉 " 一個位置,因此使位于頂端的最重氣泡下沉到底部時,需做 n-1 趟掃描。

?
改進不對稱性的方法
???
 在排序過程中交替改變掃描方向,可改進不對稱性。

? 代碼實現如下:

代碼來源: http://www.goc.ac.cn/liuag/html/algorithms_bibobblesort.html ?

??1?????????????????int
??2??????????????????data[10]={4,8,22,79,-2,0,100,13,12,-100};
??3?????????
??4?
??5?????????????????void
??6??????????????????Bubble_Sort2(int?a[],int?n);
??7?????????
??8?
??9?????????????????void
?10??????????????????Print(int?a[],int?n);
?11?????????
?12?
?13?????????????????main()
?14?????????
?15?
?16?????????????????{
?17?????????
?18?
?19?????????????????
?20???????????????????????????Print(data,10);
?21?????????
?22?
?23?????????????????
?24???????????????????????????Bubble_Sort2(data,10);
?25?????????
?26?
?27?????????????????
?28???????????????????????????Print(data,10);
?29?????????
?30?
?31?????????????????}
?32?????????
?33?
?34?????????????????void
?35??????????????????Print(int?a[],int?n)
?36?????????
?37?
?38?????????????????{
?39?????????
?40?
?41?????????????????
?42?????????????????????????????
?43?????????????????????????int?i;
?44?????????
?45?
?46?????????????????
?47?????????????????????????????
?48?????????????????????????for(i=0;i<n;++i)
?49?????????
?50?
?51?????????????????
?52??????????????????????????????printf("%4d",a[i]);
?53?????????
?54?
?55?????????????????
?56?????????????????????????????printf("\n");
?57?????????
?58?
?59?????????????????}
?60?????????
?61?
?62?????????????????void
?63??????????????????Bubble_Sort2(int?a[?],int?n)
?64?????????
?65?
?66?????????????????{
?67???
?71?????????????????????????int?low=0,high=n-1;
?72??
?76?????????????????????????int?change=1;
?77
?81?????????????????????????int?i,temp;
?82??? ?????????????????????????
?86?????????????????????????while(low<high&&change)
?87
?90???????????????????????????{
?91?
?94?????????????????????????????change=0;
?95????
?99?????????????????????????for(i=low;i<high;i++)
100???
104?????????????????????????if(a[i]>a[i+1])
105????
108???????????????????????????????{
109?????????
110?
113?????????????????????????/*?a[i]<->a[i+1];*/
114????
118?????????????????????????????????temp=a[i];
119????
122?????????????????????????????????a[i]=a[i+1];
123?????????
124?
125?????????????????
126?????????????????????????????????a[i+1]=temp;
127?????????
128?
129?????????????????
130?????????????????????????????????change=1;
131?????????
132?
133?????????????????
134???????????????????????????????}
135?????????
136?
137?????????????????
138?????????????????????????????high--;
139?????????
140?
141?????????????????
142?????????????????????????????
143?????????????????????????for(i=high;i>low;i--)
144?????????
145?
146?????????????????
147???????????????????????????????
148?????????????????????????if(a[i]<a[i-1])
149?????????
150?
151?????????????????
152???????????????????????????????{
153?????????
154?
155?????????????????
156?????????????????????????????????
157?????????????????????????/*?a[i]<->a[i-1];?*/
158?????????????????
159?????????
160?
161?????????????????
162?????????????????????????????????temp=a[i];
163?????????
164?
165?????????????????
166?????????????????????????????????a[i]=a[i-1];
167?????????
168?
169?????????????????
170?????????????????????????????????a[i-1]=temp;
171?????????
172?
173?????????????????
174?????????????????????????????????change=1;
175?????????
176?
177?????????????????
178???????????????????????????????}
179?????????
180?
181?????????????????
182?????????????????????????????low++;
183?????????
184?
185?????????????????
186???????????????????????????}//while
187?????????
188?
189?????????????????}//Bubble_Sort2
190?????????

⑤雙向冒泡排序真的比單向的快?

其實雙向冒泡并不一定比單向的快,只是在排序過程中交替改變掃描方向,可改進冒泡排序的不對稱性。

?

Ok

明天學習快速排序法!

Come on !