数据结构与算法浅析

244 阅读2分钟

查找算法

1 二分查找

二分查找一种非常高效的查找算法。它的时间复杂度为 O(logn)。n 表示数据规模大小。有时甚至比O(1)效率更高。因为O(1)表示是一个常量值,当数量大道一定程度,O(logn)反而表现更好。

2 为什么要讲二分查找?

当数据量比较大的时候,相比循环遍历查找,二分查找的时间复杂度为O(logn),这就是优势。

当数据量比较小时,如10个,那跟顺序查找没什么区别了。但是,如果数据间的比较很耗时的时候(如:字符串比对),那么还是推荐二分查找,因为它能减少比较次数。

当数据量比较大的时候,因为二分查找依赖的是连续的数组结构来存储数据,如果超过1G或者2G的内存,那么大概率不会分配到连续的大块内存。

3 实现原理

分治思想,折半查找。

3.1 循环方式

 public boolean binarySearch(int[] aar, int n, int searchValue) {
        int low = 0;
        int high = n - 1;
        while (low <= high) {
//            int mid = low + (high - low) >> 1;  错误写法
            int mid = low + ((high - low) >> 1);
            int midValue = aar[mid];
            Log.d("binarySearch, mid:", "=  " + mid+", value: "+midValue);
            if (midValue == searchValue) {
                return true;
            }
            if (searchValue < midValue) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }

        }
        return false;

    }
int[] aa = {1, 2, 4, 5, 7, 8, 10, 33, 43, 55};

boolean b = binarySearch(aa, aa.length, 8);

3.2 递归方式

public boolean binarySearch2(int[] aar, int low, int high, int searchValue) {

//注意递归的退出条件 
    if (low > high) {
        return false;
    }
    int mid = low + ((high - low) >> 1);
    int midValue = aar[mid];

    if (midValue == searchValue) {
        return true;
    }
    if (searchValue < midValue) {
       return binarySearch2(aar, low, mid - 1, searchValue);
    } else {
       return binarySearch2(aar, mid + 1, high, searchValue);
    }
}

4 时间复杂度

O(logn)

5 二分查找使用场景

由于它依赖的 连续有序不重复 的数组,所以应用场景有一定的局限。

数据规模不能太小,太小没有优势。

也不能太大,太大无法申请连续内存。

6 二分查找的变形

在有序重复的数组中:

6.1 查找第一个等于给定值

6.1 查找最后一个等于给定值的元素

6.1 查找第一个等于给定值元素

6.1 查找第一个大于等于给定值的元素

6.1 查找最后一个小于等于给定值的元素

跳表(skip list)

如何在有序的单链表实现时间复杂度为O(logn)的查找方法?

方案:

给链表加索引层,即跳表。 每个几个节点则提取节点到索引层,索引节点指针down指向原链表的节点。 可以建立多个索引层,从而加快查找速度。

跳表浪费内存吗?

由于一般情况不会真正去存储某个对象实例,而是存储对象的引用。因此,不存在浪费很大内存。

索引动态更新

当插入大量数据的时候,如果在某两个索引节点插入的,那么该跳表就会退化为单链表。 因此,在插入的时候需要在当前锁定层数间产生一个随机数,在插入到链表的同时,也要在随机数索引层插入该数据。