氣泡排序(重溫經典演算法系列)

2021-10-23 00:26:05 字數 2983 閱讀 6716

// 單個元素時肯定是有序的;故首元素單獨有序,從 [1,n) 為待排元素所在的區間;

// i 控制: n-1輪冒泡(即執行一系列兩兩元素對比的操作),第 i 輪能夠選出第 i 大(或者小)的元素值,n-1輪 選出 n-1 個較大(或者小)值之後,整個序列即可有序;

for(

int i =

1; i < n ;

++i)

}}

// 外層i 控制 n-1 輪即可; 

for(

int i =

0; i < n -1;

++i)

}}

原始**的設計問題所在:

原始**執行了n^2次元素掃瞄:每一輪都從開頭掃瞄至末尾

每一輪冒泡都會加長有序元素區間段:

自前往後冒泡則出現在末端,自後往前則出現在前段;

**優化:

雙側迴圈可跳過對該區間元素的掃瞄,

僅掃瞄無序元素區間,這便是**優化的理論依據

從前到後掃瞄

for

(int i =

0; i < n -1;

++i)

}

自後往前掃瞄

for

(int i = 0; i < n - 1; ++i)

for(int j = n - 1 - i; j > 0; --j)

//自後往前冒泡比較;

迴圈控制條件的總結(綜述)

無論具體迴圈的條件如何設定,本質依舊都是確保a的索引在[0,n)範圍;

其次要確保:

外層控制 n-1 輪冒泡,內層控制待排序元素區間即可;

使用《符號而非是<=符號時:

0與n-1配對使用,1與n配對使用.

問題描述及其優化

若當前輪次的冒泡使得整個序列已經全部有序,或者待排序的資料本身就是有序的,

則後續執行的冒泡操作都是贅餘工作;

優化辦法:

引入 flag標誌即可,

記錄當前輪次冒泡是否有元素交換操作,無交換則表明已序列全部有序.

加入有序標誌的簡單冒泡

template

<

typename t>

void

bubblesort

(t* arr,

const std::size_t n)

//該部分**再次改進如下;}}

}

assert

(arr)

;該斷言語句需要使用標頭檔案(c++)

#include

之前是序列整體有序之後的贅餘工作問題;

若給出的待排序數列直接是前段或者後段部分有序的,則

也會因為執行了對部分有序元素的區間的掃瞄而導致工作贅餘.

優化辦法:

引入哨兵標誌,記錄有序區間與無序區間段的邊界,

每一輪冒泡中,最後執行交換操作的索引位置即為有序與無序的分界處.

加入有序標誌與有無序邊界記錄的進一步優化版冒泡

自左往右掃瞄,則左段無序、右段有序;

反之,模擬可知.

template

<

typename t>

void

bubblesort2

(t* arr,

const std::size_t n)

} sortedborder = lastexchangeindex;

if(issortedflag)

//未發生交換時flag未被重置為false,表明數列已經有序;

}}

進一步優化的雙向冒泡法(同快排設計思想),同時刷選最大、最小值往兩端靠攏;
template

<

typename t>

void

headtailbubblesort

(t* arr,

const std::size_t n)

//std::cout << "自前向後掃瞄: i = " << i << " j = "<< j << " maxindex = " << maxindex << std::endl;

//randomarrayfuntionhelper::printarray(arr, n);}if

(issortedflag)

issortedflag =

true

; j = leftindex;

leftindex =0;

for(std::size_t i = rightindex; i > j;

--i)

//std::cout << "自後往前掃瞄: i = " << i << " j = " << j << " minindex = " << maxindex << std::endl;

//randomarrayfuntionhelper::printarray(arr, n); }if

(issortedflag)

}}

冒泡演算法逐步改進的思想,請參考文章:

氣泡排序的演算法分析與改進

冒泡演算法排序過程的圖形化演示,請參考:

排序演算法過程演示

交流方式

希爾排序(重溫經典演算法系列)

參考材料 希爾排序,又名縮小增量排序 它是一種改進版本的直接插入排序法 只不過直接插入排序是從左往右遍歷選擇帶插入的元素,再自右向左找到合適的插入位置 而希爾排序是通過對原陣列進行分組,進而產生小規模的區域性有序的陣列,接著再直接插入排序演算法實現高效排序的一種排序演算法.本質是 直接插入排序高效處...

歸併排序(重溫經典演算法系列)

單個元素肯定有序 歸併排序採用分治思想,分而治之 將待排序陣列劃分為n等分,每份長度為1個元素,則 n份全部有序 再一生二,二生四,逐步兩兩元素有序的區間,歸一合併成1個有序區間 最終會歸併出整乙個陣列元素有序的結果.歸併排序有兩種實現方式 1 自頂向下遞迴呼叫實現 2 自底向上迭代執行實現.左右雙...

演算法系列 氣泡排序

在我們的生活中,撲克牌應該是每乙個人的娛樂專案之一吧。在我們玩撲克牌的過程中,我們也可以體會到學習的奧秘。我們會根據手裡的牌,從小到大進行排序 即小的牌在前面,大的牌在後面 在這個過程中,我們可以體會並學習氣泡排序的神奇。氣泡排序 臨近的數字兩兩進行比較,按照從小到大或者從大到小的順序進行交換,這樣...