📜  数据结构示例-搜索双向链接列表中的元素(1)

📅  最后修改于: 2023-12-03 15:26:09.796000             🧑  作者: Mango

数据结构示例-搜索双向链接列表中的元素

双向链接列表是一种常用的数据结构,它可以在 O(1) 时间内对链表进行任意位置的插入和删除操作。本文将介绍如何在双向链接列表中搜索特定元素的方法。

双向链接列表结构

双向链接列表与普通单向链表的区别在于,每个节点除了指向下一个节点的指针,还有指向前一个节点的指针。

class ListNode {
  constructor(val, prev, next) {
    this.val = val;  // 节点的值
    this.prev = prev;  // 指向前一个节点的指针
    this.next = next;  // 指向下一个节点的指针
  }
}

class LinkedList {
  constructor() {
    this.dummyHead = new ListNode(null, null, null);  // 头节点指针
    this.dummyTail = new ListNode(null, null, null);  // 尾节点指针
    this.dummyHead.next = this.dummyTail;  // 头节点的下一个节点指向尾节点
    this.dummyTail.prev = this.dummyHead;  // 尾节点的前一个节点指向头节点
    this.length = 0;  // 这里记录了链表的长度,不是紧必要的
  }
  
  // 插入节点的实现
  insert(index, value) {
    // ... 插入操作省略 ...
  }
  
  // 删除节点的实现
  delete(index) {
    // ... 删除操作省略 ...
  }
  
  // 搜索节点的实现
  search(target) {
    // ... 搜索操作需要实现 ...
  }
}
搜索节点的实现

搜索节点的方法相对来说比较简单,我们只需要从头节点开始向后遍历,直到找到目标节点为止。但是由于我们有了前一个节点的指针,这里我们可以优化一下,从两个方向同时进行搜索,这也是双向链接列表的特点之一。

class LinkedList {
  // ...
  
  search(target) {
    let cur = this.dummyHead.next;
    let backward = this.dummyTail.prev;
    while (cur !== this.dummyTail && backward !== this.dummyHead) {
      if (cur.val === target) {
        return cur;
      }
      if (backward.val === target) {
        return backward;
      }
      cur = cur.next;
      backward = backward.prev;
    }
    return null;  // 没找到目标节点
  }
}

代码中,我们同时从头开始向后搜索和从尾开始向前搜索,任何一个方向找到目标节点就直接返回。这样就可以减少搜索的时间复杂度,使得搜索的速度更快。

总结

双向链接列表是一种常用的数据结构,在实际开发中能够帮助我们解决很多问题。本文介绍了其搜索特定元素的方法,利用前一个节点的指针从两个方向同时进行搜索,使得搜索的速度更快。