使用Golang實現的快速排序
一、舞動的快速排序
在實現排序算法前,先讓我們來欣賞一段關于快速排序的視頻,本段視頻展示了快速排序的原理,如果沒有看懂,請看完本文后再回頭來看一下,應該就明白了吧。 O(∩_∩)O~
![]()
二、快速排序實現
2.1 快速排序基礎版
通過下面一組數據,將最左邊的數設定為軸,并記錄其值為 s。
(注意:*表示要交換的數,[]表示軸)
- [41] 24 76* 11 45 64 21 69 19 36*
- [41] 24 36 11 45* 64 21 69 19* 76
- [41] 24 36 11 19 64* 21* 69 45 76
- [41] 24 36 11 19 21 64 69 45 76
- 21 24 36 11 19 [41] 64 69 45 76
- 令索引 i 從數列左方往右方找,直到找到大于 s 的數
- 令索引 j 從數列右方往左方找,直到找到小于 s 的數
- 如果 i >= j,則離開回圈
- 如果 i < j,則交換索引i與j兩處的值
- 將左側的軸與 j 進行交換
- 對軸左邊進行遞回
- 對軸右邊進行遞回
透過以上演算法,則軸左邊的值都會小于s,軸右邊的值都會大于s,如此再對軸左右兩邊進行遞回,就可以對完成排序的目的。在上面的例子中,41左邊的值都比它小,而右邊的值都比它大,如此左右再進行遞回至排序完成。
具體代碼如下:
package main
import (
"fmt"
)
const MAX = 10
var sortArray = []int{41, 24, 76, 11, 45, 64, 21, 69, 19, 36}
func main() {
fmt.Println("before sort:")
show()
quickSort(sortArray, 0, MAX-1)
fmt.Println("after sort:")
show()
}
// quickSort
func quickSort(sortArray []int, left, right int) {
if left < right {
key := sortArray[left]
i := left
j := right
for {
for i+1 < MAX {
i++
if key <= sortArray[i] {
break
}
}
for j-1 >= 0 {
if key >= sortArray[j] {
break
}
j--
}
if i >= j {
break
}
swap(i, j)
}
sortArray[left] = sortArray[j]
sortArray[j] = key
show()
quickSort(sortArray, left, j-1)
quickSort(sortArray, j+1, right)
}
}
// Swap the position of a and b
func swap(a, b int) {
sortArray[a], sortArray[b] = sortArray[b], sortArray[a]
}
// foreach
func show() {
for _, value := range sortArray {
fmt.Printf("%d\t", value)
}
} 2.2 快速排序升級版
在快速排序法基礎版中,每次將最左邊的元素設為軸,而之前曾經說過,快速排序法的加速在于軸的選擇,在這個例子中,只將軸設定為中間的元素,依這個元素作基準進行比較,這可以增加快速排序法的效率。
在這個例子中,取中間的元素s作比較,同樣的先得右找比s大的索引 i,然后找比s小的索引 j,只要兩邊的索引還沒有交會,就交換 i 與 j 的元素值,這次不用再進行軸的交換了,因為在尋找交換的過程中,軸位置的元素也會參與交換的動作,例如:41 24 76 11 45 64 21 69 19 36
首先left為0,right為9,(left+right)/2 = 4(取整數的商),所以軸為索引4的位置,比較的元素是45,您往右找比45大的,往左找比45小的進行交換: - 41 24 76* 11 [45] 64 21 69 19 *36
- 41 24 36 11 45* 64 21 69 19* 76
- 41 24 36 11 19 64* 21* 69 45 76
- [41 24 36 11 19 21] [64 69 45 76]
完成以上之后,再初別對左邊括號與右邊括號的部份進行遞回,如此就可以完成排序的目的。
具體代碼如下:
package main
import (
"fmt"
)
const MAX = 10
var sortArray = []int{41, 24, 76, 11, 45, 64, 21, 69, 19, 36}
func main() {
fmt.Println("before sort:")
show()
quickSort(sortArray, 0, MAX-1)
fmt.Println("after sort:")
show()
}
func quickSort(sortArray []int, left, right int) {
if left < right {
key := sortArray[(left+right)/2]
i := left
j := right
for {
for sortArray[i] < key {
i++
}
for sortArray[j] > key {
j--
}
if i >= j {
break
}
swap(i, j)
}
quickSort(sortArray, left, i-1)
quickSort(sortArray, j+1, right)
}
}
// Swap the position of a and b
func swap(a, b int) {
sortArray[a], sortArray[b] = sortArray[b], sortArray[a]
}
// foreach
func show() {
for _, value := range sortArray {
fmt.Printf("%d\t", value)
}
} 2.3 快速排序最終版
先說明這個快速排序法的概念,它以最右邊的值s作比較的標準,將整個數列分為三個部份,一個是小于s的部份,一個是大于s的部份,一個是未處理的部份,如下所示 :

在排序的過程中,i 與 j 都會不斷的往右進行比較與交換,最后數列會變為以下的狀態:
然后將s的值置于中間,接下來就以相同的步驟會左右兩邊的數列進行排序的動作,如下所示:

整個演算的過程,直接摘錄書中的虛擬碼來作說明:
QUICKSORT(A, p, r)
if p < r
then q <- PARTITION(A, p, r)
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
end QUICKSORT
PARTITION(A, p, r)
x <- A[r]
i <- p-1
for j <- p to r-1
do if A[j] <= x
then i <- i+1
exchange A[i]<->A[j]
exchange A[i+1]<->A[r]
return i+1
end PARTITION 一個實際例子的演算如下所示:

具體代碼如下:
package main
import (
"fmt"
)
const MAX = 10
var sortArray = []int{41, 24, 76, 11, 45, 64, 21, 69, 19, 36}
func main() {
fmt.Println("before sort:")
show()
quickSort(sortArray, 0, MAX-1)
fmt.Println("after sort:")
show()
}
func quickSort(sortArray []int, left, right int) {
if left < right {
pos := partition(sortArray, left, right)
partition(sortArray, left, pos-1)
partition(sortArray, pos+1, right)
}
}
func partition(sortArray []int, left, right int) int {
key := sortArray[right]
i := left - 1
for j := left; j < right; j++ {
if sortArray[j] <= key {
i++
swap(i, j)
}
}
swap(i+1, right)
return i + 1
}
// Swap the position of a and b
func swap(a, b int) {
sortArray[a], sortArray[b] = sortArray[b], sortArray[a]
}
// foreach
func show() {
for _, value := range sortArray {
fmt.Printf("%d\t", value)
}
} 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!