記錄一下最近學習的各種排序演算法。
插入排序
氣泡排序
歸併排序
快速排序
選擇排序是最簡單且容易想到的排序方法。它把輸入值(以下均以列表為例)分為兩個部分:已排序 和 未排序部分。
先看一組偽**:
}//找到餘下值中最小的索引值,與第i個值交換。若沒找到則不變
temp = numbers[i]
numbers[i]
= numbers[indexsmallest
numbers[indexsmallest]
= temp
}兩個迴圈把列表分為已排序和未排序兩部分,用 i,j 去表示
該演算法找到未排序中最小值的索引值
把索引值上的元素與i元素交換
i,j 更新,表示出新的已排序未排序部分
直到 i 小於長度 -1,遍歷停止。因為不再需要單獨遍歷最後乙個元素。
該演算法或將執行多次比較。當列表長度為n時,外層迴圈將執行 n - 1 次。在這些外迴圈中,內層迴圈每次將執行平均 n / 2 次。所以,(n - 1) x (n / 2) = o(n ^ 2)。此演算法也是眾多排序演算法中最慢的演算法之一。
同樣的,插入排序也將列表分為已排序和未排序部分。不同的是,此演算法每次只在未排序部分中提取第乙個元素,然後把它放到已排序部分中合適的位置。
先看一組偽**:
}這次要外層要迴圈到長度而不是長度 - 1,因為我們也要把最後乙個元素放到正確的位置上。
將第i個元素作為第乙個未排序部分的起點。因為我們無需排序索引0,所以 i 為1。
第j個元素一直標記為我們要插入的元素。如果該元素比前乙個元素小,則互換。
當第i個元素放置到正確的位置後,i + 1。迴圈下一位元素並放置到正確位置。
如果要插入的元素比前面所有元素值都要小,則該元素依次迴圈到列表第一位,隨之 j = 0打破迴圈。
該演算法實際上效率與選擇排序同理,複雜度均為o(n^2)。因為外層迴圈執行n - 1次,而內層迴圈同樣每次平均執行n/2 次。(n - 1) x (n / 2) = o(n ^ 2)。
該演算法不再將列表分為兩個部分,每次只比較兩個相鄰的元素然後調整位置。
先看一組偽**:
for
(i =
0; i < numberssize -1;
++i)
}}
該演算法從第乙個元素開始,依次和後面的元素比較。若後一位元素小於前一位元素則互換。
內層迴圈結束後,該列表中最大的元素已確定到最後一位。然後重新遍歷列表。
當 i = 長度 - 1 時,結束遍歷,此時列表已排好序。
與前兩種演算法不同,該演算法依次優先排好後面的順序,而不是前面。
因為巢狀迴圈,該演算法的時間複雜度仍為o(n^2)。
該演算法用到遞迴解決,分為兩個部分。第乙個部分為遞迴函式,該函式每次平均把列表分為兩個部分,分別去遞迴。第二個部分為乙個排序函式,用來排遞迴回來的列表。
來看兩組偽**:
//遞迴函式內容:
merge
(numbers, start, end)
//排序函式
mergehelper
(numbers, start, mid, end)
else
++mergepos
}//當左邊沒新增完,右邊已經新增完時,把左邊剩下的加到mergednumbers
while
(leftpos <= mid)
//右邊同理
while
(rightpos <= end)
//最後,把排好序的列表放回到原列表中
for(mergepos =
0; mergepos < mergedsize;
++mergepos)
}
思路已寫在注釋中。
該演算法重複平分列表直到每個列表的元素數為1。此做法會構成log n層列表。每層列表中執行n次比較運算,所以一共有 n * log n次運算,而該演算法成為最有效率的排序演算法之一。
與歸併排序類似,快排也用到了遞迴去解決問題。該演算法隨意取乙個元素為基準數pivot。把所有比它小的元素放在它的前面,比它大的元素放在後面。在以pivot為中心把列表分別遞迴,直到個數為1。
再來看兩組偽**:
quicksort
(numbers, lowindex, highindex)
//lowendindex為小於的部分的最後乙個元素
lowendindex =
partition
(numbers, lowindex, highindex)
//遞迴小於的部分和大於的部分
quicksort
(numbers, lowindex, lowendindex)
quicksort
(numbers, lowendindex +
1, highindex)
}
partition
(numbers, lowindex, highindex)
//當numbers[highindex] > pivot時,增加highindex
while
(numbers[highindex]
> pivot)
if(lowindex >= highindex)
else
}return highindex
}
思路已寫在注釋中。
通常來說,該演算法的時間複雜的為o(n log n)。特殊情況下,當每一層的pivot都選擇了最大或是最小的元素,則此情況下的時間複雜度為o(n^2)。但是由於這種情況的發生概率小之又小,該演算法是最有效率的排序演算法之一。
後面會更新更多的排序演算法,此部落格僅用於自我學習的記錄,如有不當請指正。
選擇 冒泡 歸併 插入及希爾排序
選擇排序每次遍歷一遍陣列,找出最小的數,然後跟陣列的第乙個元素交換。再從剩下的元素中重複此步驟直至陣列排序完畢。時間複雜度與輸入資料無關,為o n 2 每次從首元素開始,從左到右交換相鄰且逆序的元素,一直交換到尾元素時即完成一輪迴圈,此時末尾元素即為最大值。接著在除尾元素外的剩餘元素中繼續上述迴圈,...
演算法之旅 氣泡排序及選擇排序
氣泡排序和選擇排序是排序演算法中比較簡單的兩種演算法。氣泡排序的思想是 比較相鄰的元素。如果第乙個比第二個大,就交換他們兩個。對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對,針對所有的元素重複以上的步驟,這樣每次參與比較的元素就越來越少,直到沒有任何一對數字需要比較。對n個數字進行氣泡排...
Java演算法之排序(快速,冒泡,歸併,選擇)
下面是個人整理的幾種排序演算法,不算太難,有一定基礎的認真看看都可理解。歸併演算法思想比較簡單,但在寫 時要注意處理好邊界問題,注意對陣列的賦值和改變。選擇排序 選擇排序 public class n1 1 public n1 1 int a public int result temp a i a...