实现双向链表

实现双向链表

假设理解 big o 表示法。 javascript 中有示例。资料参考 gayle laakmann mcdowell 的《cracking the coding interview》

理解双向链表

双向链表与单链表非常相似,除了节点的结构和添加/删除节点的方式不同。

节点结构

双向链表中的节点包含

prev指针、next指针和value。 prev 指针指向前一个节点,next 指针指向下一个节点。本质上,这个列表在每个节点都是双向的。

添加节点

在特定索引处插入新节点(newnode):

将当前位于插入索引处的节点存储在临时变量 nextnode 中。

更新前一个节点和新节点的连接:

将前一个节点的next指针设置为newnode。设置newnode的prev指针指向前一个节点。将新节点连接到下一个节点:

将newnode的next指针设置为nextnode。将 nextnode 的 prev 指针设置为 newnode。 删除节点

要删除特定索引处的节点:

更新前一个节点的next指针:设置为指向被移除后的节点。更新下一个节点的prev指针:将其设置为指向被删除节点之前的节点。这有效地“弥合”了删除节点所产生的间隙,保持了列表的完整性。

时间复杂度分析

在双向链表中添加/删除 →

o(n)o(n)o(n)

在双向链表的头部或尾部添加/删除 →

o(1)o(1)o(1)

javascript 实现

经典面向对象编程

class listnode {  constructor(value, prev = null, next = null) {    this.value = value;    this.prev = prev;    this.next = next;  }}class doublylinkedlist {  constructor() {    this.head = null;    this.tail = null;    this.size = 0;  }  // add a node to the head of the list  addhead(value) {    const newnode = new listnode(value, null, this.head);    if (this.head) {      this.head.prev = newnode;    } else {      this.tail = newnode; // if list was empty, new node is also the tail    }    this.head = newnode;    this.size++;  }  // add a node to the tail of the list  addtail(value) {    const newnode = new listnode(value, this.tail, null);    if (this.tail) {      this.tail.next = newnode;    } else {      this.head = newnode; // if list was empty, new node is also the head    }    this.tail = newnode;    this.size++;  }  // remove a node from the head of the list  removehead() {    if (!this.head) return null; // list is empty    const removedvalue = this.head.value;    this.head = this.head.next;    if (this.head) {      this.head.prev = null;    } else {      this.tail = null; // list became empty    }    this.size--;    return removedvalue;  }  // remove a node from the tail of the list  removetail() {    if (!this.tail) return null; // list is empty    const removedvalue = this.tail.value;    this.tail = this.tail.prev;    if (this.tail) {      this.tail.next = null;    } else {      this.head = null; // list became empty    }    this.size--;    return removedvalue;  }  // remove a node at a specific index  removeat(index) {    if (index = this.size) return null;    let current;    if (index < this.size / 2) {      current = this.head;      for (let i = 0; i  index; i--) {        current = current.prev;      }    }    if (current.prev) current.prev.next = current.next;    if (current.next) current.next.prev = current.prev;    if (index === 0) this.head = current.next;    if (index === this.size - 1) this.tail = current.prev;    this.size--;    return current.value;  }  // get the size of the list  getsize() {    return this.size;  }  // get the values in the list  getvalues() {    const values = [];    let current = this.head;    while (current) {      values.push(current.value);      current = current.next;    }    return values;  }}

函数式面向对象编程

function ListNode(value, prev = null, next = null) {  this.value = value;  this.prev = prev;  this.next = next;}function DoublyLinkedList() {  this.head = null;  this.tail = null;  this.size = 0;}// Add a node to the head of the listDoublyLinkedList.prototype.addHead = function(value) {  const newNode = new ListNode(value, null, this.head);  if (this.head) {    this.head.prev = newNode;  } else {    this.tail = newNode;  }  this.head = newNode;  this.size++;};// Add a node to the tail of the listDoublyLinkedList.prototype.addTail = function(value) {  const newNode = new ListNode(value, this.tail, null);  if (this.tail) {    this.tail.next = newNode;  } else {    this.head = newNode;  }  this.tail = newNode;  this.size++;};// Remove a node from the head of the listDoublyLinkedList.prototype.removeHead = function() {  if (!this.head) return null;  const removedValue = this.head.value;  this.head = this.head.next;  if (this.head) {    this.head.prev = null;  } else {    this.tail = null;  }  this.size--;  return removedValue;};// Remove a node from the tail of the listDoublyLinkedList.prototype.removeTail = function() {  if (!this.tail) return null;  const removedValue = this.tail.value;  this.tail = this.tail.prev;  if (this.tail) {    this.tail.next = null;  } else {    this.head = null;  }  this.size--;  return removedValue;};// Remove a node at a specific indexDoublyLinkedList.prototype.removeAt = function(index) {  if (index = this.size) return null;  let current;  if (index < this.size / 2) {    current = this.head;    for (let i = 0; i  index; i--) {      current = current.prev;    }  }  if (current.prev) current.prev.next = current.next;  if (current.next) current.next.prev = current.prev;  if (index === 0) this.head = current.next;  if (index === this.size - 1) this.tail = current.prev;  this.size--;  return current.value;};// Get the size of the listDoublyLinkedList.prototype.getSize = function() {  return this.size;};// Get the values in the listDoublyLinkedList.prototype.getValues = function() {  const values = [];  let current = this.head;  while (current) {    values.push(current.value);    current = current.next;  }  return values;};

以上就是实现双向链表的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1490414.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月19日 13:09:06
下一篇 2025年12月19日 13:09:25

相关推荐

  • React/JavaScript中高效合并对象数组内嵌套数组的教程

    本教程详细讲解了如何在React/JavaScript应用中,将包含嵌套数组的对象数组扁平化为一个单一的数组。我们将分析传统方法可能遇到的问题,并重点介绍如何利用Array.prototype.reduce方法,以声明式和高效的方式实现这一数据转换,从而避免状态覆盖,确保数据完整性。 1. 引言:理…

    2025年12月20日
    000
  • React/JavaScript中合并对象数组内部嵌套数组的教程

    本文将详细介绍如何在React/JavaScript中高效地合并一个对象数组内部嵌套的子数组。当遇到包含多个对象,且每个对象又含有一个子数组的数据结构时,我们通常需要将所有这些子数组中的元素提取并合并成一个扁平化的单一数组。教程将通过分析常见的错误方法,并重点讲解如何利用Array.prototyp…

    2025年12月20日
    000
  • JavaScript/React中高效合并对象数组内嵌套数组的教程

    本教程探讨了在React应用中如何高效地合并对象数组内嵌套的子数组。我们将深入分析一种常见的错误,并提供基于JavaScript reduce 方法的专业解决方案,以及更现代的 flatMap 替代方案,旨在帮助开发者以清晰、可维护的方式处理复杂数据结构,确保数据扁平化以满足UI渲染需求。 理解问题…

    2025年12月20日
    000
  • JavaScript/React中合并对象数组内嵌数组的实用教程

    本教程将指导您如何在JavaScript和React应用中高效合并对象数组中嵌套的子数组。通过深入解析Array.prototype.reduce()方法,结合扩展运算符,我们将演示如何将多层嵌套的数据结构扁平化为一个单一的数组,避免常见的状态更新错误,并提供清晰的示例代码和最佳实践。 理解问题:嵌…

    2025年12月20日 好文分享
    000
  • JS如何实现动画?动画的帧控制

    JavaScript实现动画的核心是通过requestAnimationFrame与浏览器刷新同步,持续更新元素的transform或opacity等高性能CSS属性,避免回流和重绘,结合缓动函数提升视觉流畅度,同时可借助GSAP等动画库简化复杂动画的开发,实现高效、流畅的动画效果。 JavaScr…

    好文分享 2025年12月20日
    000
  • JS如何实现主题切换?主题的变量

    答案:JavaScript通过操作CSS自定义属性和类名实现主题切换,并利用localStorage持久化用户偏好。首先在CSS中定义:root下的默认主题变量及.dark-theme等类中的覆盖变量,采用语义化命名如–color-primary提升可维护性;JavaScript在DOM…

    2025年12月20日
    000
  • js怎么实现模态框弹出

    模态框弹出时避免页面滚动的方法是通过javascript动态设置body的overflow为hidden,并在关闭时恢复;1. 打开模态框时,执行body.style.overflow = ‘hidden’,阻止页面滚动;2. 关闭模态框时,将overflow属性重置为空字符…

    2025年12月20日
    000
  • JS如何实现自适应布局

    JavaScript在自适应布局中弥补CSS的不足,通过动态操作DOM实现内容感知与结构重组,如响应视口变化、使用ResizeObserver监听元素尺寸、matchMedia控制断点逻辑,并结合节流、防抖和requestAnimationFrame优化性能,提升用户体验。 JavaScript在自…

    2025年12月20日
    000
  • js 如何复制文本到剪贴板

    javascript中复制文本到剪贴板最现代且推荐的方式是使用navigator.clipboard.writetext(),它基于promise、异步执行、不阻塞主线程,且需在用户手势触发的上下文中调用以满足安全策略;2. 为兼容老旧浏览器可降级使用document.execcommand(&#8…

    2025年12月20日
    000
  • js 怎么实现图片懒加载

    图片懒加载的核心是延迟加载非首屏图片,等到接近用户视野时再加载,能显著提升页面加载速度、节省流量、优化用户体验;2. 推荐使用 intersectionobserver api 实现,通过将真实图片地址存于 data-src,用 src 显示占位符,当元素进入视口时再赋值真实地址并停止观察,同时提供…

    2025年12月20日
    000
  • JSX是什么语法

    jsx通过将html结构直接嵌入javascript代码中提升开发效率,使ui描述更直观、减少字符串拼接和出错概率,支持嵌入javascript表达式实现动态渲染,且代码更简洁易读;jsx与html的主要区别在于属性命名需使用classname和htmlfor、所有标签必须闭合、可嵌入javascr…

    2025年12月20日
    000
  • js 怎样设置CSS样式

    通过javascript设置css样式的核心是利用dom操作获取元素后通过style属性修改,1. 使用document.getelementbyid或queryselector等方法获取目标元素;2. 通过元素的style属性设置内联样式,如element.style.color = &#8216…

    2025年12月20日
    000
  • JS如何获取HTML元素

    答案:JS通过DOM方法获取HTML元素,常用方式包括getElementById(通过ID获取单个元素,高效但仅限唯一ID)、getElementsByClassName(通过类名获取动态集合)、getElementsByTagName(通过标签名获取元素集合)、querySelector(支持C…

    2025年12月20日
    000
  • 实现网页选项过滤功能的教程

    本文档旨在指导开发者如何实现一个简单的网页选项过滤功能。通过创建动态卡片并利用 JavaScript 控制其显示与隐藏,用户可以根据预设的类别筛选内容。本文将提供完整的代码示例,并详细解释实现步骤,帮助开发者快速构建类似的功能。 搭建HTML结构 首先,我们需要创建一个基本的HTML结构,包括用于显…

    2025年12月20日
    000
  • 什么是CSS-in-JS?CSS的模块化

    css-in-js通过将样式写入javascript文件并利用js的编程能力实现样式的模块化与动态管理,从根本上解决了传统css的全局作用域污染、命名冲突、维护困难和死代码等问题。它通过在运行时或构建时生成唯一类名或内联样式,确保样式仅作用于对应组件,实现真正的局部作用域。与sass/less等预处…

    2025年12月20日
    000
  • 什么是JS文件?JS代码如何运行

    javascript文件是包含javascript代码的纯文本文件,以.js为扩展名,需通过javascript引擎(如浏览器的v8、spidermonkey或node.js)解析执行,其运行过程包括词法分析、语法分析生成ast、编译为字节码、jit优化并最终执行;在网页中,javascript通过…

    2025年12月20日
    000
  • JS如何实现拓扑图

    实现javascript拓扑图的核心答案是优先使用d3.js等成熟库进行数据可视化和交互,其数据结构通常由节点(nodes)和边(links)组成的标准json格式,选择库时需权衡定制化、性能、学习成本等因素,常见挑战包括布局优化、渲染性能、交互实现与数据更新。具体而言,d3.js适合高定制需求但学…

    2025年12月20日
    000
  • 在 Angular 中基于特定条件获取不同的 ID

    本文将介绍如何在 Angular 中使用 JavaScript 的数组方法,从 JSON 数据集中筛选出满足特定条件的唯一 ID。主要涉及 filter 和 map 方法的结合使用,以实现数据筛选、去重和提取目标字段的功能。 数据筛选 首先,我们需要使用 filter 方法根据条件筛选出符合要求的数…

    2025年12月20日
    000
  • 实现前端页面选项过滤功能的教程

    本文旨在指导开发者如何实现一个基于前端的选项过滤功能。我们将通过一个学校信息展示的示例,详细讲解如何使用 JavaScript 和 CSS 来动态地显示和隐藏页面元素,从而实现按类别过滤学校的功能。本文将涵盖数据结构设计、HTML 结构搭建、JavaScript 逻辑编写以及 CSS 样式设置等方面…

    2025年12月20日
    000
  • 实现页面选项过滤功能的教程

    本文档旨在指导开发者如何实现一个简单的页面选项过滤功能。通过创建动态卡片并利用 JavaScript 控制其显示与隐藏,可以根据用户选择的类别过滤页面内容。本文将详细介绍 HTML 结构、CSS 样式和 JavaScript 代码,并提供完整的示例代码和注意事项,帮助读者快速掌握该功能的实现方法。 …

    2025年12月20日
    000

发表回复

登录后才能评论
关注微信