Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f71a3eb

Browse files
Implemented Singly Linked List (#5 IP)
1 parent 565c911 commit f71a3eb

File tree

3 files changed

+316
-1
lines changed

3 files changed

+316
-1
lines changed
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
import Node from './NodeLL.ts';
2+
3+
export default class LinkedList<T> {
4+
private head: Node<T> | null;
5+
private tail: Node<T> | null;
6+
private length: number;
7+
8+
constructor() {
9+
this.head = null;
10+
this.tail = null;
11+
this.length = 0;
12+
}
13+
14+
public getLength(): number {
15+
return this.length;
16+
}
17+
18+
public isEmpty(): boolean {
19+
return this.length === 0;
20+
}
21+
22+
public append(value: T): boolean {
23+
const newNode = new Node(value);
24+
25+
if (!this.tail) {
26+
this.head = newNode;
27+
this.tail = newNode;
28+
}
29+
else {
30+
this.tail.setNext(newNode);
31+
this.tail = this.tail.getNext();
32+
}
33+
++this.length;
34+
35+
return true;
36+
}
37+
38+
public prepend(value: T): boolean {
39+
const newNode = new Node(value);
40+
41+
if (!this.head) {
42+
this.head = newNode;
43+
this.tail = newNode;
44+
} else {
45+
newNode.setNext(this.head);
46+
this.head = newNode;
47+
}
48+
++this.length;
49+
50+
return true;
51+
}
52+
53+
public insert(value: T, atIndex: number): boolean | null {
54+
if (atIndex < 0 || atIndex > this.length) return null;
55+
if (!this.head) {
56+
this.prepend(value);
57+
return true;
58+
}
59+
if (atIndex === this.length) {
60+
this.append(value);
61+
return true;
62+
}
63+
64+
65+
const newNode = new Node(value);
66+
67+
let currentNode: Node<T> = this.head;
68+
69+
for (let i=0; i < atIndex-1; ++i) {
70+
currentNode = currentNode.getNext();
71+
}
72+
73+
newNode.setNext(currentNode.getNext());
74+
currentNode.setNext(newNode);
75+
76+
++this.length;
77+
78+
return true;
79+
}
80+
81+
public removeElementAtIndex(index: number): T | null {
82+
if (index > this.length-1 || index < 0) return null;
83+
if (this.length === 0 || !this.head) return null;
84+
85+
let value = null;
86+
87+
if (index===0) {
88+
value = this.head.getValue();
89+
this.head = this.head.getNext();
90+
}
91+
else {
92+
let currentNode = this.head;
93+
94+
for (let i=0; i < index; ++i) { // Traverse linked list to find Node index-1
95+
if (i===index-1) {
96+
value = currentNode.getNext().getValue(); // Store Node value
97+
break;
98+
}
99+
currentNode = currentNode.getNext();
100+
}
101+
currentNode.setNext(currentNode.getNext().getNext()); // Manipulate pointers to mark deleted Node for garbage collection
102+
}
103+
104+
--this.length; // Decrement length
105+
106+
return value;
107+
}
108+
109+
public getValueAtIndex(index: number): T | null {
110+
if (index > this.length || index < 0) return null; // Validate input
111+
if (this.length === 0 || !this.head || !this.tail) return null; // Verify that list is not empty
112+
if (index === this.length-1) return this.tail.getValue(); // Optimization when retrieving last element
113+
114+
let currentNode = this.head;
115+
116+
for (let i=0; i <= index; ++i) {
117+
if (i===index) return currentNode.getValue();
118+
currentNode = currentNode.getNext();
119+
}
120+
121+
return null;
122+
}
123+
124+
/**
125+
* Find the index of the desired element if it exists.
126+
* WARNING: Usable only for trees of primitive types, i.e. number, string
127+
* @param value Value to search for, i.e. desired element
128+
* @returns Numerical index of element position
129+
*/
130+
public searchFor(value: T): number | null {
131+
if (this.length === 0 || !this.head) return null;
132+
133+
let currentNode = this.head;
134+
135+
for (let i=0; !!currentNode; ++i) {
136+
if (currentNode.getValue()===value) return i; // Value matches, so return index
137+
currentNode = currentNode.getNext(); // Otherwise, continue searching
138+
}
139+
return null;
140+
}
141+
142+
/**
143+
* Remove all nodes from list. Constant Time O(1)
144+
*/
145+
public empty(): boolean {
146+
this.head = null;
147+
this.tail = null;
148+
this.length = 0;
149+
return true;
150+
}
151+
152+
public toString(nodesPerGroup?: number): string {
153+
if (this.length === 0 || !this.head) {
154+
return "";
155+
}
156+
157+
nodesPerGroup = nodesPerGroup ? nodesPerGroup : 8;
158+
159+
const LABEL_HEAD = 'HEAD';
160+
const LABEL_TAIL = 'TAIL';
161+
162+
let listAsString: string = `--- Node Count: ${this.length}\n`;
163+
let currentNode: Node<any> = this.head;
164+
165+
for (let i=0; i < this.length; ++i) {
166+
listAsString += `${Array(i%nodesPerGroup).fill('\t').join('')} ${i===0 ? LABEL_HEAD : '–'} ${currentNode} ${i===this.length-1 ? LABEL_TAIL : ''}\n`;
167+
168+
if (currentNode.hasNext()) {
169+
currentNode = currentNode.getNext();
170+
}
171+
}
172+
173+
return listAsString;
174+
}
175+
}
176+
177+
function printLinkedList(linkedList: LinkedList<any>): void {
178+
if (linkedList.isEmpty()) {
179+
console.log('Empty linked list -_-');
180+
return;
181+
}
182+
console.log(linkedList.toString());
183+
}
184+
185+
function printSearchFor(value: any, linkedList: LinkedList<any>): void {
186+
console.log(JSON.stringify(value), 'found at index:', linkedList.searchFor(value));
187+
}
188+
189+
function printGetValueAtIndex(index: number, linkedList: LinkedList<any>) {
190+
console.log('Element at index', index +':', linkedList.getValueAtIndex(index));
191+
}
192+
193+
function printRemoveIndex(index: number, linkedList: LinkedList<any>) {
194+
console.log('Removing element at index', index + ':', JSON.stringify(linkedList.removeElementAtIndex(index)));
195+
}
196+
197+
198+
199+
//---------------------------------------------------------------------
200+
// ---------- MAIN PROGRAM ----------
201+
//---------------------------------------------------------------------
202+
if (import.meta.main) {
203+
204+
const ATLA = new LinkedList<string>();
205+
206+
ATLA.append('Sokka');
207+
ATLA.append('Katara');
208+
ATLA.prepend('Appa');
209+
210+
printLinkedList(ATLA);
211+
212+
ATLA.insert('Aang', 2);
213+
ATLA.insert('Zuko', 1);
214+
ATLA.insert('Iroh', 4);
215+
216+
printLinkedList(ATLA);
217+
218+
printSearchFor('Iroh', ATLA);
219+
printSearchFor('Sok', ATLA);
220+
printSearchFor('Sokka', ATLA);
221+
printSearchFor('Appa', ATLA);
222+
printSearchFor('Zuko', ATLA);
223+
printGetValueAtIndex(2, ATLA);
224+
printGetValueAtIndex(5, ATLA);
225+
console.log('----------------------------------');
226+
227+
printRemoveIndex(1, ATLA);
228+
printLinkedList(ATLA);
229+
printRemoveIndex(0, ATLA);
230+
printLinkedList(ATLA);
231+
printRemoveIndex(2, ATLA);
232+
printLinkedList(ATLA);
233+
printRemoveIndex(2, ATLA);
234+
printLinkedList(ATLA);
235+
printRemoveIndex(1, ATLA);
236+
printRemoveIndex(0, ATLA);
237+
printLinkedList(ATLA);
238+
console.log('----------------------------------');
239+
240+
ATLA.insert('Katara', 0);
241+
printLinkedList(ATLA);
242+
ATLA.append('Aang');
243+
printLinkedList(ATLA);
244+
245+
// RUN: deno run Data-Structures/Linked-Lists/LinkedList.ts
246+
}
247+
248+
249+
// --------------------------- Terminal Output: ---------------------------
250+
// --- Node Count: 3
251+
// HEAD { value: "Appa", next: true }
252+
// – { value: "Sokka", next: true }
253+
// – { value: "Katara", next: false } TAIL
254+
//
255+
// --- Node Count: 6
256+
// HEAD { value: "Appa", next: true }
257+
// – { value: "Zuko", next: true }
258+
// – { value: "Sokka", next: true }
259+
// – { value: "Aang", next: true }
260+
// – { value: "Iroh", next: true }
261+
// – { value: "Katara", next: false } TAIL
262+
//
263+
// "Iroh" found at index: 4
264+
// "Sok" found at index: null
265+
// "Sokka" found at index: 2
266+
// "Appa" found at index: 0
267+
// "Zuko" found at index: 1
268+
// Element at index 2: Sokka
269+
// Element at index 5: Katara
270+
// ----------------------------------
271+
// Removing element at index 1: "Zuko"
272+
// --- Node Count: 5
273+
// HEAD { value: "Appa", next: true }
274+
// – { value: "Sokka", next: true }
275+
// – { value: "Aang", next: true }
276+
// – { value: "Iroh", next: true }
277+
// – { value: "Katara", next: false } TAIL
278+
//
279+
// Removing element at index 0: "Appa"
280+
// --- Node Count: 4
281+
// HEAD { value: "Sokka", next: true }
282+
// – { value: "Aang", next: true }
283+
// – { value: "Iroh", next: true }
284+
// – { value: "Katara", next: false } TAIL
285+
//
286+
// Removing element at index 2: "Iroh"
287+
// --- Node Count: 3
288+
// HEAD { value: "Sokka", next: true }
289+
// – { value: "Aang", next: true }
290+
// – { value: "Katara", next: false } TAIL
291+
//
292+
// Removing element at index 2: "Katara"
293+
// --- Node Count: 2
294+
// HEAD { value: "Sokka", next: true }
295+
// – { value: "Aang", next: false } TAIL
296+
//
297+
// Removing element at index 1: "Aang"
298+
// Removing element at index 0: "Sokka"
299+
// Empty linked list -_-
300+
// ----------------------------------
301+
// --- Node Count: 1
302+
// HEAD { value: "Katara", next: false } TAIL
303+
//
304+
// --- Node Count: 2
305+
// HEAD { value: "Katara", next: true }
306+
// – { value: "Aang", next: false } TAIL

‎Data-Structures/Linked-Lists/NodeLL.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,12 @@ export default class LinkedListNode<T> {
2222
public getNext(): LinkedListNode<T> | any {
2323
return this.next;
2424
}
25+
26+
public hasNext(): boolean {
27+
return !!this.next;
28+
}
29+
30+
public toString(): string {
31+
return `{ value: ${JSON.stringify(this.value)}, next: ${!!this.next} }`;
32+
}
2533
}

‎Data-Structures/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
- [Visualizing Data Structures & Algorithms](https://visualgo.net/en)
2222

2323
### Trees
24-
- [BST: VisuAlgo](https://visualgo.net/bn/bst?slide=1)
24+
- [Linked List: VisuAlgo](https://visualgo.net/en/list)
25+
- [Binary Search Tree: VisuAlgo](https://visualgo.net/bn/bst?slide=1)
2526
- [Binary Heap: VisuAlgo](https://visualgo.net/en/heap)
2627
- [AVL Tree Visualization](https://www.cs.usfca.edu/~galles/visualization/AVLtree.html)
2728
- [Red-Black Tree Visualization](https://www.cs.usfca.edu/~galles/visualization/RedBlack.html)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /