• 检索算法之二分查找


    二分查找算法类似我们日常生活中常见的猜数字的游戏。假设给定从1-100这个排好序的数组,而猜数字的人只知道这个范围,你拿着一块写有数字的题板背对着他,让他猜你手里拿的的数字。

    估计有经验的人会先猜50,然后你说偏大了,偏小了,还是相等。如果偏大了或者是偏小了,他会用同样的方式在偏大或者偏小的数组中从新指定一个中间值来猜。。就这样不断重复如下去。。直到找到要猜的数字为止。

    类似图如下:

    算法分析如下:

    (1) 将数组的第一个位置设置为下边界( 0 )。
    (2) 将数组最后一个元素所在的位置设置为上边界(数组的长度减 1 )。
    (3) 若下边界等于或小于上边界,则做如下操作。
        a. 将中点设置为(上边界加上下边界)除以 2 。
        b. 如果中点的元素小于查询的值,则将下边界设置为中点元素所在下标加 1 。
        c. 如果中点的元素大于查询的值,则将上边界设置为中点元素所在下标减 1 。
        d. 如果没有找到,重复执行a,b,c.直到找到为止。否则中点元素即为要查找的数据,可以进行返回。

    算法代码如下:

    //   插入排序算法
    var insertionSort = function (arr) {
                var temp, inner;
                for (var outer = 1; outer <= arr.length-1; ++outer) {
                    temp = arr[outer];
                    inner = outer;
                    while (inner > 0 && (arr[inner-1] >= temp)) {
                        arr[inner] = arr[inner-1];
                        --inner;
                    }
                    arr[inner] = temp;
                }
            };
    
    //   二分查找算法
    var binSearch = function (arr, data){
                var upperBound = arr.length - 1;
                var lowerBound = 0;
                while(lowerBound <= upperBound){
                    var mid = Math.floor((upperBound + lowerBound) / 2);
                    console.log("当前中间点" + mid);
                    if (arr[mid] < data){
                        lowerBound = mid + 1;
                    }else if (arr[mid] > data){
                        upperBound = mid - 1;
                    } else {
                        return mid;
                    }
                }
    
                return -1;
            };
            var nums = [5,1,7,4,2,10,9,3,6,8];
            console.log(nums.toString());
            insertionSort(nums);
            console.log(nums.toString());
            console.log(nums[binSearch(nums, 6)]);

    结果如下:

    有一种情况我们似乎没有考虑到,那就是当数组中出现多个重复数据的情况下,怎么来确定我们想要查找的数据的出现次数。

    通过分析我们知道要查找的数字6的开始索引为5,结束索引为8,通过Math.floor取中间值的时候得到的索引就是7.也就是说7是处在5和8之间的一个数。所以我们可以利用这个7来遍历左右两边来查找重复值。

    var sameCount = function (arr, data){
                var count = 0;
                var position = binSearch(arr, data);
                if (position > -1){
                    ++count;
                    for (var i = (position - 1); i >= 0; --i){
                        if (arr[i] == data){
                            ++count;
                        } else {
                            break;
                        }
                    }
    
                    for (var j = (position + 1); j < arr.length; ++j){
                        if (arr[j] == data){
                            ++count;
                        } else {
                            break;
                        }
                    }
                }
    
                return count;
            };

    运行:

    var nums = [5,1,7,4,2,10,9,3,6,8,6,7,6,11,6];
            console.log(nums.toString());
            insertionSort(nums);
            console.log(nums.toString());
            console.log(sameCount(nums, 6));

    结果为:

  • 相关阅读:
    linux软件名规则
    给php开启mysql扩展
    centos6可用的Apache管理脚本
    Centos下设置redis开机自启动
    拆卸mysql
    如何判断是否在一个网路中
    linux 如何清理僵尸进程
    如何查找僵尸进程并Kill之,杀不掉的要查看父进程并杀之
    一张图告诉你php的命名空间和自动加载
    PHP的文件加载机制到底是什么目录
  • 原文地址:https://www.cnblogs.com/duhuo/p/5092144.html
Copyright © 2020-2023  润新知