A simple and practical algorithm binary search

Time:2021-1-21

catalog
  • Algorithm overview
  • Application
  • Algorithm principle
  • Algorithm implementation (C #)
  • Practical application: searching boundary value by dichotomy
  • Reference article

Algorithm overview

Binary search(English: binary search), also known asHalf search(English: half interval search) is a kind ofFinding specific elements in an ordered arrayThe search algorithm of the algorithm. Therefore, the premise of binary search is that the array must be ordered.
Time complexity, space complexityPlease refer to the figure below (the picture is from Wikipedia)

Application

Binary search only appliesSequential storage structure. In order to keep the order of the table, a large number of nodes must be moved when inserting or deleting in the order structure. Therefore,Binary search is especially suitable for linear tables which are rarely changed and often need to be searched

For those linear tables which need to be changed frequently and find little, we can use linked list as storage structure to search in order.Binary search cannot be realized on linked list (to be more precise, binary search is not worth the loss)

Algorithm principle

The basic idea of binary search is as follows

  • set upR[low… … high] is the current search interval
  • First determine theMid = Low + ((high – low) > > 1)
  • Then compare the target value to be searched with ary [mid]: if it is equal, the search succeeds and returns to this position; otherwise, a new search interval must be determined to continue the binary search.
  • If are [mid] > target, then the order of the table shows that are [mid] > target . high] is greater than k, so if there is a node with the keyword equal to target in the table, it must be the sub table R [low So the new search interval isLeft sub table are [low …mid-1]
  • If ary [mid]Right sub table ary [mid + 1 high]。
  • The next search is for the new search interval.

Therefore, starting from the initial search interval R [0.. n-1], each comparison with the node keywords at the midpoint of the current search interval can determine whether the search is successful or not. If not, the current search interval will be reduced by half. This process is repeated until the node whose keyword is target is found, or until the current search interval is empty(high)So far.

Algorithm implementation (C #)

The algorithm is based on C #. There are two implementations: simple and generic. Each implementation is divided into recursive version and while loop version. In practice,It is recommended to use the binary search of while loop version
The algorithm code is as follows:

//This algorithm assumes that the array is sorted; otherwise, the result will be incorrect.
    class BinarySearch
    {
        //Do not use mid = (high + low) / 2, which may cause overflow
        #Region is simple
        //Recursive version           
        public static int Recursive(int[] ary, int target)
        {
            return Recursive(ary, 0, ary.Length-1, target);           
        }
        static int Recursive(int[] ary, int low, int high, int target)
        {
            if (high < low) return -1;    
            int mid = low + ((high - low) >> 1);
            if (ary[mid] == target) return mid;
            if (ary[mid] > target)
            {
                return Recursive(ary, low, mid-1, target);
            }
            else
            {
                return Recursive(ary, mid + 1, high, target);
            }            
        }
        //While loop version
        public static int WhileLoop(int[] ary, int target)
        {
            int low = 0; 
            int high = ary.Length - 1;
            while (low <= high)
            {                                
                int mid = low + ((high - low) >> 1);
                if (ary[mid] == target) return mid;
                if (ary[mid] > target)
                {
                    high = mid - 1;
                }
                else 
                {
                    low = mid + 1;
                }
            }
            return -1;
        }
        #endregion
        
        #Region generics
        //Recursive version           
        public static int RecursiveT(T[] ary, T target) where T : IComparable
        {
            return RecursiveT(ary, 0, ary.Length - 1, target);
        }
        static int RecursiveT(T[] ary, int low, int high, T target) where T : IComparable
        {               
            if (high < low) return -1;            
            int mid = low + ((high - low) >> 1);
            int cr = Comparer.Default.Compare(ary[mid], target);             
            if(cr==0)return mid;
            if (cr > 0)
            {
                return RecursiveT(ary, low, mid - 1, target);
            }
            else 
            {
                return RecursiveT(ary, mid + 1, high, target);
            }            
        }
        //While loop version
        public static int WhileLoopT(T[] ary, T target) where T : IComparable
        {
            int low = 0;
            int high = ary.Length - 1;
            while (low <= high)
            {                
                int mid = low + ((high - low) >> 1);
                int cr = Comparer.Default.Compare(ary[mid], target);                
                if (cr == 0) return mid;
                if (cr>0)
                {
                    high = mid - 1;
                }
                else 
                {
                    low = mid + 1;
                }               
            }
            return -1;
        }
        //The while loop version is recommended by default
        public static int DefaultT(T[] ary, T target) where T : IComparable 
        {            
            return WhileLoopT(ary, target);
        }
        #endregion 
    }

The test code is as follows:

//Array must be ordered
//The integer array is incremented in ascending order to check the result
int[] ary = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }; 
long[] aryT = new long[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };            
int target = 8;
int r = BinarySearch.Recursive(ary, target);
int w = BinarySearch.WhileLoop(ary, target);
int rT = BinarySearch.RecursiveT(ary, target);
int wT = BinarySearch.WhileLoopT(ary, target);
Console.WriteLine("r={0} w={1} rT={2} wT={3}", r, w, rT, wT);

Practical application: searching boundary value by dichotomy

Find a number x in the set that is greater than (less than) the target number T, so that any number in the set is either greater than (less than) or equal to x, or less than (greater than) or equal to t.
For example: give arrays and targets

int array = {2, 3, 5, 7, 11, 13, 17};
int target = 7;

So the upper bound should be 11, because it’s “just right” greater than 7; the lower bound is 5, because it’s “just right” less than 7.

This problem can’t be solved by binary search code directly. We need to modify the code, but the solution is binary search.

The implementation code is as follows:

//Finding the upper bound by dichotomy
static int BSearchUpperBound(int[] ary, int target)
{           
    int low = 0;
    int high = ary.Length - 1;            
    while (low <= high)
    {
        int mid = low + ((high - low) >> 1);
        if (high == low) 
        {
            if (ary[mid] > target) return mid;
            else return -1;            
        }
        if (ary[mid] > target)
        {
            //When the number currently found is greater than the target number, it may be the number we are looking for, so we need to keep this index
            high = mid ;
        }
        else
        {
            //When the number currently found is less than or equal to the target number, continue to take the interval upward
            low = mid + 1;
        }
    }
    return -1;        
}
 //Finding the lower bound by dichotomy
static  int BSearchLowerBound(int[] ary, int target)
{
    int low = 0;
    int high = ary.Length - 1;
    while (low <= high)
    {
        //Round up is used when taking the middle index, otherwise low cannot climb up to the lower bound
        int mid = low + ((high - low + 1) >> 1);
        if (high == low)
        {
            if (ary[mid] < target) return mid;
            else return -1;
        }               
        if (ary[mid] >= target)
        {
            //When the number currently found is greater than or equal to the target number, continue to take the interval downward
            high = mid-1;
        }
        else
        {
            //When the number currently found is less than the target number, it may be the number we are looking for, so we need to keep this index
            low = mid;
        }
    }
    return -1;
}

The test code is as follows:

//Looking for boundary value
int[] array =new int[]{ 2, 3, 5, 7, 11, 13, 17 };
int target =6;
//Searching for the last year's Olympic Games by dichotomy
int up = BSearchUpperBound(array, target);
int lo=BSearchLowerBound(array, target);

Reference article

Binary search_ Search: a short book
Baidu Encyclopedia
Binarysearch. Net source code
Binary search principle analysis, decision tree and its variant CSDN
Implementation and application of binary search method — CSDN