又是程序员小灰的漫画,关于二分查找的,我写了个简单的实现。
不过实际写代码的过程中并不一帆风顺,有些特殊情况还是没有考虑到。
下面是源码:
var (
ErrNotFound = errors.New("not found target")
)
func BinarySearch(data []int, target int) (int,error) {
dataAmount := len(data)
if dataAmount == 0 {
return 0, ErrNotFound
}
start := 0
end := dataAmount-1
testIndex := (start+end)/2
for {
if data[testIndex] > target {
end = testIndex
testIndex = (start+end)/2
} else if data[testIndex] < target {
start = testIndex
testIndex = (start+end)/2
} else {
return testIndex,nil
}
if start == end {
break
}
if end == start+1 {
if target == data[end] {
return end,nil
}
if target == data[start] {
return start,nil
}
break
}
}
return 0,ErrNotFound
}
下面是测试用例:
func TestBinarySearch(t *testing.T) {
var testcases = []struct{
data []int
target int
index int
err error
}{
{[]int{1,2,3,4,5,6,7,8,9}, 1,0,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 2,1,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 3,2,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 4,3,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 5,4,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 6,5,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 7,6,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 8,7,nil},
{[]int{1,2,3,4,5,6,7,8,9}, 9,8,nil},
{[]int{1,2,3,4}, 1,0,nil},
{[]int{1,2,3,4}, 2,1,nil},
{[]int{1,2,3,4}, 3,2,nil},
{[]int{1,2,3,4}, 4,3,nil},
{[]int{}, 3, 0, ErrNotFound},
{[]int{1}, 3, 0, ErrNotFound},
{[]int{1}, 1, 0, nil},
}
for i, testcase := range testcases {
retIndex, err := BinarySearch(testcase.data, testcase.target)
if retIndex != testcase.index || err != testcase.err {
t.Errorf("testcases[%d] binary search failed", i)
t.Error("test datas:", testcase.data)
t.Errorf("test target:%d, get index[%d],get error[%v], want index[%d],want error[%v]",
testcase.target,retIndex, err, testcase.index, testcase.err)
return
}
}
}