TypeScript数据结构与算法(5)最基础的数据结构-链表-LinkedList
链表的概念,使用文字描述过于苍白,用一张图解释:

从图中可以看出链表的特性:
1.存储在链表中元素时无顺序的,图中我故意打乱了排列的情况,就是为了说明这一点,如果仍然无法理解这点,可以对比下数组来看看链表中的各个元素的关系
2.链表中的各个元素之前的关联关系,由每个元素中的next这个属性来进行链接,也就是说,每个元素中next这个属性就是存储的下一个节点(这里开始涉及递归的概念了)
3.存储链表元素的叫做节点Node,它的设计如下:
class Node<T>{ e: T; next: Node<T>; constructor(e: T, next: Node<T>) { this.e = e; this.next = next; } }
这里,我先实现了一个普通的链表DataStruct_LinkedList_Normal<T>,源码如下:
class Node<T>{ e: T; next: Node<T>; constructor(e: T, next: Node<T>) { this.e = e; this.next = next; } } /** * Autor: Created by 李清风 on 2020-12-19. * Desc: 不采用虚拟头节点的链表,慢慢引入虚拟头节点,解决index==0的情况 */ export class DataStruct_LinkedList_Normal<T> { private head: Node<T>;//指向linked第一个节点 private size: number; constructor() { this.head = null; this.size = 0; } //获取size public getSize(): number { return this.size; } //是否为空 public isEmpty(): boolean { return this.size == 0; } //在链表头部添加元素 public addFirst(e: T) { this.head = new Node(e, this.head); this.size++; } //在链表指定索引(0-based)处添加新元素 //注:在真实使用链表的环境中,并不存在索引的概念 public add(index: number, e: T) { if (index < 0 || index > this.size) { throw new Error("LogError:Add failed.Require index >=0 and index<size."); } if (index == 0) { this.addFirst(e); } else { let prev: Node<T> = this.head; for (let i = 0; i < index - 1; i++) { // index - 1表示遍历链表结构树寻找插入位置之前的那个索引元素 prev = prev.next; } prev.next = new Node(e, prev.next); this.size++; } } public addLast(e: T) { this.add(this.size, e); } }
引入虚拟头节点dummyHead,对上述实现的简单的链表数据结构类进行优化,源码如下:
/** * Autor: Created by 李清风 on 2020-12-19. * Desc: 链表,在内存中无序的,通过next把一个一个node链接起来,构建关系 */ class Node<T>{ public e: T; public next: Node<T>;//这里就有递归的意思了 constructor(e: T, next: Node<T>) { this.e = e; this.next = next; } } export class DataStruct_LinkedList<T>{ private dummyHead: Node<T>;//虚拟头节点 private size: number; //链表中实际存储了多少个元素 constructor() { this.dummyHead = new Node(null, null); this.size = 0; } public getSize(): number { return this.size; } public isEmpty(): boolean { return this.size == 0; } //往链表中添加元素 public add(index: number, e: T) { if (index < 0 || index > this.size) { throw new Error("LogError:Add failed.Require index >=0 and index<size."); } let p: Node<T> = this.dummyHead; for (let i = 0; i < index; i++) { p = p.next; } p.next = new Node<T>(e, p.next); this.size++; } //头部插入元素 public addFirst(e: T) { this.add(0, e); } //尾部插入元素 public addLast(e: T) { this.add(this.size, e); } //根据index获取元素 public getElement(index: number): T { if (index < 0 || index >= this.size) { throw new Error("LogError:Add failed.Require index >=0 and index<size."); } let cur = this.dummyHead.next; for (let i = 0; i < index; i++) { cur = cur.next; } return cur.e; } //获取首元素 public getFirst(): T { return this.getElement(0); } //获取尾元素 public getLast(): T { return this.getElement(this.size - 1); } //设置index处的元素为e public setElement(index: number, e: T) { if (index < 0 || index >= this.size) { throw new Error("LogError:Add failed.Require index >=0 and index<size."); } let cur = this.dummyHead.next; for (let i = 0; i < index; i++) { cur = cur.next; } cur.e = e; } //链表是否包含元素e public contains(e: T): boolean { let cur = this.dummyHead; while (cur.next != null) { if (cur.e == e) { //Equals更好 return true; } cur = cur.next; } return false; } //移除index处的元素 public remove(index: number) { if (index < 0 || index >= this.size) { throw new Error("LogError:Add failed.Require index >=0 and index<size."); } let p = this.dummyHead; for (let i = 0; i < index; i++) { p = p.next; } let retNode = p.next; p.next = retNode.next; retNode.next = null;//与链表脱离 this.size--; return retNode.e; } //移处链表中某个元素 public removeElement(e: T) { let prev = this.dummyHead; while (prev.next != null) { if (prev.next.e == e) { //可以自己封装一个equals break; } prev = prev.next; } if (prev.next != null) { let delNode = prev.next; prev.next = delNode.next; delNode.next = null;//与链表脱离 } } //移除首元素 public removeFirst() { return this.remove(0); } //移除尾元素 public removeLast() { return this.remove(this.size - 1); } }

浙公网安备 33010602011771号