二分查找为什么不能用于链表

二分查找不能用于链表的原因:二分查找是一种高效的查找算法,适用于已排序且静态的数组或列表,而链表不支持随机内存访问,即每一个节点的地址不能在O(1)的时间复杂度内获得,因此二分查找不能使用于链表。

一、二分查找不能用于链表的原因

链表的每一个节点的地址不能在O(1)的时间复杂度内获得,二分查找是一种高效的查找算法,适用于已排序且静态的数组或列表。然而,二分查找不能使用于链表,因为链表不支持随机内存访问。如下图,名列前茅行是地址,第二行是数组(顺序表),第三行是链表。

二分查找为什么不能用于链表

可以看到,在数组(线性表)中,a[i]的地址就是 &a[0]+sizeof(int)*i (a+i),这样你对于一次二分查找 [l,r) 区域,通过简单的计算得到中间值 mid = (l+r)/2 对应的值而对于链表,每个节点对应的坐标是不确定的,比如查找 [0,4) ,需要比较mid = (0+4)/2 = 2 的值,然后电脑就开始找,从0开始往后找到1,找到1再往下找,遍历很多次之后才能找到 a[2] 位于0x0010 这个地址,理论而言,我们每次都需要遍历整个查询区域二分之一长度的数据,即 T(n/2) 。再加上二分查找本身的 T(logn) 总的时间复杂度是 O(nlogn) 甚至比直接遍历链表查询更慢。

二、二分查找的原理及实现

二分查找的实现原理非常简单,首先要有一个有序的列表。但是如果没有,则该怎么办?可以使用排序算法进行排序。以升序数列为例,比较一个元素与数列中的中间位置的元素的大小,如果比中间位置的元素大,则继续在后半部分的数列中进行二分查找;如果比中间位置的元素小,则在数列的前半部分进行比较;如果相等,则找到了元素的位置。每次比较的数列长度都会是之前数列的一半,直到找到相等元素的位置或者最终没有找到要找的元素。

我们先来想象一下,如果数列中有 3 个数,则先与第 2 个数进行比较,如果比第 2 个数大,则与第 2 个数右边的数列进行二分查找,这时这个数列就剩下一个数了,直接比较是否相等即可。所以在 3 个数的时候非常多比较两次。同理,在有 4 个数的时候,我们与中间数进行比较,一般中间数是首加末除以 2 算出来的,这时我们算出来的中间数是 (1+4)/2 等于 2,所以我们把要查找的数与第 2 个数比较,若比第 2 个数小,则直接与第 1 个数比较;否则与后面两个数进行二分查找,这时的中间数是 (3+4)/2 等于 3,也就是后半部分的第 1 个数。再接着进行比较,相等则找到相应的元素,小于则没有这个数(因为左边所有的数都已经判断过了),大于则继续向右查找。所以在 4 个数的时候非常多比较 3 次。以此类推,在 5 个数的时候非常多查找 3 次,在 6 个数的时候也是非常多查找 3 次。

实现代码

public class BinarySearch {
    private int[] array;
    /**
     * 递归实现二分查找
     * @param target
     * @return
     */
    public int searchRecursion(int target) {
        if (array != null) {
            return searchRecursion(target, 0, array.length - 1);
        }
        return -1;
    }

    private int searchRecursion(int target, int start, int end) {
        if (start > end) {
            return -1;
        }
        int mid = start + (end - start) / 2;
        if (array[mid] == target) {
            return mid;
        } else if (target < array[mid]) {
            return searchRecursion(target, start, mid - 1);
        } else {
            return searchRecursion(target, mid + 1, end);
        }
    }
}

三、链表简介

1、链表概念

链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。

2、链表的构成

链表中每个节点都分为两部分,一个数据域,一个是指针域。说到这里你应该就明白了,链表就如同车链子一样,head指向名列前茅个元素:名列前茅个元素又指向第二个元素,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。作为有强大功能的链表,对他的操作当然有许多,比如:链表的创建,修改,删除,插入,输出,排序,反序,清空链表的元素,求链表的长度等等。

3、常见的链表

  • 单链表
  • 循环链表
  • 双向链表

4、链表的增删改查

我们在进行数组的插入、删除操作的时候,为了保持内存数据的连续性,需要进行大量的数据搬移工作,所以时间复杂度为 O(n);而在链表中插入或者删除一个数据我们并不需要为了保持内存的连续性而搬移节点,因为链表本身的存储空间也不是连续的,所以在链表中插入和删除一个数据是非常快的。

  • 插入数据: 我们只需要将要插入位置的前一个数据单元的next指针指向插入数据的内存地址,插入数据的next指针指向下一个数据的内存地址;
  • 删除数据: 将要删除数据的前一个数据单元的next指针指向要删除数据的下一个数据单元的内存地址,然后再删除数据。

5、实现代码

public class MyLinkedList<E> {
10     /**
11      * 私有的 Node
12      */
13     private class Node{
14         public E e;
15         public Node next;
16 
17         public Node(E e, Node next){
18             this.e = e;
19             this.next = next;
20         }
21         public Node(E e){
22             this(e, null);
23         }
24         public Node(){
25             this(null, null);
26         }
27     }
28     private Node head;
29     private int size;
30 
31     public MyLinkedList(){
32         head = null;
33         size = 0;
34     }
35     public int getSize(){
36         return this.size;
37     }
38     public boolean isEmpty(){
39         return size == 0;
40     }
41 }

延伸阅读

循环链表简介

  • 单向循环链表 [Circular Linked List] : 由各个内存结构通过一个指针 Next 链接在一起组成,每一个内存结构都存在后继内存结构,内存结构由数据域和 Next 指针域组成。
  • 双向循环链表 [Double Circular Linked List] : 由各个内存结构通过指针 Next 和指针 Prev 链接在一起组成,每一个内存结构都存在前驱内存结构和后继内存结构,内存结构由数据域、Prev 指针域和 Next 指针域组成。

文章标题:二分查找为什么不能用于链表,发布者:Z, ZLW,转载请注明出处:https://worktile.com/kb/p/49385

(1)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Z, ZLW的头像Z, ZLW
上一篇 2023年4月15日
下一篇 2023年4月15日

相关推荐

  • 项目管理培训内容有哪些类型

    项目管理培训内容主要包括:基础知识培训、项目规划与控制培训、风险管理培训、质量管理培训、团队管理与领导力培训等。其中,基础知识培训是培训的起点,它主要涵盖项目管理的定义、项目生命周期、项目管理过程等关键概念,让参与者对项目管理有一个全面的理解。 一、基础知识培训 基础知识培训是项目管理培训的基石,主…

    2024年7月24日
    1000
  • bim项目管理平台有哪些内容

    BIM项目管理平台包含的内容主要有:项目管理模块、模型管理模块、协作与沟通模块、任务管理模块、文件管理模块、质量安全模块等。其中,项目管理模块是最核心的部分,它主要负责对项目整体进度的管理,包括项目计划、项目进度、项目成本、项目风险等方面的管理。该模块通常包含了项目信息管理、项目进度管理、项目成本管…

    2024年7月24日
    500
  • 旅游局管理哪些行业项目

    旅游局是一个专门负责管理和监管旅游活动的政府机构,主要负责的行业项目包括:旅游资源开发、旅游景区管理、旅游市场营销、旅游服务质量监管、旅游政策制定、旅游企业管理、旅游行业统计数据收集与分析、旅游规划与建设、旅游文化推广等。其中,旅游资源开发是旅游局的重要职责之一,它涉及到对旅游资源的勘查、评价、利用…

    2024年7月24日
    400
  • 项目管理的职业证书有哪些

    在项目管理领域,各种职业证书层出不穷,但以下几种证书是最为知名和公认的:PMP(项目管理专业人士)、PRINCE2(项目内控环境)、CAPM(认证项目管理师)、MSP(管理成功的项目)、ACP(敏捷认证专家)和CSM(认证Scrum Master)。各种证书的培训和取得,对从事项目管理工作的人来说,…

    2024年7月24日
    300
  • 项目管理的关键点有哪些

    项目管理的关键点包括:明确目标、制定详细计划、有效沟通、风险管理、资源分配、进度监控、质量控制、变更管理。明确目标是项目管理的基础,确保项目的所有参与者都了解并认同项目的最终目标,这是项目成功的第一步。明确目标不仅要清晰具体,还需可衡量、可实现、有时间限制和相关性。制定详细计划则是根据项目目标,分解…

    2024年7月24日
    300

发表回复

登录后才能评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部