演算法學習 基礎排序演算法

2021-09-11 12:44:39 字數 3875 閱讀 9189

這篇文章主要講解3個基礎的排序演算法,選擇排序,插入排序,以及氣泡排序,其時間複雜度都是0(n^2)級別的,實現**使用c++語言。

首先給定乙個元素是無序的整數陣列:

需要對這個陣列中的8個整數進行從小到大的排序。

選擇排序的基本思路

首先從起始位置index = 0開始,遍歷一遍陣列,獲取到最小的元素值index = 4 的元素,元素值為1,然後將index = 0與index = 4 上的兩個元素交換位置,此時index = 0 上的元素值1。index = 4上的元素值為5。紅色為已排序完成的有序區域。

找到了最小的元素放在陣列的第一位後,接著從index = 1開始往後遍歷陣列。找到第二小的元素後再與index = 1的位置交換元素,此時,index = 1上的元素值為2,index = 2 上的元素為4.

接著再從index = 2的位置往後遍歷陣列,找到第三小的元素後再與index = 2上的元素交換位置,交換後,index = 2上的元素為3,index = 5 上的元素為4。

然後依此遍歷的方法,直到陣列的最後乙個位置存放的是最大的元素。選擇排序的整體思想不難理解,就是迴圈一遍陣列找到迴圈元素中最小的元素,再與已排好序的下乙個索引上的元素交換位置。

**實現

我寫成乙個函式,傳入乙個陣列以及元素的個數:

template void selectionsort(t arr,int n)

}swap(arr[i], arr[minindex]);

}}複製**

插入排序的基本思路

bobo老師打個這樣乙個比方,我覺得用來理解插入排序非常合適:就好像有一副牌,三個人用這副牌來鬥地主,分牌階段,你需要將你摸到的牌放在手中的牌中的合適位置,手中的牌是整理好的,是有序的,放入後,使其整體依舊有序。我們來模擬一下這個過程。首先固定手中有一張牌,用紅色標記為手中已整理好的牌。

接著摸第二張牌,為4,比5小,所以放在5的前面,4與5交換位置。

接著摸第三張牌,為2,2比5小,所以先放在5的前面,4的後面。

此時這裡並不是2合適的位置,繼續和前面的元素比較,2比4小,所以要放到4的前面。此時變成有序了。

接著再摸第四張牌,為7,7比5小,發現不用交換位置,放在原地就好了。

就這樣,按照這個方法,將摸到的牌與整理好的牌依次做比較,使其放在合適的位置,直到摸完最後一張牌。

**實現

template void insertionsort(t arr,int n) else }}

}複製**

注意:第一層for迴圈時 i = 1,i不是從零開始。因為第一張牌不需要排序,從第二張牌開始。所以設定i = 1。

在[0 i) 前閉後開這個區間中為已排好序的元素,i為待排序的元素的索引,第二層for迴圈是從待整理的元素索引i開始。在已排好序的區間[0,i)中,從後往前遍歷。 如果發現前面的元素比它大,則兩個元素交換位置。當發現前面的元素比它小的時候,此時它就找到了合適的位置。就不需要再遍歷了,直接結束這一層迴圈。

插入排序優化

在交換兩個元素位置的時候,呼叫了swap(arr[j - 1],arr[j]),而一次交換其實是三次賦值,這句**其實也可以改寫為:

int temp = arr[j-1];

arr[j-1] = arr[j];

arr[j] = temp;

複製**

如果乙個較小的元素要插入到合適的位置,肯定要一路交換很多次。這無形中就增加了排序時間。優化思路就是只進行賦值操作而不進行交換操作,先儲存乙份待排序的元素,然後遍歷已排好序的元素,從後往前進行逐一比較,如果當遍歷到index = j的元素時,j - 1索引上的元素要比j位置上的元素大,則將j - 1索引位置的元素往後挪,往後挪也就是將j索引位置的元素賦值為j-1索引位置的元素,當遍歷到j-1索引上的元素比元素j位置上的元素小或相等時,就說明上一次迴圈往後挪而騰出來的位置為待排序的合適位置,在將該位置的值賦值為待排序的值就好了。

假定現在按照優化的思路對1進行排序,紅色為已排好序的部分。

首先先複製乙份待排序的元素1

然後將待排序的元素與已排好序的index = 3位置,值為7的元素比較,如果這個元素比待排序的元素要大,則直接將待排序的值複製為這個元素。7 比 1 大,7往後挪,所以待排序位置上的元素值賦值為7,而index = 3位置就騰出來了。

然後依次往前與帶排序的元素比較。這次是index = 2 時的 5 與 1比較, 5比1大,5往後挪,將index = 3 位置上的元素賦值為5,index = 2這個位置就騰出來了。

再將index = 1 時的4 與 待排序的元素1比較,4 還是比1 大,4往後挪,將 index = 2位置賦值為4,index = 1這個位置就騰出來了。

繼續。再將index = 0時的2, 與待排序的元素1比較,2還是比1大,2往後挪,將index = 1位置賦值為2,index = 0這個位置騰出來了。

那麼騰出來的位置上為元素的前面已沒有元素可以比較了。所以此時在index = 0的位置上放置上待排序的元素。

元素1經過一番波折,塵埃落定,終於找到了他合適的位置,元素1排序完畢

然後index = 5上的元素3按照上述方法找到合適的位置,index = 6 上的元素按照上述方法找到合適的位置,接著是index = 7上的元素。將所有的元素都按照上述方法找到自己合適的位置。

**實現

template void insertionsort(t arr,int n)

}arr[j] = e;

}}複製**

氣泡排序實現思路

首先還是這乙個由8個數組成的乙個無序的陣列

氣泡排序的核心思想就是將相鄰的兩個元素兩兩比較,根據大小來交換元素的位置

首先,5與4比較,5比4大,我們的需求是從小到達排列,4需要在5的前面,所以4與5交換位置,紅色表示兩個要交換位置的元素。

交換後

然後, 5與2開始比較,5比2大,交換位置

交換後

繼續, 5和7比較,5比7小,位置保持不變

go on, 7與1比較,7比1大,交換位置

交換後

不要停,7與3比較,7比3大,交換位置

交換後

繼續深入, 7與8比較,7比8小,保持不變

還有最後乙個,8與6比,8比6大,交換位置

交換後

這樣一輪下來,元素8排到了最右側,此時紅色代表️已排好序的區域

接著按照上述方法,重新重頭開始相鄰元素兩兩遍歷,前乙個元素比後乙個元素大則交換位置,小則保持位置不變,一路比較下來。找到第二大的元素放到元素8的左側。

然後是然後是

給定的一組無序的整數陣列,按照排序的思路來講,藍色區域屬於無序的區域,還需要比較,但是上面中藍色部分已經是有序的了,這可以作為乙個優化的方面,就是當發現代排區域中的元素已經是有序了的時候,排序完成,結束排序,下面的**中不涉及這部分的優化。

實現**

template void bubblesort(t arr,int n)}}

}複製**

**不難理解,雙層迴圈,外層每一次迴圈確定乙個最大值放在陣列的右側,內層尋找這個最大值。先進行元素比較,滿足則交換。

剛剛在逐步比較的時候,出現了這樣一種情況:藍色的無序區域中的元素已經是有序的了。

但是上面的氣泡排序的**還會繼續的比較下去。每乙個元素都會參與外層迴圈,直到迴圈結束。所以優化方向是在無序區域中的元素已經有序了的情況下結束迴圈。 優化後的**,部分解釋見注釋。

void bubblesort(t arr,int n)

}if (issorted)

}}複製**

這個優化主要是用乙個bool值做標記,來確定是否有序。在內層迴圈中如果沒有元素交換,那麼這個數列肯定就是有序的了,那麼外層就無需在迴圈了。

下次學習內容:歸併排序

基礎 排序演算法學習筆記

noip範疇常見的排序一般是這幾種 1 氣泡排序,選擇排序,插入排序 2 快速排序,歸併排序,堆排序 3 計數排序,基數排序,桶排序 前兩類是基於比較的,第三類是基於統計的。第一類都是o n 2 的,第二類都是o nlogn 的。氣泡排序 1.相鄰的資料兩兩比較,小數放前面,大數放後面 2.這樣每一...

演算法學習 排序演算法

排序演算法 平均時間複雜度 最好情況 最壞情況 空間複雜度 穩定性氣泡排序 o n 2 o n o n 2 o 1 穩定選擇排序 o n 2 o n 2 o n 2 o 1 不穩定插入排序 o n 2 o n o n 2 o 1 穩定希爾排序 o nlogn o nlogn o nlogn o 1 ...

排序演算法學習

一直都想把排序和搜尋類的演算法總結一下,一直拖著沒寫,主要是太懶了,現在決定還是要再好好學習下這些基本的演算法。畢竟基礎真的是很重要。好了現在開始學習第乙個排序演算法 插入排序 我記得插入排序在我們以前的資料結構教程上是第乙個介紹的 插入排序 聽這個排序名字就是將乙個什麼數要插入到某個地方,不錯,他...