📌算法Go语言描述📌algorithm📌search.go
package algorithm

/*
折半计算 mid=(low+higt)/2
如需防止溢出可变形为 mid=low+(high-low)/2
*/

//二分查找/折半查找,前提是线性表中的记录必须是有序(通常从小到大有序)。时间复杂度O(logn)。
func BinarySearch(arr []int, target int) int {
	low, high := 0, len(arr)-1
	for low <= high {
		mid := (low + high) >> 1
		if target < arr[mid] {
			high = mid - 1
		} else if target > arr[mid] {
			low = mid + 1
		} else {
			return mid
		}
	}
	return -1
}

//查找最先出现的位置
func BinarySearchBegin(arr []int, target int) int {
	end := len(arr) - 1
	low, high := 0, end
	for low <= high {
		mid := (low + high) >> 1
		if target > arr[mid] {
			low = mid + 1
		} else {
			high = mid - 1 //小于或等于都收缩右边界
		}
	}
	if low > end || arr[low] != target {
		return -1
	}
	return low
}

//查找最后出现的位置
func BinarySearchEnd(arr []int, target int) int {
	low, high := 0, len(arr)-1
	for low <= high {
		mid := (low + high) >> 1
		if target < arr[mid] {
			high = mid - 1
		} else {
			low = mid + 1 //大于或等于都收缩左边界
		}
	}
	if high < 0 || arr[high] != target {
		return -1
	}
	return high
}

//查找目标首尾出现的位置
func BinarySearchRange(arr []int, target int) (int, int) {
	end := len(arr) - 1
	//先找左边界low
	low, high := 0, end
	for low <= high {
		mid := (low + high) >> 1
		if target > arr[mid] {
			low = mid + 1
		} else {
			high = mid - 1
		}
	}
	if low > end || arr[low] != target {
		return -1, -1
	}
	//再找右边界r,有左边界必然右边界可求,不用判断越界
	l, r := low, end
	for l <= r {
		m := (l + r) >> 1
		if target < arr[m] {
			r = m - 1
		} else {
			l = m + 1
		}
	}
	return low, r
}

//插值查找基于二分查找,将查找点的选择改进为自适应选择,提高查找效率,时间复杂度同为O(logn)。
//对于表长较大,而关键字分布又比较均匀的查找表来说,插值查找的平均性能比折半查找要好。
func InsertSearch(arr []int, target int) int {
	low := 0
	high := len(arr) - 1
	for low <= high {
		mid := low + (target-arr[low])/(arr[high]-arr[low])*(high-low)
		if target > arr[mid] {
			low = mid + 1
		} else if target < arr[mid] {
			high = mid - 1
		} else {
			return mid
		}
	}
	return -1
}