笔记整理自 coderwhy 『TypeScript 高阶数据结构与算法』课程

双向链表:拥有两个指针方向的链表

DoublyNode 结构:

  • prev:指向上一个节点
  • value:节点值
  • next:指向下一个节点

DoublyLinkedList 属性:

  • head:头节点
  • tail:尾节点
  • length:链表长度

实现方法:

  1. append:尾部插入节点
  2. prepend:头部插入节点
  3. traverse:正向遍历
  4. postTraverse:反向遍历
  5. getNodeByPosition:根据索引获取节点
  6. insert:根据索引插入节点
  7. removeAt:根据索引删除节点
  8. Size:获取链表长度

具体代码实现:


  1. class DoublyNode<T> {
  2. value: T;
  3. next: DoublyNode<T> | null = null;
  4. prev: DoublyNode<T> | null = null;
  5. constructor(value: T) {
  6. this.value = value;
  7. }
  8. }
  9. class DoublyLinkedList<T> {
  10. head: DoublyNode<T> | null = null;
  11. tail: DoublyNode<T> | null = null;
  12. length: number = 0;
  13. constructor() {}
  14. // 获取链表长度
  15. get Size(): number {
  16. return this.length;
  17. }
  18. // 尾部插入节点
  19. append(value: T): void {
  20. const newNode = new DoublyNode(value);
  21. if (!this.head) {
  22. this.head = newNode;
  23. this.tail = newNode;
  24. } else {
  25. this.tail!.next = newNode;
  26. newNode.prev = this.tail;
  27. this.tail = newNode;
  28. }
  29. this.length++;
  30. }
  31. // 头部插入节点
  32. prepend(value: T): void {
  33. // 创建一个新节点
  34. const newNode = new DoublyNode(value);
  35. // 链表无数据,即 head 为空
  36. if (!this.head) {
  37. this.head = newNode;
  38. this.tail = newNode;
  39. } else {
  40. // 处理以前的 head
  41. newNode.next = this.head;
  42. this.head.prev = newNode;
  43. // 更新 head
  44. this.head = newNode;
  45. }
  46. // 链表数据增加
  47. this.length++;
  48. }
  49. // 正向遍历
  50. traverse() {
  51. let current = this.head;
  52. let _arr: (T | null)[] = [];
  53. while (current) {
  54. _arr.push(current.value);
  55. current = current.next;
  56. }
  57. console.log(_arr.join(" -> "));
  58. }
  59. // 反向遍历
  60. postTraverse() {
  61. let current = this.tail;
  62. let _arr: T[] = [];
  63. while (current) {
  64. _arr.push(current.value);
  65. current = current.prev;
  66. }
  67. console.log(_arr.join(" -> "));
  68. }
  69. // 根据索引获取当前节点
  70. getNodeByPosition(position: number): DoublyNode<T> | null {
  71. let index = 0;
  72. let current = this.head;
  73. while (index++ < position && current) {
  74. current = current.next;
  75. }
  76. return current;
  77. }
  78. // 根据索引插入元素
  79. insert(value: T, position: number): boolean {
  80. // 越界判断
  81. if (position < 0 || position > this.length) return false;
  82. // 头部插入
  83. if (position === 0) {
  84. this.prepend(value);
  85. } else if (position === this.length) {
  86. // 尾部插入
  87. this.append(value);
  88. } else {
  89. // 根据 position 插入
  90. const newNode = new DoublyNode(value);
  91. let current = this.getNodeByPosition(position);
  92. current!.prev!.next = newNode;
  93. newNode.prev = current!.prev;
  94. newNode.next = current;
  95. current!.prev = newNode;
  96. this.length++;
  97. }
  98. return true;
  99. }
  100. // 根据索引删除元素
  101. removeAt(position: number): T | null {
  102. // 1. 越界判断
  103. if (position < 0 || position >= this.length) return null;
  104. // 2. 合规情况分析
  105. let current = this.head;
  106. // 2.1 删除头部
  107. if (position === 0) {
  108. // 只有一个节点
  109. if (this.length === 1) {
  110. this.head = null;
  111. this.tail = null;
  112. } else {
  113. // 多个节点
  114. this.head = this.head!.next;
  115. this.head!.prev = null;
  116. }
  117. } else if (position === this.length - 1) {
  118. // 2.2 删除尾部
  119. current = this.tail;
  120. this.tail = this.tail!.prev;
  121. this.tail!.next = null;
  122. } else {
  123. // 2.3 其余情况
  124. const node = this.getNodeByPosition(position);
  125. current = node;
  126. node!.prev!.next = node!.next;
  127. node!.next!.prev = node!.prev;
  128. }
  129. this.length--;
  130. return current ? current.value : null;
  131. }
  132. }
  133. const doublyLinkedList = new DoublyLinkedList<string>();
  134. doublyLinkedList.append("aaa");
  135. doublyLinkedList.append("bbb");
  136. doublyLinkedList.append("ccc");
  137. doublyLinkedList.insert("ddd", 0);
  138. doublyLinkedList.removeAt(0);
  139. doublyLinkedList.traverse();

双向链表的基本实现【数据结构与算法—TypeScript 实现】的更多相关文章

  1. JS数据结构与算法--双向链表

    双向链表中链接是双向的:一个链向下一个元素,另一个链向上一个元素,如下图所示: 双向链表结构代码如下: class Node { constructor(element) { this.element ...

  2. 重读《学习JavaScript数据结构与算法-第三版》-第2章 ECMAScript与TypeScript概述

    定场诗 八月中秋白露,路上行人凄凉: 小桥流水桂花香,日夜千思万想. 心中不得宁静,清早览罢文章, 十年寒苦在书房,方显才高志广. 前言 洛伊安妮·格罗纳女士所著的<学习JavaScript数据 ...

  3. 数据结构与算法 Big O 备忘录与现实

    不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新.        算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...

  4. 《数据结构与算法JavaScript描述》

    <数据结构与算法JavaScript描述> 基本信息 作者: (美)Michael McMillan 译者: 王群锋 杜欢 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9 ...

  5. 面试常考的常用数据结构与算法(zz)

    数据结构与算法,这个部分的内容其实是十分的庞大,要想都覆盖到不太容易.在校学习阶段我们可能需要对每种结构,每种算法都学习,但是找工作笔试或者面试的时候,要在很短的时间内考察一个人这方面的能力,把每种结 ...

  6. Android版数据结构与算法(一):基础简介

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 一.前言 项目进入收尾阶段,忙忙碌碌将近一个多月吧,还好,不算太难,就是麻烦点. 数据结构与算法这个系列早就想写了,一是梳理总结,顺便逼迫自己把一 ...

  7. Python3-Cookbook总结 - 第一章:数据结构和算法

    第一章:数据结构和算法 Python 提供了大量的内置数据结构,包括列表,集合以及字典.大多数情况下使用这些数据结构是很简单的. 但是,我们也会经常碰到到诸如查询,排序和过滤等等这些普遍存在的问题. ...

  8. 数据结构与算法JS实现

      行解算法题,没错,就是这么方便. 当然也可以使用 Node.js 环境来执行,具体参考Node.js官方文档即可. 二 对象和面向对象编程 js中5种数据类型,并没有定义更多的数据类型,但是运用j ...

  9. Linux内核中常用的数据结构和算法(转)

    知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...

  10. Python 数据结构和算法

    阅读目录 什么是算法 算法效率衡量 算法分析 常见时间复杂度 Python内置类型性能分析 数据结构 顺序表 链表 栈 队列 双端队列 排序与搜索 冒泡排序 选择排序 插入排序 希尔排序 快速排序 归 ...

随机推荐

  1. c++复习笔记——STL(vector)

    c++-----STL容器系列(1) vector 1 介绍 Vector是stl容器中一种常见的容器 ,基本和数组类似,其大小(size)可变,常用于数组长度不确定时来代替数组,当数据超过vecto ...

  2. logon scripts后门

    Windows登录脚本,当用户登录时触发,Logon Scripts能够优先于杀毒软件执行,绕过杀毒软件对敏感操作的拦截 注册表位置:HKEY_CURRENT_USER\Environment 在命令 ...

  3. 【LLM】大模型落地-从理论到实践

    简述 按个人偏好和目标总结了学习目标和路径(可按需学习),后续将陆续整理出相应学习资料和资源. 学习目标 熟悉主流LLM(Llama, ChatGLM, Qwen)的技术架构和技术细节:有实际应用RA ...

  4. spring boot 自动装载对象为null问题的解决

    情况描述 有个Server类,成员变量是spring中自动管理的bean类对象 public class Server { @Autowired private CommandMapper comma ...

  5. 一个简单的HTTP服务器的实现

    我们继续我们的HTTP服务器的实现(使用别的代码来实现), 这个HTTP服务器的实现,我们主要就是关注TCP服务器中的recv还有send的处理. 首先,看一下HTTP,我们在用浏览器访问我们的TCP ...

  6. C++11 中运行代码块耗时的方法以及坑(chrono 方法)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  7. 如何在UE4中播放本地视频文件?

    在UE4中有一套媒体框架方法,它根据视频源的不同,对应的播放方式也不一样,支持的视频源有本地视频文件.影像序列.视频流.实时视频截图.播放形式可选择在场景内的静态网格上播放或者以UI的形式播放.本文主 ...

  8. 专访OV季军|毕业转为freelancer,他如何斩获大量CG奖项?

    "新锐先锋,玩转未来"--首届实时渲染3D动画创作大赛由瑞云科技主办,英伟达.青椒云.3DCAT实时渲染云协办,戴尔科技集团.Reallusion.英迈.万生华态.D5渲染器.中视 ...

  9. Python爬虫实战系列4:天眼查公司工商信息采集

    Python爬虫实战系列1:博客园cnblogs热门新闻采集 Python爬虫实战系列2:虎嗅网24小时热门新闻采集 Python爬虫实战系列3:今日BBNews编程新闻采集 Python爬虫实战系列 ...

  10. 记录--怎么实现一个3d翻书效果

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 本篇主要讨论以下两种翻书动画的实现: 第一种是整页翻转的效果: 这种整页翻转的效果主要是做rotateY的动画,并结合一些CSS的3d属性 ...