feat(Go-Tool):新增二分法查找算法及其单测、插入查询及其单测、lomuto划分查询第k小元素及其单测、归并排序及其单测、快速排序及其单测.

This commit is contained in:
huangzj
2020-08-20 09:28:35 +08:00
parent fa58e1a97f
commit c2aca17567
12 changed files with 385 additions and 8 deletions
+28
View File
@@ -0,0 +1,28 @@
/*
* @Author : huangzj
* @Time : 2020/8/18 17:45
* @Description:二分查找法,对于有序数组进行查找
*/
package search
func BinarySearch(list []int, value int) int {
low := 0
high := len(list) - 1
var mid int
for low <= high {
mid = (low + high) >> 1 //相当于(low + high) / 2
if value == list[mid] {
return mid
}
if value < list[mid] {
high = mid - 1
} else {
low = mid + 1
}
}
return -1
}
+42
View File
@@ -0,0 +1,42 @@
/*
* @Author : huangzj
* @Time : 2020/8/18 17:59
* @Description
*/
package search
import (
"fmt"
"testing"
)
func TestBinarySearch(t *testing.T) {
evenNumList := []int{1, 2, 3, 5, 6, 7, 9, 10, 22, 111, 333, 431}
for _, r := range evenNumList {
position := BinarySearch(evenNumList, r)
fmt.Println(position)
}
position := BinarySearch(evenNumList, 999)
fmt.Println(position)
position = BinarySearch(evenNumList, -10)
fmt.Println(position)
fmt.Println()
oddNumList := []int{1, 2, 3, 5, 6, 7, 9, 10, 22, 111, 333, 431, 3211}
for _, r := range oddNumList {
position := BinarySearch(oddNumList, r)
fmt.Println(position)
}
position = BinarySearch(oddNumList, 999)
fmt.Println(position)
position = BinarySearch(oddNumList, -10)
fmt.Println(position)
}
+34
View File
@@ -0,0 +1,34 @@
/*
* @Author : huangzj
* @Time : 2020/8/19 10:24
* @Description
*
*/
package search
func InsertionSearch(list []int, value int) int {
low := 0
high := len(list) - 1
var mid int
//插值查找这边如果数字和起始数字差别大的话,计算出来的下标会越界挺多的
if value > list[high-1] || value < list[0] {
return -1
}
for low < high {
mid = low + (high-low)*(value-list[low])/(list[high]-list[low])
if value == list[mid] {
return mid
}
if value < list[mid] {
high = mid - 1
} else {
low = mid + 1
}
}
return -1
}
+7
View File
@@ -0,0 +1,7 @@
从折半查找中可以看出,折半查找的查找效率还是不错的。可是为什么要折半呢?为什么不是四分之一、八分之一呢?打个比方,在牛津词典里要查找“apple”这个单词,会首先翻开字典的中间部分,然后继续折半吗?
肯定不会,对于查找单词“apple”,我们肯定是下意识的往字典的最前部分翻去,而查找单词“zero”则相反,我们会下意识的往字典的最后部分翻去。
所以在折半查找法的基础上进行改造就出现了插值查找法,也叫做按比例查找。所以插值查找与折半查找唯一不同的是在于mid的计算方式上,它的计算方式为:
mid = low + (high - low) * (searchValue - data[low]) / (data[high] - data[low])
插值查找的时间复杂度也是O(log2n),但是对于数据集合较长,且关键字分布比较均匀的数据集合来说,插值查找的算法性能比折半查找要好,其它的则不适用。
+42
View File
@@ -0,0 +1,42 @@
/*
* @Author : huangzj
* @Time : 2020/8/19 10:38
* @Description
*/
package search
import (
"fmt"
"testing"
)
func TestInsertionSearch(t *testing.T) {
evenNumList := []int{1, 2, 3, 5, 6, 7, 9, 10, 22, 111, 333, 431}
for _, r := range evenNumList {
position := InsertionSearch(evenNumList, r)
fmt.Println(position)
}
position := InsertionSearch(evenNumList, 999)
fmt.Println(position)
position = InsertionSearch(evenNumList, -10)
fmt.Println(position)
fmt.Println()
oddNumList := []int{1, 2, 3, 5, 6, 7, 9, 10, 22, 111, 333, 431, 3211}
for _, r := range oddNumList {
position := InsertionSearch(oddNumList, r)
fmt.Println(position)
}
position = InsertionSearch(oddNumList, 999)
fmt.Println(position)
position = InsertionSearch(oddNumList, -10)
fmt.Println(position)
}
+4 -4
View File
@@ -11,7 +11,7 @@ package search
//start : 开始比较的数字下标
//end :结束比较的数字下标
//作用说明:
func partition(list []int, start int, end int) int {
func LomutoPartition(list []int, start int, end int) int {
moveSubscript := start
compareValue := list[start]
for i := start + 1; i <= end; i++ {
@@ -27,13 +27,13 @@ func partition(list []int, start int, end int) int {
func LomutoQuiteSelect(list []int, pointPosition int) int {
positionCheck(pointPosition, len(list)) //下标校验
nowPosition := partition(list, 0, len(list)-1)
nowPosition := LomutoPartition(list, 0, len(list)-1)
//循环进行lomuto划分处理,知道找到我们需要的那个位置的元素
for nowPosition != pointPosition-1 {
if nowPosition > pointPosition-1 {
nowPosition = partition(list, 0, nowPosition)
nowPosition = LomutoPartition(list, 0, nowPosition)
} else {
nowPosition = partition(list, nowPosition+1, len(list)-1)
nowPosition = LomutoPartition(list, nowPosition+1, len(list)-1)
}
}
+2 -2
View File
@@ -13,13 +13,13 @@ import (
func TestPartition(t *testing.T) {
list := []int{99, 1, 2, 3, 4, 100, 200, 90, 5}
s := partition(list, 0, 9-1)
s := LomutoPartition(list, 0, 9-1)
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s))
for _, r := range list {
fmt.Print(r, " ")
}
s = partition(list, 0, 9-1)
s = LomutoPartition(list, 0, 9-1)
fmt.Println(fmt.Sprintf("当前第一个元素应该存在位置为:%d", s))
for _, r := range list {
fmt.Print(r, " ")