Skip to content

Commit

Permalink
add pop/shift to linked list
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Dec 10, 2018
1 parent 0bcf5cf commit 3cd6d8a
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 55 deletions.
97 changes: 60 additions & 37 deletions src/vs/base/common/linkedList.ts
Expand Up @@ -32,17 +32,18 @@ export class LinkedList<E> {
clear(): void {
this._first = undefined;
this._last = undefined;
this._size = 0;
}

unshift(element: E) {
return this.insert(element, false);
unshift(element: E): () => void {
return this._insert(element, false);
}

push(element: E) {
return this.insert(element, true);
push(element: E): () => void {
return this._insert(element, true);
}

private insert(element: E, atTheEnd: boolean) {
private _insert(element: E, atTheEnd: boolean): () => void {
const newNode = new Node(element);
if (!this._first) {
this._first = newNode;
Expand All @@ -63,41 +64,63 @@ export class LinkedList<E> {
oldFirst.prev = newNode;
}
this._size += 1;
return this._remove.bind(this, newNode);
}

return () => {
let candidate: Node<E> | undefined = this._first;
while (candidate instanceof Node) {
if (candidate !== newNode) {
candidate = candidate.next;
continue;
}
if (candidate.prev && candidate.next) {
// middle
let anchor = candidate.prev;
anchor.next = candidate.next;
candidate.next.prev = anchor;

} else if (!candidate.prev && !candidate.next) {
// only node
this._first = undefined;
this._last = undefined;

} else if (!candidate.next) {
// last
this._last = this._last!.prev!;
this._last.next = undefined;

} else if (!candidate.prev) {
// first
this._first = this._first!.next!;
this._first.prev = undefined;
}

// done
this._size -= 1;
break;
shift(): E | undefined {
if (!this._first) {
return undefined;
} else {
const res = this._first.element;
this._remove(this._first);
return res;
}
}

pop(): E | undefined {
if (!this._last) {
return undefined;
} else {
const res = this._last.element;
this._remove(this._last);
return res;
}
}

private _remove(node: Node<E>): void {
let candidate: Node<E> | undefined = this._first;
while (candidate instanceof Node) {
if (candidate !== node) {
candidate = candidate.next;
continue;
}
};
if (candidate.prev && candidate.next) {
// middle
let anchor = candidate.prev;
anchor.next = candidate.next;
candidate.next.prev = anchor;

} else if (!candidate.prev && !candidate.next) {
// only node
this._first = undefined;
this._last = undefined;

} else if (!candidate.next) {
// last
this._last = this._last!.prev!;
this._last.next = undefined;

} else if (!candidate.prev) {
// first
this._first = this._first!.next!;
this._first.prev = undefined;
}

// done
this._size -= 1;
break;
}
}

iterator(): Iterator<E> {
Expand Down
39 changes: 21 additions & 18 deletions src/vs/base/test/common/linkedList.test.ts
Expand Up @@ -61,15 +61,7 @@ suite('LinkedList', function () {
list.push('far');
list.push('boo');

assert.deepEqual(
list.toArray(),
[
'foo',
'bar',
'far',
'boo',
]
);
assertElements(list, 'foo', 'bar', 'far', 'boo');
});

test('unshift/Iter', () => {
Expand Down Expand Up @@ -109,15 +101,26 @@ suite('LinkedList', function () {
list.unshift('bar');
list.unshift('far');
list.unshift('boo');
assertElements(list, 'boo', 'far', 'bar', 'foo');
});

test('pop/unshift', function () {
let list = new LinkedList<string>();
list.push('a');
list.push('b');

assertElements(list, 'a', 'b');

let a = list.shift();
assert.equal(a, 'a');
assertElements(list, 'b');

list.unshift('a');
assertElements(list, 'a', 'b');

let b = list.pop();
assert.equal(b, 'b');
assertElements(list, 'a');

assert.deepEqual(
list.toArray(),
[
'boo',
'far',
'bar',
'foo',
]
);
});
});

0 comments on commit 3cd6d8a

Please sign in to comment.