Skip to content

Commit

Permalink
feat: complete doubly linked list
Browse files Browse the repository at this point in the history
  • Loading branch information
javaswing committed Nov 16, 2023
1 parent 975dff1 commit f06543a
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 7 deletions.
7 changes: 2 additions & 5 deletions code/linked-list/book/LinkedList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,8 @@ export default class LinkedList<T> implements LinkedListInterface<T> {
getElementAt(index: number) {
if (index >= 0 && index < this.count) {
let current = this.head;
for (let i = 0; i < this.count; i++) {
if (i === index) {
break;
}
current = current?.next;
for (let i = 0; i < index && current != undefined; i++) {
current = current.next;
}
return current;
}
Expand Down
4 changes: 2 additions & 2 deletions code/linked-list/book/LinkedNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
export class LinkedNode<T> {
val: T;
next: undefined | LinkedNode<T>;
constructor(v: T) {
constructor(v: T, next: undefined | LinkedNode<T> = undefined) {
this.val = v;
this.next = undefined;
this.next = next;
}
}
93 changes: 93 additions & 0 deletions code/linked-list/book/doubly-linked-list/doubly-linked-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { defaultEquals } from '../../../utils';
import LinkedList from '../LinkedList';
import DoublyNode from './doubly-node';

export default class DoublyLinkedList<T> extends LinkedList<T> {
tail: undefined | DoublyNode<T>;
head: undefined | DoublyNode<T>;

constructor(eqFn = defaultEquals) {
super(eqFn);
this.tail = undefined;
}

push(element: T): void {
const node = new DoublyNode(element);
if (this.head === undefined) {
this.head = node;
} else {
let c = this.head;
while (c.next != undefined) {
c = c.next;
}
c.next = node;
node.prev = c;
}
this.count++;
}

insert(e: T, index: number) {
if (index >= 0 && index <= this.count) {
const node = new DoublyNode(e);
if (index == 0) {
let c = this.head;
node.next = c;
c && (c.prev = node);
this.head = node;
} else if (index === this.count - 1) {
let c = this.tail;
node.next = c;
c && (c.prev = node);
this.tail = node;
} else {
let c = this.head;
for (let i = 0; i < this.count && c !== undefined; i++) {
if (i === index) {
let prev = c.prev;
prev && (prev.next = node);
node.prev = prev;
node.next = c;
c.prev = node;
break;
}
c = c?.next;
}
}
this.count++;
return true;
}
return false;
}

removeAt(index: number) {
if (index >= 0 && index < this.count) {
let c = this.head;
if (index == 0) {
this.head = c?.next;
if (this.count === 1) {
this.tail = undefined;
} else {
this.head && (this.head.prev = undefined);
}
} else if (index === this.count - 1) {
c = this.tail;
this.tail = c?.prev;
if (this.tail) {
this.tail.next = undefined;
}
} else {
c = this.getElementAt(index) as DoublyNode<T> | undefined;
const p = c?.prev;
if (p) {
p.next = c?.next?.next;
}
if (c && c.next) {
c.next.prev = p;
}
}
this.count--;
return c?.val;
}
return undefined;
}
}
14 changes: 14 additions & 0 deletions code/linked-list/book/doubly-linked-list/doubly-node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { LinkedNode } from "../LinkedNode";

/**
* 双向链表 node 节点
*/
export default class DoublyNode<T> extends LinkedNode<T> {
prev: DoublyNode<T> | undefined;
next: DoublyNode<T> | undefined;

constructor(element: T, next: DoublyNode<T> | undefined = undefined, prev: DoublyNode<T>| undefined = undefined) {
super(element, next)
this.prev = prev;
}
}
17 changes: 17 additions & 0 deletions code/linked-list/test/doubly-linked-list.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import DoublyLinkedList from "../book/doubly-linked-list/doubly-linked-list";

describe('doubly linked list', () => {
it('should create empty doubly linked list', () => {
const linkedList = new DoublyLinkedList<number>();
expect(linkedList.toString()).toBe('');
});

it('test insert doubly linked list', () => {
const linkedList = new DoublyLinkedList<number>();
linkedList.push(2);
linkedList.push(5);
linkedList.push(7);
linkedList.insert(1, 1)
expect(linkedList.toString()).toBe("2,1,5,7");
});
});
4 changes: 4 additions & 0 deletions docs/zh/guide/book/chap6.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,7 @@ export default class LinkedList<T> implements LinkedListInterface<T> {
}

```

## 双向链表

与单向链表相比较而言,双向链表在链表节点内部多了一个指针指向前一个节点。也就是说一个节点有`next`指针和`prev`指针。在遍历上,可以正向遍历也可以反向遍历。

0 comments on commit f06543a

Please sign in to comment.