{"id":24309655,"url":"https://github.com/nelsonbn/algorithms-data-structures-binary-search","last_synced_at":"2026-04-21T02:02:24.165Z","repository":{"id":173681786,"uuid":"651134877","full_name":"NelsonBN/algorithms-data-structures-binary-search","owner":"NelsonBN","description":"Algorithms and Data Structures - Binary search","archived":false,"fork":false,"pushed_at":"2025-03-02T13:28:10.000Z","size":82,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-02T14:28:31.673Z","etag":null,"topics":["algorithms","algorithms-and-data-structures","binary-search","data-structures"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NelsonBN.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-08T15:12:20.000Z","updated_at":"2025-03-02T13:28:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"559b7263-53a8-4f05-a8f5-5291cce4958e","html_url":"https://github.com/NelsonBN/algorithms-data-structures-binary-search","commit_stats":null,"previous_names":["nelsonbn/algorithms-data-structures-binary-search"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NelsonBN%2Falgorithms-data-structures-binary-search","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NelsonBN%2Falgorithms-data-structures-binary-search/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NelsonBN%2Falgorithms-data-structures-binary-search/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NelsonBN%2Falgorithms-data-structures-binary-search/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NelsonBN","download_url":"https://codeload.github.com/NelsonBN/algorithms-data-structures-binary-search/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242277688,"owners_count":20101545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","algorithms-and-data-structures","binary-search","data-structures"],"created_at":"2025-01-17T05:16:03.044Z","updated_at":"2026-04-21T02:02:24.063Z","avatar_url":"https://github.com/NelsonBN.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Algorithms and Data Structures - Binary search\n\n\n## What is binary search?\n\nBinary search is a search algorithm that finds the position of a target value within a sorted array. Binary search compares the target value to the middle element of the array. If they are not equal, the half in which the target cannot lie is eliminated and the search continues on the remaining half, again taking the middle element to compare to the target value, and repeating this until the target value is found. If the search ends with the remaining half being empty, the target is not in the array.\n\nThe concept behind binary search is to \"divide and conquer\" continuously dividing the number of candidate elements in half at each iteration. This property enables the algorithm to have a time complexity of `O(log n)`.\n\n### Pros\n* `O(log n)` time complexity. It's one of the fastest search algorithms;\n* It's simple to implement;\n* It's easy to understand;\n\n\n### Cons\n* It only works on sorted arrays;\n* Time complexity for insertion is `O(log n)`. I put this as a cons because exists algorithms with `O(1)` time complexity for insertion, but that is not a big deal for many cases because `O(log n)` is still very good performance;\n\n\n### Requirements\n* The array must be sorted;\n* To use the binary search algorithm, the array must be random-access, which means that elements can be accessed using their index;\n* The data stored in the array must be of a type that supports comparison. For example `a \u003c b`, `a \u003e b`, `a == b`;\n* The comparison used to search value in the array must be the same used to sort or insert values in the array;\n\n### Time complexity (Binary search vs. linear search)\n![Time complexity](./docs/binary-search-vs-linear-search.png)\nIn the previous graph, we can see the number of steps required to find a value increases very slowly as the size of the array increases using binary search in comparison with linear search.\n\n### Demo animation\n\n[Binary search vs linear search](https://www.cs.usfca.edu/~galles/visualization/Search.html)\n\n\n## Implementations\n\nThe binary search algorithm can be implemented in different ways. Interative and recursive are the most common implementations.\n\nFor my examples, I am going to use the C#, but the algorithm can be implemented in any language. Only the syntax will change.\n\n### Interative implementation\n\n```csharp\nstatic int BinarySearch(int[] array, int search)\n{\n    var left = 0;\n    var right = array.Length - 1;\n\n    while (left \u003c= right)\n    {\n        var middle = left + ((right - left) / 2);\n        if (array[middle] == search)\n        {\n            return middle;\n        }\n\n        if (array[middle] \u003c search)\n        {\n            left = middle + 1;\n        }\n        else\n        {\n            right = middle - 1;\n        }\n    }\n\n    return -1;\n}\n```\n\n### Recursive implementation\n\n```csharp\nstatic int BinarySearch(int[] array, int search, int left, int right)\n{\n    while(left \u003c= right)\n    {\n        var middle = left + ((right - left) / 2);\n\n        if(search == array[middle])\n        {\n            return middle;\n        }\n\n        if(search \u003e array[middle])\n        {\n            return BinarySearch(array, search, middle + 1, right);\n        }\n\n        return BinarySearch(array, search, left, middle - 1);\n    }\n\n    return -1;\n}\n```\n\n### Some tips to implement binary search\n\n#### Found the middle index\n\nIt is very common to see the middle index calculation as `(left + right) / 2`, but this is not the best way to do it. If the array is very large, the sum of `left` and `right` can overflow the maximum value of the integer type. To avoid this problem, we can use the following formula: `left + ((right - left) / 2)`.\n\nLet's break down this formula piece by piece to understand the problem.\n\n```csharp\nConsole.WriteLine($\"MaxInt: {int.MaxValue:n0}\"); // MaxInt: 2 147 483 647\n\nvar left = int.MaxValue - 1_000;\nvar right = int.MaxValue - 300;\n\nConsole.WriteLine($\"left: {left:n0}\"); // left: 2 147 482 647\nConsole.WriteLine($\"right: {right:n0}\"); // right: 2 147 483 347\n\n// Bad why\nvar badWhyStep1 = left + right;\nConsole.WriteLine($\"Bad why -\u003e left + right: {badWhyStep1:n0}\"); // Bad why -\u003e left + right: -1 302\nvar badWhyStep2 = badWhyStep1 / 2;\nConsole.WriteLine($\"Bad why -\u003e (left + right) / 2: {badWhyStep2:n0}\"); // Bad why -\u003e (left + right) / 2: -651\n\n// Good why\nvar goodWhyStep1 = right - left;\nConsole.WriteLine($\"Good why -\u003e right - left: {goodWhyStep1:n0}\"); // Good why -\u003e right - left: 700\nvar goodWhyStep2 = goodWhyStep1 / 2;\nConsole.WriteLine($\"Good why -\u003e (right - left) / 2: {goodWhyStep2:n0}\"); // Good why -\u003e (right - left) / 2: 350\nvar goodWhyStep3 = left + goodWhyStep2;\nConsole.WriteLine($\"Good why -\u003e left + ((right - left) / 2): {goodWhyStep3:n0}\"); // Good why -\u003e left + ((right - left)) / 2: 2 147 482 997 // right: 2 147 483 147\n```\n\nAs you can see, for a large array, the `left + right` operation can overflow the maximum value of the integer type and return a worng value.\n\n#### Use shift operator\nIn the built-in binary search implementation of some languages, you can see the use of the shift operator `\u003e\u003e 1` to divide the value by 2.\nFirst we can do this because the shift operation `\u003e\u003e 1` is equivalent to the division by 2. Second because the bitwise operations are more close to the machine code and can be faster than the division operation.\n\n**Before**\n```csharp\nvar middle = left + ((right - left) / 2);\n```\n\n**After**\n```csharp\nvar middle = left + ((right - left) \u003e\u003e 1);\n```\n\n#### Return the complement of the index if the value is not found\n\nIn the previous examples, I returned `-1` when the value was not found. Using the condition `index \u003c 0` serves as an indicator that the value was not located. However, suppose we also want to use the same implementation to identify the next suitable index for inserting the value. In this scenario, the index `-1` is not particularly helpful.\n\nWe know that when we attempt to search for a value in our sorted array, the algorithm will halt either when it finds the value or when it doesn't. If the value is not found, the left index will point to the position where the value should be inserted.\n\nWith this in mind, if the value is not found, we can simply use the `~` operator. This operator inverts all bits, including the sign bit, resulting in a negative value. We can use this negative value to signify that the value was not found. However, if we apply the complement operation once more, we obtain the position where the value should be inserted. This approach allows us to use the same implementation for both finding a value and determining the next possible insertion point.\n\n```csharp\npublic void Add(int item)\n{\n    var position = Search(item);\n    if(position \u003c 0)\n    {\n        position = ~position;\n    }\n    items.Insert(position, item);\n}\n\npublic int Search(int item)\n{\n    // ...\n    // When the value is not found\n    return ~left;\n}\n```\n\n#### Binary search is not only for numbers\n\nThe binary search algorithm does not work only with numbers. It can be used with any type of data that supports comparison. For example in C# you can a class and implement the `IComparable` interface to to define the comparison logic.\n\n```csharp\npublic int BinarySearch(T item)\n{\n    var left = 0;\n    var right = _items.Count - 1;\n\n    while(left \u003c= right)\n    {\n        var middle = left + ((right - left) \u003e\u003e 1);\n\n        if(_items[middle].CompareTo(item) == 0)\n        {\n            return middle;\n        }\n\n        if(_items[middle].CompareTo(item) \u003c 0)\n        {\n            left = middle + 1;\n        }\n        else\n        {\n            right = middle - 1;\n        }\n    }\n\n    return ~left;\n}\n\npublic class Person : IComparable\u003cPerson\u003e\n{\n    public string? FirstName { get; set; }\n    public string? LastName { get; set; }\n    public int Age { get; set; }\n\n    public int CompareTo(Person? other)\n    {\n        if(other is null)\n        {\n            return -1;\n        }\n\n        var result = Age.CompareTo(other.Age);\n        if(result != 0)\n        {\n            return result;\n        }\n\n        result = compareTo(FirstName, other?.FirstName);\n        if(result != 0)\n        {\n            return result;\n        }\n\n        return compareTo(LastName, other?.LastName);\n\n\n        static int compareTo(string? left, string? right)\n        {\n            if(left is null \u0026\u0026 right is null)\n            {\n                return 0;\n            }\n\n            if(left is null)\n            {\n                return -1;\n            }\n\n            if(right is null)\n            {\n                return 1;\n            }\n\n            return left.CompareTo(right);\n        }\n    }\n}\n```\n\n\n## References\n- [Other Algorithms \u0026 Data Structures](https://github.com/NelsonBN/algorithms-data-structures)\n- [Medium Post](https://medium.com/@NelsonBN/algorithms-and-data-structuresbinary-search-a12594183c0d)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnelsonbn%2Falgorithms-data-structures-binary-search","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnelsonbn%2Falgorithms-data-structures-binary-search","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnelsonbn%2Falgorithms-data-structures-binary-search/lists"}