From dfbb9e30e04d6b3d8a9cc074ab7a47bd4d54070d Mon Sep 17 00:00:00 2001 From: dudaodong Date: Mon, 17 Jan 2022 15:36:48 +0800 Subject: [PATCH] feat: algorithm package, BinarySearch and BinaryIterativeSearch functions --- algorithm/search.go | 45 ++++++++++++++++++++++++++++++++++++++++ algorithm/search_test.go | 25 ++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 algorithm/search.go create mode 100644 algorithm/search_test.go diff --git a/algorithm/search.go b/algorithm/search.go new file mode 100644 index 0000000..ad7a533 --- /dev/null +++ b/algorithm/search.go @@ -0,0 +1,45 @@ +// Copyright 2021 dudaodong@gmail.com. All rights reserved. +// Use of this source code is governed by MIT license + +// Package algorithm contain some basic algorithm functions. eg. sort, search, list, linklist, stack, queue, tree, graph. TODO +package algorithm + +import "github.com/duke-git/lancet/lancetconstraints" + +// BinarySearch search for target within a sorted slice, recursive call itself. +// If a target is found, the index of the target is returned. Else the function return -1 +func BinarySearch[T any](slice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int { + if highIndex < lowIndex || len(slice) == 0 { + return -1 + } + + midIndex := int(lowIndex + (highIndex-lowIndex)/2) + // slice[midIndex] > target + if comparator.Compare(slice[midIndex], target) == 1 { + return BinarySearch(slice, target, lowIndex, midIndex-1, comparator) + } else if comparator.Compare(slice[midIndex], target) == -1 { + return BinarySearch(slice, target, midIndex+1, highIndex, comparator) + } + + return midIndex +} + +// BinaryIterativeSearch search for target within a sorted slice. +// If a target is found, the index of the target is returned. Else the function return -1 +func BinaryIterativeSearch[T any](slice []T, target T, lowIndex, highIndex int, comparator lancetconstraints.Comparator) int { + startIndex := lowIndex + endIndex := highIndex + + var midIndex int + for startIndex <= endIndex { + midIndex = int(startIndex + (endIndex-startIndex)/2) + if comparator.Compare(slice[midIndex], target) == 1 { + endIndex = midIndex - 1 + } else if comparator.Compare(slice[midIndex], target) == -1 { + startIndex = midIndex + 1 + } else { + return midIndex + } + } + return -1 +} diff --git a/algorithm/search_test.go b/algorithm/search_test.go new file mode 100644 index 0000000..340123c --- /dev/null +++ b/algorithm/search_test.go @@ -0,0 +1,25 @@ +package algorithm + +import ( + "testing" + + "github.com/duke-git/lancet/internal" +) + +var sortedNumbers = []int{1, 2, 3, 4, 5, 6, 7, 8} + +func TestBinarySearch(t *testing.T) { + asssert := internal.NewAssert(t, "TestBinarySearch") + + comparator := &intComparator{} + asssert.Equal(4, BinarySearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)) + asssert.Equal(-1, BinarySearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)) +} + +func TestBinaryIterativeSearch(t *testing.T) { + asssert := internal.NewAssert(t, "TestBinaryIterativeSearch") + + comparator := &intComparator{} + asssert.Equal(4, BinaryIterativeSearch(sortedNumbers, 5, 0, len(sortedNumbers)-1, comparator)) + asssert.Equal(-1, BinaryIterativeSearch(sortedNumbers, 9, 0, len(sortedNumbers)-1, comparator)) +}