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 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" | ||||
| @@ -225,7 +242,18 @@ comments: true | ||||
| === "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" | ||||
| @@ -369,7 +397,25 @@ comments: true | ||||
| === "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" | ||||
| @@ -485,7 +531,22 @@ comments: true | ||||
| === "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" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user