mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-04 22:28:40 +08:00 
			
		
		
		
	Quick sort using go
This commit is contained in:
		
							
								
								
									
										128
									
								
								codes/go/chapter_sorting/quick_sort/quick_sort.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								codes/go/chapter_sorting/quick_sort/quick_sort.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					//File: quick_sort.go
 | 
				
			||||||
 | 
					//Created Time: 2022-12-12
 | 
				
			||||||
 | 
					//Author: msk397 (machangxinq@gmail.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package quick_sort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 快速排序
 | 
				
			||||||
 | 
					type QuickSort struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 快速排序(中位基准数优化)
 | 
				
			||||||
 | 
					type QuickSortMedian struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 快速排序(尾递归优化)
 | 
				
			||||||
 | 
					type QuickSortTailCall struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 哨兵划分 */
 | 
				
			||||||
 | 
					func (q *QuickSort) partition(nums []int, left, right int) int {
 | 
				
			||||||
 | 
						// 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
						i, j := left, right
 | 
				
			||||||
 | 
						for i < j {
 | 
				
			||||||
 | 
							for i < j && nums[j] >= nums[left] {
 | 
				
			||||||
 | 
								j-- // 从右向左找首个小于基准数的元素
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i < j && nums[i] <= nums[left] {
 | 
				
			||||||
 | 
								i++ // 从左向右找首个大于基准数的元素
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 元素交换
 | 
				
			||||||
 | 
							nums[i], nums[j] = nums[j], nums[i]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 将基准数交换至两子数组的分界线
 | 
				
			||||||
 | 
						nums[i], nums[left] = nums[left], nums[i]
 | 
				
			||||||
 | 
						return i // 返回基准数的索引
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 快速排序 */
 | 
				
			||||||
 | 
					func (q *QuickSort) quickSort(nums []int, left, right int) {
 | 
				
			||||||
 | 
						// 子数组长度为 1 时终止递归
 | 
				
			||||||
 | 
						if left >= right {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 哨兵划分
 | 
				
			||||||
 | 
						pivot := q.partition(nums, left, right)
 | 
				
			||||||
 | 
						// 递归左子数组、右子数组
 | 
				
			||||||
 | 
						q.quickSort(nums, left, pivot-1)
 | 
				
			||||||
 | 
						q.quickSort(nums, pivot+1, right)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 选取三个元素的中位数 */
 | 
				
			||||||
 | 
					func (q *QuickSortMedian) medianThree(nums []int, left, mid, right int) int {
 | 
				
			||||||
 | 
						if (nums[left] > nums[mid]) != (nums[left] > nums[right]) {
 | 
				
			||||||
 | 
							return left
 | 
				
			||||||
 | 
						} else if (nums[mid] < nums[left]) != (nums[mid] > nums[right]) {
 | 
				
			||||||
 | 
							return mid
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return right
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 哨兵划分(三数取中值)*/
 | 
				
			||||||
 | 
					func (q *QuickSortMedian) partition(nums []int, left, right int) int {
 | 
				
			||||||
 | 
						// 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
						med := q.medianThree(nums, left, (left+right)/2, right)
 | 
				
			||||||
 | 
						// 将中位数交换至数组最左端
 | 
				
			||||||
 | 
						nums[left], nums[med] = nums[med], nums[left]
 | 
				
			||||||
 | 
						// 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
						i, j := left, right
 | 
				
			||||||
 | 
						for i < j {
 | 
				
			||||||
 | 
							for i < j && nums[j] >= nums[left] {
 | 
				
			||||||
 | 
								j-- //从右向左找首个小于基准数的元素
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i < j && nums[i] <= nums[left] {
 | 
				
			||||||
 | 
								i++ //从左向右找首个大于基准数的元素
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							//元素交换
 | 
				
			||||||
 | 
							nums[i], nums[j] = nums[j], nums[i]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						//将基准数交换至两子数组的分界线
 | 
				
			||||||
 | 
						nums[i], nums[left] = nums[left], nums[i]
 | 
				
			||||||
 | 
						return i //返回基准数的索引
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 快速排序 */
 | 
				
			||||||
 | 
					func (q *QuickSortMedian) quickSort(nums []int, left, right int) {
 | 
				
			||||||
 | 
						// 子数组长度为 1 时终止递归
 | 
				
			||||||
 | 
						if left >= right {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 哨兵划分
 | 
				
			||||||
 | 
						pivot := q.partition(nums, left, right)
 | 
				
			||||||
 | 
						// 递归左子数组、右子数组
 | 
				
			||||||
 | 
						q.quickSort(nums, left, pivot-1)
 | 
				
			||||||
 | 
						q.quickSort(nums, pivot+1, right)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 哨兵划分 */
 | 
				
			||||||
 | 
					func (q *QuickSortTailCall) partition(nums []int, left, right int) int {
 | 
				
			||||||
 | 
						// 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
						i, j := left, right
 | 
				
			||||||
 | 
						for i < j {
 | 
				
			||||||
 | 
							for i < j && nums[j] >= nums[left] {
 | 
				
			||||||
 | 
								j-- // 从右向左找首个小于基准数的元素
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for i < j && nums[i] <= nums[left] {
 | 
				
			||||||
 | 
								i++ // 从左向右找首个大于基准数的元素
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 元素交换
 | 
				
			||||||
 | 
							nums[i], nums[j] = nums[j], nums[i]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 将基准数交换至两子数组的分界线
 | 
				
			||||||
 | 
						nums[i], nums[left] = nums[left], nums[i]
 | 
				
			||||||
 | 
						return i // 返回基准数的索引
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 快速排序(尾递归优化)*/
 | 
				
			||||||
 | 
					func (q *QuickSortTailCall) quickSort(nums []int, left, right int) {
 | 
				
			||||||
 | 
						// 子数组长度为 1 时终止
 | 
				
			||||||
 | 
						for left < right {
 | 
				
			||||||
 | 
							// 哨兵划分操作
 | 
				
			||||||
 | 
							pivot := q.partition(nums, left, right)
 | 
				
			||||||
 | 
							// 对两个子数组中较短的那个执行快排
 | 
				
			||||||
 | 
							if pivot-left < right-pivot {
 | 
				
			||||||
 | 
								q.quickSort(nums, left, pivot-1) // 递归排序左子数组
 | 
				
			||||||
 | 
								left = pivot + 1                 // 剩余待排序区间为 [pivot + 1, right]
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								q.quickSort(nums, pivot+1, right) // 递归排序右子数组
 | 
				
			||||||
 | 
								right = pivot - 1                 // 剩余待排序区间为 [left, pivot - 1]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								codes/go/chapter_sorting/quick_sort/quick_sort_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								codes/go/chapter_sorting/quick_sort/quick_sort_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					//File: quick_sort_test.go
 | 
				
			||||||
 | 
					//Created Time: 2022-12-12
 | 
				
			||||||
 | 
					//Author: msk397 (machangxinq@gmail.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package quick_sort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 快速排序
 | 
				
			||||||
 | 
					func TestQuickSort(t *testing.T) {
 | 
				
			||||||
 | 
						q := QuickSort{}
 | 
				
			||||||
 | 
						nums := []int{4, 1, 3, 1, 5, 2}
 | 
				
			||||||
 | 
						q.quickSort(nums, 0, len(nums)-1)
 | 
				
			||||||
 | 
						fmt.Println("快速排序完成后 nums = ", nums)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 快速排序(中位基准数优化)
 | 
				
			||||||
 | 
					func TestQuickSortMedian(t *testing.T) {
 | 
				
			||||||
 | 
						q := QuickSortMedian{}
 | 
				
			||||||
 | 
						nums := []int{4, 1, 3, 1, 5, 2}
 | 
				
			||||||
 | 
						q.quickSort(nums, 0, len(nums)-1)
 | 
				
			||||||
 | 
						fmt.Println("快速排序(中位基准数优化)完成后 nums = ", nums)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 快速排序(尾递归优化)
 | 
				
			||||||
 | 
					func TestQuickSortTailCall(t *testing.T) {
 | 
				
			||||||
 | 
						q := QuickSortTailCall{}
 | 
				
			||||||
 | 
						nums := []int{4, 1, 3, 1, 5, 2}
 | 
				
			||||||
 | 
						q.quickSort(nums, 0, len(nums)-1)
 | 
				
			||||||
 | 
						fmt.Println("快速排序(尾递归优化)完成后 nums = ", nums)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -109,7 +109,24 @@ comments: true
 | 
				
			|||||||
=== "Go"
 | 
					=== "Go"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```go title="quick_sort.go"
 | 
					    ```go title="quick_sort.go"
 | 
				
			||||||
 | 
					    /* 哨兵划分 */
 | 
				
			||||||
 | 
					    func partition(nums []int, left, right int) int {
 | 
				
			||||||
 | 
					        //以 nums[left] 作为基准数
 | 
				
			||||||
 | 
					        i, j := left, right
 | 
				
			||||||
 | 
					        for i < j {
 | 
				
			||||||
 | 
					            for i < j && nums[j] >= nums[left] {
 | 
				
			||||||
 | 
					                j-- //从右向左找首个小于基准数的元素
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            for i < j && nums[i] <= nums[left] {
 | 
				
			||||||
 | 
					                i++ //从左向右找首个大于基准数的元素
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            //元素交换
 | 
				
			||||||
 | 
					            nums[i], nums[j] = nums[j], nums[i]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        //将基准数交换至两子数组的分界线
 | 
				
			||||||
 | 
					        nums[i], nums[left] = nums[left], nums[i]
 | 
				
			||||||
 | 
					        return i //返回基准数的索引
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== "JavaScript"
 | 
					=== "JavaScript"
 | 
				
			||||||
@ -225,7 +242,18 @@ comments: true
 | 
				
			|||||||
=== "Go"
 | 
					=== "Go"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```go title="quick_sort.go"
 | 
					    ```go title="quick_sort.go"
 | 
				
			||||||
 | 
					    /* 快速排序 */
 | 
				
			||||||
 | 
					    func quickSort(nums []int, left, right int) {
 | 
				
			||||||
 | 
					        // 子数组长度为 1 时终止递归
 | 
				
			||||||
 | 
					        if left >= right {
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // 哨兵划分
 | 
				
			||||||
 | 
					        pivot := partition(nums, left, right)
 | 
				
			||||||
 | 
					        // 递归左子数组、右子数组
 | 
				
			||||||
 | 
					        quickSort(nums, left, pivot-1)
 | 
				
			||||||
 | 
					        quickSort(nums, pivot+1, right)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== "JavaScript"
 | 
					=== "JavaScript"
 | 
				
			||||||
@ -369,7 +397,25 @@ comments: true
 | 
				
			|||||||
=== "Go"
 | 
					=== "Go"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```go title="quick_sort.go"
 | 
					    ```go title="quick_sort.go"
 | 
				
			||||||
 | 
					    /* 选取三个元素的中位数 */
 | 
				
			||||||
 | 
					    func medianThree(nums []int, left, mid, right int) int {
 | 
				
			||||||
 | 
					        if (nums[left] > nums[mid]) != (nums[left] > nums[right]) {
 | 
				
			||||||
 | 
					            return left
 | 
				
			||||||
 | 
					        } else if (nums[mid] < nums[left]) != (nums[mid] > nums[right]) {
 | 
				
			||||||
 | 
					            return mid
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return right
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 哨兵划分(三数取中值)*/
 | 
				
			||||||
 | 
					    func partition(nums []int, left, right int) int {
 | 
				
			||||||
 | 
					        // 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
					        med := medianThree(nums, left, (left+right)/2, right)
 | 
				
			||||||
 | 
					        // 将中位数交换至数组最左端
 | 
				
			||||||
 | 
					        nums[left], nums[med] = nums[med], nums[left]
 | 
				
			||||||
 | 
					        // 以 nums[left] 作为基准数
 | 
				
			||||||
 | 
					        // 下同省略...
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== "JavaScript"
 | 
					=== "JavaScript"
 | 
				
			||||||
@ -485,7 +531,22 @@ comments: true
 | 
				
			|||||||
=== "Go"
 | 
					=== "Go"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ```go title="quick_sort.go"
 | 
					    ```go title="quick_sort.go"
 | 
				
			||||||
 | 
					    /* 快速排序(尾递归优化)*/
 | 
				
			||||||
 | 
					    func quickSort(nums []int, left, right int) {
 | 
				
			||||||
 | 
					        // 子数组长度为 1 时终止
 | 
				
			||||||
 | 
					        for left < right {
 | 
				
			||||||
 | 
					            // 哨兵划分操作
 | 
				
			||||||
 | 
					            pivot := partition(nums, left, right)
 | 
				
			||||||
 | 
					            // 对两个子数组中较短的那个执行快排
 | 
				
			||||||
 | 
					            if pivot-left < right-pivot {
 | 
				
			||||||
 | 
					                quickSort(nums, left, pivot-1)   // 递归排序左子数组
 | 
				
			||||||
 | 
					                left = pivot + 1				 // 剩余待排序区间为 [pivot + 1, right]
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                quickSort(nums, pivot+1, right)  // 递归排序右子数组
 | 
				
			||||||
 | 
					                right = pivot - 1				 // 剩余待排序区间为 [left, pivot - 1]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    ```
 | 
					    ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== "JavaScript"
 | 
					=== "JavaScript"
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user