資料結構——排序與查詢(3)——氣泡排序(C++實現)
阿新 • • 發佈:2018-11-10
交換排序演算法
所謂交換,意思是說根據所給的序列,對其中的兩個元素進行大小比較,若為逆序,那麼我們就交換它。這樣就達到了排序的目的。接下來介紹最簡單的交換排序——氣泡排序。
氣泡排序的原理
氣泡排序的原理很簡單,它反覆遍歷要排序的列表,比較每對相鄰的專案,如果它們的順序錯誤則交換它們。 重複遍歷列表,直到不需要交換,這表示列表已排序。我們可以從後往前(或者從前往後)兩兩比較相鄰的元素,若為逆序,則交換他們。(這跟插入排序不同,插入排序一開始是區域性排序,也就是說一開始排完的數字的位置,有可能下次排序的時候還會變動,而氣泡排序是全域性排序,一旦位置排好就是固定位置)。
舉個例子來說說氣泡排序的步驟:
假設我們對 5 1 4 2 8
如果這個時候我們將圖倒過來看,就會發現5就像從底下往上冒的水泡,這也是為什麼這個演算法稱為氣泡排序的原因。
好,接下來我們看看第二趟會發生什麼:
那麼我們對5排完之後,應該對誰排序呢?當然是對 1 了,因為我們是遍歷要排序的序列的,得按順序來。於是發現1比後面的都小,於是不用交換,保留原地不動。(這個時候就注意了,1是不動沒錯,那麼就意味著它真的不動?當然不是,它還是得跟其他元素遍歷比較,否則我怎麼知道它比其他的元素都要小?所以這是一種對時間資源的浪費)。
排完之後,對4排序,重複第一步的演算法,如圖所示;
排完之後,對2排序,(實際上這個時候,我們的排序已經完成,但是對於演算法來說它並不知道此時的序列已經處於有序狀態
下面貼一個動態圖(來自維基百科),直觀的描述這一過程:
氣泡排序的C++實現
下面我們用C++語言來寫一下這個演算法
#include <iostream> #include <vector> using namespace std; /*函式宣告*/ void bubbleSort(vector<int> &vec); void swap(int &i, int &j); /*主函式*/ int main() { vector<int> vec; cout << "請輸入待排序的序列" << endl; //假設我們對5個數進行排序 for (int i = 0; i < 5; i++) { int n; cin >> n; vec.push_back(n); } bubbleSort(vec);//使用希爾排序對vector進行排序 //輸出結果 cout << "氣泡排序後:" << endl; for (int k = 0; k < vec.size(); k++) { cout << vec[k] << " "; } return 0; } //氣泡排序的實現,由小到大 void bubbleSort(vector<int> &vec) { //遍歷序列中的每個元素 for (int i = 0; i < vec.size() - 1; i++) { bool IsSwap = false; //設立是否交換的標記 for (int j = vec.size() - 1; j > i; j--) { //一趟排序 if (vec[j - 1] > vec[j]) { //後面的大於左邊的大於右邊的數,交換 swap(vec[j - 1], vec[j]); IsSwap = true;//交換標記為true } } //當交換標記為flase的時候,意味著本次遍歷沒有發生交換,跳出迴圈 if (IsSwap = false) return; } } //交換兩個數的函式 void swap(int &i, int &j) { int temp = j; j = i; i = temp; }
複雜度分析
顯然這種做法造成了極大的時間浪費,做了很多不必要的操作。考慮極端的情況,當被排數列有序的時候,要進行n - 1次比較。(最後一次不用比較,因為已經排好)。當為逆序的時候,進行N-1次排序,並且,第I趟要進行N-I次比較,複雜度為O(n^2).
另外一種用的最廣泛的交換排序,叫快速排序,我之前寫過我就不再贅述了,連結貼上:C++抽象程式設計——演算法分析(6)——快速排序演算法