Skip to content

Commit 17cfa43

Browse files
committed
chapter 05: [LinkedLists]
1 parent 1a4f18e commit 17cfa43

10 files changed

+477
-169
lines changed

src/ts/data-structures/circular-linked-list.ts

+11-28
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import LinkedList from './linked-list';
33
import { Node } from './models/linked-list-models';
44

55
export default class CircularLinkedList<T> extends LinkedList<T> {
6-
76
constructor(protected equalsFn: IEqualsFunction<T> = defaultEquals) {
87
super(equalsFn);
98
}
@@ -24,9 +23,7 @@ export default class CircularLinkedList<T> extends LinkedList<T> {
2423
this.head = node;
2524
} else {
2625
current = this.getLastElement();
27-
if (current != null) {
28-
current.next = node;
29-
}
26+
current.next = node;
3027
}
3128

3229
// set node.next to head - to have circular list
@@ -35,7 +32,7 @@ export default class CircularLinkedList<T> extends LinkedList<T> {
3532
this.count++;
3633
}
3734

38-
insert(index: number, element: T) {
35+
insert(element: T, index: number) {
3936
if (index >= 0 && index <= this.count) {
4037
const node = new Node(element);
4138
let current = this.head;
@@ -50,16 +47,12 @@ export default class CircularLinkedList<T> extends LinkedList<T> {
5047
current = this.getLastElement();
5148
// update last element
5249
this.head = node;
53-
if (current != null) {
54-
current.next = this.head;
55-
}
50+
current.next = this.head;
5651
}
5752
} else {
5853
const previous = this.getElementAt(index - 1);
59-
if (previous != null) {
60-
node.next = previous.next;
61-
previous.next = node;
62-
}
54+
node.next = previous.next;
55+
previous.next = node;
6356
}
6457
this.count++;
6558
return true;
@@ -78,28 +71,18 @@ export default class CircularLinkedList<T> extends LinkedList<T> {
7871
this.head = undefined;
7972
} else {
8073
current = this.getLastElement();
81-
if (this.head != null) {
82-
this.head = this.head.next;
83-
}
84-
if (current != null) {
85-
current.next = this.head;
86-
}
74+
this.head = this.head.next;
75+
current.next = this.head;
8776
current = removed;
8877
}
8978
} else {
9079
// no need to update last element for circular list
9180
const previous = this.getElementAt(index - 1);
92-
if (previous != null) {
93-
current = previous.next;
94-
if (current != null) {
95-
previous.next = current.next;
96-
}
97-
}
98-
}
99-
if (current != null) {
100-
this.count--;
101-
return current.element;
81+
current = previous.next;
82+
previous.next = current.next;
10283
}
84+
this.count--;
85+
return current.element;
10386
}
10487
return undefined;
10588
}

src/ts/data-structures/doubly-linked-list.ts

+28-52
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,14 @@ export default class DoublyLinkedList<T> extends LinkedList<T> {
1818
this.tail = node; // NEW
1919
} else {
2020
// attach to the tail node // NEW
21-
if (this.tail != null) {
22-
this.tail.next = node;
23-
node.prev = this.tail;
24-
this.tail = node;
25-
}
21+
this.tail.next = node;
22+
node.prev = this.tail;
23+
this.tail = node;
2624
}
2725
this.count++;
2826
}
2927

30-
insert(index: number, element: T) {
28+
insert(element: T, index: number) {
3129
if (index >= 0 && index <= this.count) {
3230
const node = new DoublyNode(element);
3331
let current = this.head;
@@ -46,23 +44,17 @@ export default class DoublyLinkedList<T> extends LinkedList<T> {
4644
// last item // NEW
4745

4846
current = this.tail; // {2}
49-
if (current != null) {
50-
current.next = node;
51-
node.prev = current;
52-
this.tail = node;
53-
}
47+
current.next = node;
48+
node.prev = current;
49+
this.tail = node;
5450
} else {
5551
const previous = this.getElementAt(index - 1);
56-
if (previous != null) {
57-
current = previous.next;
58-
node.next = current;
59-
previous.next = node;
60-
61-
if (current != null) {
62-
current.prev = node; // NEW
63-
node.prev = previous; // NEW
64-
}
65-
}
52+
current = previous.next;
53+
node.next = current;
54+
previous.next = node;
55+
56+
current.prev = node; // NEW
57+
node.prev = previous; // NEW
6658
}
6759
this.count++;
6860
return true;
@@ -75,44 +67,28 @@ export default class DoublyLinkedList<T> extends LinkedList<T> {
7567
let current = this.head;
7668

7769
if (index === 0) {
78-
if (this.head != null) {
79-
this.head = this.head.next; // {1}
80-
// if there is only one item, then we update tail as well //NEW
81-
if (this.count === 1) {
82-
// {2}
83-
this.tail = undefined;
84-
} else {
85-
if (this.head != null) {
86-
this.head.prev = undefined; // {3}
87-
}
88-
}
70+
this.head = this.head.next; // {1}
71+
// if there is only one item, then we update tail as well //NEW
72+
if (this.count === 1) {
73+
// {2}
74+
this.tail = undefined;
75+
} else {
76+
this.head.prev = undefined; // {3}
8977
}
9078
} else if (index === this.count - 1) {
9179
// last item //NEW
9280
current = this.tail; // {4}
93-
if (current != null) {
94-
this.tail = current.prev;
95-
if (this.tail) {
96-
this.tail.next = undefined;
97-
}
98-
}
81+
this.tail = current.prev;
82+
this.tail.next = undefined;
9983
} else {
10084
current = this.getElementAt(index);
101-
if (current != null) {
102-
const previous = current.prev;
103-
if (previous != null) {
104-
// link previous with current's next - skip it to remove
105-
previous.next = current.next; // {6}
106-
if (current != null && current.next != null) {
107-
current.next.prev = previous; // NEW
108-
}
109-
}
110-
}
111-
}
112-
if (current != null) {
113-
this.count--;
114-
return current.element;
85+
const previous = current.prev;
86+
// link previous with current's next - skip it to remove
87+
previous.next = current.next; // {6}
88+
current.next.prev = previous; // NEW
11589
}
90+
this.count--;
91+
return current.element;
11692
}
11793
return undefined;
11894
}

src/ts/data-structures/linked-list.ts

+14-51
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
import { defaultCompare, defaultEquals, ICompareFunction, IEqualsFunction } from '../util';
1+
import { defaultEquals, IEqualsFunction } from '../util';
22
import { Node } from './models/linked-list-models';
33

44
export default class LinkedList<T> {
55
protected count = 0;
66
protected head: Node<T> | undefined;
77

8-
constructor(
9-
protected equalsFn: IEqualsFunction<T> = defaultEquals,
10-
protected compareFn: ICompareFunction<T> = defaultCompare
11-
) {}
8+
constructor(protected equalsFn: IEqualsFunction<T> = defaultEquals) {}
129

1310
push(element: T) {
1411
const node = new Node(element);
1512
let current;
1613

17-
if (this.head == null) { // catches null && undefined
14+
if (this.head == null) {
15+
// catches null && undefined
1816
this.head = node;
1917
} else {
2018
current = this.head;
@@ -31,17 +29,15 @@ export default class LinkedList<T> {
3129
getElementAt(index: number) {
3230
if (index >= 0 && index <= this.count) {
3331
let node = this.head;
34-
for (let i = 0; i < index; i++) {
35-
if (node != null) {
36-
node = node.next;
37-
}
32+
for (let i = 0; i < index && node != null; i++) {
33+
node = node.next;
3834
}
3935
return node;
4036
}
4137
return undefined;
4238
}
4339

44-
insert(index: number, element: T) {
40+
insert(element: T, index: number) {
4541
if (index >= 0 && index <= this.count) {
4642
const node = new Node(element);
4743
const current = this.head;
@@ -51,61 +47,28 @@ export default class LinkedList<T> {
5147
this.head = node;
5248
} else {
5349
const previous = this.getElementAt(index - 1);
54-
if (previous != null) {
55-
node.next = previous.next;
56-
previous.next = node;
57-
}
50+
node.next = previous.next;
51+
previous.next = node;
5852
}
5953
this.count++;
6054
return true;
6155
}
6256
return false;
6357
}
6458

65-
insertSorted(element: T) {
66-
if (this.isEmpty()) {
67-
this.push(element);
68-
} else {
69-
const index = this.getIndexNextSortedElement(element);
70-
this.insert(index, element);
71-
}
72-
}
73-
74-
private getIndexNextSortedElement(element: T) {
75-
let current = this.head;
76-
77-
for (let i = 0; i < this.size() && current; i++) {
78-
const comp = this.compareFn(element, current.element);
79-
if (comp >= 0) {
80-
return i;
81-
}
82-
current = current.next;
83-
}
84-
85-
return -1;
86-
}
87-
8859
removeAt(index: number) {
8960
if (index >= 0 && index < this.count) {
9061
let current = this.head;
9162

9263
if (index === 0) {
93-
if (this.head != null) {
94-
this.head = this.head.next;
95-
}
64+
this.head = current.next;
9665
} else {
9766
const previous = this.getElementAt(index - 1);
98-
if (previous != null) {
99-
current = previous.next;
100-
if (current != null) {
101-
previous.next = current.next;
102-
}
103-
}
104-
}
105-
if (current != null) {
106-
this.count--;
107-
return current.element;
67+
current = previous.next;
68+
previous.next = current.next;
10869
}
70+
this.count--;
71+
return current.element;
10972
}
11073
return undefined;
11174
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { Compare, defaultCompare, defaultEquals, ICompareFunction, IEqualsFunction } from '../util';
2+
import LinkedList from './linked-list';
3+
4+
export default class SortedLinkedList<T> extends LinkedList<T> {
5+
constructor(
6+
protected equalsFn: IEqualsFunction<T> = defaultEquals,
7+
protected compareFn: ICompareFunction<T> = defaultCompare
8+
) {
9+
super(equalsFn);
10+
}
11+
12+
push(element: T) {
13+
if (this.isEmpty()) {
14+
super.push(element);
15+
} else {
16+
const index = this.getIndexNextSortedElement(element);
17+
super.insert(element, index);
18+
}
19+
}
20+
21+
insert(element: T, index: number = 0) {
22+
if (this.isEmpty()) {
23+
return super.insert(element, 0);
24+
}
25+
index = this.getIndexNextSortedElement(element);
26+
return super.insert(element, index);
27+
}
28+
29+
private getIndexNextSortedElement(element: T) {
30+
let current = this.head;
31+
let i = 0;
32+
33+
for (; i < this.size() && current; i++) {
34+
const comp = this.compareFn(element, current.element);
35+
if (comp === Compare.LESS_THAN) {
36+
return i;
37+
}
38+
current = current.next;
39+
}
40+
41+
return i;
42+
}
43+
}

src/ts/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import * as _util from './util';
2+
13
export { default as CircularLinkedList } from './data-structures/circular-linked-list';
24
export { default as DoublyLinkedList } from './data-structures/doubly-linked-list';
35
export { default as LinkedList } from './data-structures/linked-list';
6+
export { default as SortedLinkedList } from './data-structures/sorted-linked-list';
47

5-
import * as _util from './util';
68
export const util = _util;
79

810
/* import { hotPotato } from './others/hot-potato';

0 commit comments

Comments
 (0)