mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-04 14:18:20 +08:00 
			
		
		
		
	feat(sort/search): support heap/selection_sort/binary_search_edge in go code (#521)
* feat(go): support binary search edge and testcase * feat(go): support selection sort and testcase * feat(go): support heap sort and testcase * Update selection_sort_test.go * Update selection_sort.go * Update heap_sort.go --------- Co-authored-by: Yudong Jin <krahets@163.com>
This commit is contained in:
		
							
								
								
									
										55
									
								
								codes/go/chapter_searching/binary_search_edge.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								codes/go/chapter_searching/binary_search_edge.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					// File: binary_search_edge.go
 | 
				
			||||||
 | 
					// Created Time: 2023-05-29
 | 
				
			||||||
 | 
					// Author: Reanon (793584285@qq.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package chapter_searching
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 二分查找最左一个元素 */
 | 
				
			||||||
 | 
					func binarySearchLeftEdge(nums []int, target int) int {
 | 
				
			||||||
 | 
						// 初始化双闭区间 [0, n-1]
 | 
				
			||||||
 | 
						i, j := 0, len(nums)-1
 | 
				
			||||||
 | 
						for i <= j {
 | 
				
			||||||
 | 
							// 计算中点索引 m
 | 
				
			||||||
 | 
							m := i + (j-i)/2
 | 
				
			||||||
 | 
							if nums[m] < target {
 | 
				
			||||||
 | 
								// target 在区间 [m+1, j] 中
 | 
				
			||||||
 | 
								i = m + 1
 | 
				
			||||||
 | 
							} else if nums[m] > target {
 | 
				
			||||||
 | 
								// target 在区间 [i, m-1] 中
 | 
				
			||||||
 | 
								j = m - 1
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// 首个小于 target 的元素在区间 [i, m-1] 中
 | 
				
			||||||
 | 
								j = m - 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if i == len(nums) || nums[i] != target {
 | 
				
			||||||
 | 
							// 未找到目标元素,返回 -1
 | 
				
			||||||
 | 
							return -1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return i
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 二分查找最右一个元素 */
 | 
				
			||||||
 | 
					func binarySearchRightEdge(nums []int, target int) int {
 | 
				
			||||||
 | 
						// 初始化双闭区间 [0, n-1]
 | 
				
			||||||
 | 
						i, j := 0, len(nums)-1
 | 
				
			||||||
 | 
						for i <= j {
 | 
				
			||||||
 | 
							// 计算中点索引 m
 | 
				
			||||||
 | 
							m := i + (j-i)/2
 | 
				
			||||||
 | 
							if nums[m] < target {
 | 
				
			||||||
 | 
								// target 在区间 [m+1, j] 中
 | 
				
			||||||
 | 
								i = m + 1
 | 
				
			||||||
 | 
							} else if nums[m] > target {
 | 
				
			||||||
 | 
								// target 在区间 [i, m-1] 中
 | 
				
			||||||
 | 
								j = m - 1
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// 首个大于 target 的元素在区间 [m+1, j] 中
 | 
				
			||||||
 | 
								i = m + 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if j < 0 || nums[j] != target {
 | 
				
			||||||
 | 
							// 未找到目标元素,返回 -1
 | 
				
			||||||
 | 
							return -1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return j
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -22,3 +22,15 @@ func TestBinarySearch(t *testing.T) {
 | 
				
			|||||||
		t.Errorf("目标元素 6 的索引 = %d, 应该为 %d", actual, expected)
 | 
							t.Errorf("目标元素 6 的索引 = %d, 应该为 %d", actual, expected)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestBinarySearchEdge(t *testing.T) {
 | 
				
			||||||
 | 
						target := 6
 | 
				
			||||||
 | 
						nums := []int{1, 3, 6, 6, 6, 6, 6, 10, 12, 15}
 | 
				
			||||||
 | 
						// 二分查找最左一个元素
 | 
				
			||||||
 | 
						indexLeft := binarySearchLeftEdge(nums, target)
 | 
				
			||||||
 | 
						fmt.Println("数组中最左一个元素 6 的索引 = ", indexLeft)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 二分查找最右一个元素
 | 
				
			||||||
 | 
						indexRight := binarySearchRightEdge(nums, target)
 | 
				
			||||||
 | 
						fmt.Println("数组中最右一个元素 6 的索引 = ", indexRight)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										44
									
								
								codes/go/chapter_sorting/heap_sort.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								codes/go/chapter_sorting/heap_sort.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					// File: heap_sort.go
 | 
				
			||||||
 | 
					// Created Time: 2023-05-29
 | 
				
			||||||
 | 
					// Author: Reanon (793584285@qq.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package chapter_sorting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 堆的长度为 n ,从节点 i 开始,从顶至底堆化 */
 | 
				
			||||||
 | 
					func siftDown(nums *[]int, n, i int) {
 | 
				
			||||||
 | 
						for true {
 | 
				
			||||||
 | 
							// 判断节点 i, l, r 中值最大的节点,记为 ma
 | 
				
			||||||
 | 
							l := 2*i + 1
 | 
				
			||||||
 | 
							r := 2*i + 2
 | 
				
			||||||
 | 
							ma := i
 | 
				
			||||||
 | 
							if l < n && (*nums)[l] > (*nums)[ma] {
 | 
				
			||||||
 | 
								ma = l
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if r < n && (*nums)[r] > (*nums)[ma] {
 | 
				
			||||||
 | 
								ma = r
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
 | 
				
			||||||
 | 
							if ma == i {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 交换两节点
 | 
				
			||||||
 | 
							(*nums)[i], (*nums)[ma] = (*nums)[ma], (*nums)[i]
 | 
				
			||||||
 | 
							// 循环向下堆化
 | 
				
			||||||
 | 
							i = ma
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 堆排序 */
 | 
				
			||||||
 | 
					func heapSort(nums *[]int) {
 | 
				
			||||||
 | 
						// 建堆操作:堆化除叶节点以外的其他所有节点
 | 
				
			||||||
 | 
						for i := len(*nums)/2 - 1; i >= 0; i-- {
 | 
				
			||||||
 | 
							siftDown(nums, len(*nums), i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// 从堆中提取最大元素,循环 n-1 轮
 | 
				
			||||||
 | 
						for i := len(*nums) - 1; i > 0; i-- {
 | 
				
			||||||
 | 
							// 交换根节点与最右叶节点(即交换首元素与尾元素)
 | 
				
			||||||
 | 
							(*nums)[0], (*nums)[i] = (*nums)[i], (*nums)[0]
 | 
				
			||||||
 | 
							// 以根节点为起点,从顶至底进行堆化
 | 
				
			||||||
 | 
							siftDown(nums, i, 0)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								codes/go/chapter_sorting/heap_sort_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								codes/go/chapter_sorting/heap_sort_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					// File: heap_sort_test.go
 | 
				
			||||||
 | 
					// Created Time: 2023-05-29
 | 
				
			||||||
 | 
					// Author: Reanon (793584285@qq.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package chapter_sorting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestHeapSort(t *testing.T) {
 | 
				
			||||||
 | 
						nums := []int{4, 1, 3, 1, 5, 2}
 | 
				
			||||||
 | 
						heapSort(&nums)
 | 
				
			||||||
 | 
						fmt.Println("堆排序完成后 nums = ", nums)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								codes/go/chapter_sorting/selection_sort.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								codes/go/chapter_sorting/selection_sort.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					// File: selection_sort.go
 | 
				
			||||||
 | 
					// Created Time: 2023-05-29
 | 
				
			||||||
 | 
					// Author: Reanon (793584285@qq.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package chapter_sorting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 选择排序 */
 | 
				
			||||||
 | 
					func selectionSort(nums []int) {
 | 
				
			||||||
 | 
						n := len(nums)
 | 
				
			||||||
 | 
						// 外循环:未排序区间为 [i, n-1]
 | 
				
			||||||
 | 
						for i := 0; i < n-1; i++ {
 | 
				
			||||||
 | 
							// 内循环:找到未排序区间内的最小元素
 | 
				
			||||||
 | 
							k := i
 | 
				
			||||||
 | 
							for j := i + 1; j < n; j++ {
 | 
				
			||||||
 | 
								if nums[j] < nums[k] {
 | 
				
			||||||
 | 
									// 记录最小元素的索引
 | 
				
			||||||
 | 
									k = j
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// 将该最小元素与未排序区间的首个元素交换
 | 
				
			||||||
 | 
							nums[i], nums[k] = nums[k], nums[i]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								codes/go/chapter_sorting/selection_sort_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								codes/go/chapter_sorting/selection_sort_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					// File: selection_sort_test.go
 | 
				
			||||||
 | 
					// Created Time: 2023-05-29
 | 
				
			||||||
 | 
					// Author: Reanon (793584285@qq.com)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package chapter_sorting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSelectionSort(t *testing.T) {
 | 
				
			||||||
 | 
						nums := []int{4, 1, 3, 1, 5, 2}
 | 
				
			||||||
 | 
						selectionSort(nums)
 | 
				
			||||||
 | 
						fmt.Println("选择排序完成后 nums = ", nums)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user