循环链表 循环链表(Circular LinkedList)是一种特殊的链表数据结构:
在普通链表的基础上,最后一个节点的下一个节点不再是 null,而是指向链表的第一个节点。
这样形成了一个环,使得链表能够被无限遍历。
这样,可以在单向循环链表中从任意一个节点出发,不断地遍历下一个节点,直到回到起点。
重构 LinkedList(方便继承) 对之前实现的链表进行重构
新增尾部节点 及判断方法
1 2 3 4 5 6 7 8 9 10 protected head : Node <T> | null = null ; protected length : number = 0 ; protected tail : Node <T> | null = null ; get size () { return this .length ; } private isTail (node: Node<T> ) { return this .tail === node; }
append 重构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 append (value : T): void { const node = new Node (value); if (!this .head ) { this .head = node; } else { this .tail !.next = node; } this .tail = node; this .length ++; }
traverse 重构
1 2 3 4 5 6 7 8 9 10 11 12 13 traverse (): string { const value : T[] = []; let current = this .head ; while (current) { value.push (current.val ); if (this .isTail (current)) { current = null ; } else { current = current.next ; } }
insert 重构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 insert (value : T, position : number ): boolean { if (position < 0 || position > this .size ) return false ; const newNode = new Node (value); let current = this .head ; if (position === 0 ) { this .head = newNode; newNode.next = current; } else { const previous = this .getNode (position - 1 ); newNode.next = previous!.next ; previous!.next = newNode; if (position === this .length ) this .tail = newNode; } this .length ++; return true ; }
removeAt 重构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 removeAt (position : number ): T | null { if (position < 0 || position > this .size ) return null ; let current = this .head ; let remove : Node <T> | null = null ; if (position === 0 ) { this .head = current?.next ?? null ; if (this .length === 1 ) { this .head = null ; this .tail = null ; } } else { const previous = this .getNode (position - 1 ); remove = previous!.next ; previous!.next = previous?.next ?.next ?? null ; if (position === this .length - 1 ) { this .tail = previous; } } this .length --; return remove?.val ?? null ; }
indexOf 重构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 indexOf (value : T): number { let index = 0 ; let current = this .head ; while (current) { if (current.val === value) return index; if (this .isTail (current)) { current = null ; } else { current = current.next ; } index++; } return -1 ; }
循环链表实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import LinkedList from "./01_单向链表-重构" ;class CircularirLinkList <T> extends LinkedList <T> { append (value: T ) { super .append (value); this .tail !.next = this .head ; } traverse (): string { return super .traverse (); } insert (value : T, position : number ): boolean { const isSuccess = super .insert (value, position); if ((isSuccess && position === 0 ) || position === this .length - 1 ) { this .tail !.next = this .head ; } return isSuccess; } removeAt (position : number ): T | null { const value = super .removeAt (position); if ((value && this .tail && position === 0 ) || position === this .length ) { this .tail !.next = this .head ; } return value; } indexOf (value : T): number { return super .indexOf (value); } isEmpty (): boolean { return super .isEmpty (); } remove (value : T): T | null { return super .remove (value); } update (value : T, position : number ): boolean { return super .update (value, position); } } const cLinkList = new CircularirLinkList ();cLinkList.append ("AAA" ); cLinkList.append ("BBB" ); cLinkList.append ("CCC" ); cLinkList.append ("DDD" ); cLinkList.insert ("EEE" , 4 ); cLinkList.insert ("000" , 0 ); cLinkList.removeAt (6 ); console .log (cLinkList.indexOf ("000" ));console .log (cLinkList.indexOf ("111" ));console .log (cLinkList.isEmpty ());cLinkList.remove ("000" ); cLinkList.update ("JJJ" , 2 ); console .log (cLinkList.traverse ());