Skip to content

Commit c41407d

Browse files
committed
Finalized OneLinkList and added auto testing environment.
1 parent b3f0213 commit c41407d

File tree

7 files changed

+392
-90
lines changed

7 files changed

+392
-90
lines changed

JS Data Structures/Data Structs/Linked Lists.js renamed to JS Data Structures/Data Structs/OneLinkList.js

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ const Err = require('../misc/Errors');
1010
class OneLinkList {
1111
/**
1212
* OneLinkList constructor.
13+
* @param {any} data - The data for the first item in the list to hold.
1314
*/
1415
constructor(data) {
1516
// List properties.
1617
this.count = 0;
17-
this.first = new Item();
18-
this.last = new Item();
18+
this.first = null;
19+
this.last = null;
1920

20-
// Check if first item was passed as data.
21+
// Check if first item data was passed.
2122
if(data !== undefined) {
2223
this.AddToEnd(data);
2324
}
@@ -39,30 +40,29 @@ class Item {
3940
}
4041
}
4142

42-
// exports.TwoLinkList = class TwoLinkList {
43-
// constructor() {
44-
// console.log('In the TwoLinkList default ctor.\n')
45-
// }
46-
// }
47-
4843
/**
4944
* Method to add a new item to the end of the list.
5045
* @param {any} data - The data the new item holds.
5146
*/
5247
OneLinkList.prototype.AddToEnd = function(data) {
53-
let newNode = new Item(data),
54-
currNode = this.first;
48+
// Check if valid data was passed as an argument.
49+
if(data === undefined) {
50+
throw new Err.DSException(Err.ListErr.InvalidData(), 301);
51+
}
52+
53+
let newItem = new Item(data),
54+
currItem = this.first;
5555

56-
if(this.count == 0) {
57-
this.first = newNode;
56+
if(this.count === 0) {
57+
this.first = newItem;
5858
this.last = this.first;
5959
} else {
60-
while(currNode.next != null) {
61-
currNode = currNode.next;
60+
while(currItem.next !== null) {
61+
currItem = currItem.next;
6262
}
6363

64-
currNode.next = newNode;
65-
this.last = newNode;
64+
currItem.next = newItem;
65+
this.last = newItem;
6666
}
6767

6868
this.count++;
@@ -76,11 +76,11 @@ OneLinkList.prototype.FindAt = function(position) {
7676
// Show error when trying to access position outside of list.
7777
if(this.count === 0 || position > this.count || position < 1) {
7878
throw new Err.DSException(Err.ListErr.NonExistant(OneLinkList.name), 101);
79-
} else if(position % 1 != 0 || typeof(position) != Number.name.toLowerCase()) {
79+
} else if(position % 1 != 0 || typeof position != Number.name.toLowerCase()) {
8080
throw new Err.DSException(Err.ListErr.InvalidPosition(), 102);
8181
}
8282

83-
// Linearly search for item (1 -> last).
83+
// Sequentially search for item (1 -> last).
8484
let currItem = this.first;
8585
for(let currCount = 1; currCount < position; currCount++) {
8686
currItem = currItem.next;
@@ -97,7 +97,9 @@ OneLinkList.prototype.RemoveAt = function(position) {
9797
// Show error when trying to access position outside of list.
9898
if(this.count === 0 || position > this.count || position < 1) {
9999
throw new Err.DSException(Err.ListErr.NonExistant(OneLinkList.name), 201);
100-
} else if(position % 1 != 0 || typeof(position) != Number.name.toLowerCase()) {
100+
}
101+
// Show error when the position is invalid.
102+
else if(position % 1 != 0 || typeof(position) != Number.name.toLowerCase()) {
101103
throw new Err.DSException(Err.ListErr.InvalidPosition(), 202);
102104
}
103105

@@ -115,6 +117,77 @@ OneLinkList.prototype.RemoveAt = function(position) {
115117
this.count--;
116118
}
117119

120+
/**
121+
* Removes the first item matching the data passed.
122+
* @param {any} data - The data to search and destroy.
123+
*/
124+
OneLinkList.prototype.RemoveThis = function(data) {
125+
// Check if the list is empty.
126+
if(this.count === 0) {
127+
throw new Err.DSException(Err.ListErr.NonExistant(OneLinkList.name), 401);
128+
}
129+
// Check if valid data was passed as an argument.
130+
else if(data === undefined) {
131+
throw new Err.DSException(Err.ListErr.InvalidData(), 402);
132+
}
133+
134+
// Search through list sequentially for the data.
135+
let currItem = this.first,
136+
itemToRemove;
137+
138+
// Handle list with one item.
139+
if(this.count === 1) {
140+
if(typeof(data) == 'object') {
141+
if(JSON.stringify(currItem.data) === JSON.stringify(data)) {
142+
this.first = null;
143+
this.last = null;
144+
this.count--;
145+
return;
146+
}
147+
} else {
148+
if(currItem.data === data) {
149+
this.first = null;
150+
this.last = null;
151+
this.count--;
152+
return;
153+
}
154+
}
155+
}
156+
// Handle list with more than one item.
157+
else {
158+
// If data param is an object.
159+
if(typeof(data) == 'object') {
160+
while(currItem.next) {
161+
if(JSON.stringify(currItem.next.data) === JSON.stringify(data)) {
162+
itemToRemove = currItem.next;
163+
currItem.next = currItem.next.next;
164+
break;
165+
}
166+
167+
currItem = currItem.next;
168+
}
169+
}
170+
// Else data param is a non-reference data type.
171+
else {
172+
while(currItem.next) {
173+
if(currItem.next.data === data) {
174+
itemToRemove = currItem.next;
175+
currItem.next = currItem.next.next;
176+
break;
177+
}
178+
179+
currItem = currItem.next;
180+
}
181+
}
182+
}
183+
184+
delete itemToRemove;
185+
}
186+
187+
/**
188+
* Checks if the list has an item with the passed data.
189+
* @param {any} data - The data to check for.
190+
*/
118191
OneLinkList.prototype.Contains = function(data) {
119192
// Check if valid data was passed as an argument.
120193
if(!data) {
@@ -154,17 +227,26 @@ OneLinkList.prototype.Contains = function(data) {
154227
* Print all items of the list to the console.
155228
*/
156229
OneLinkList.prototype.PrintAll = function() {
230+
// Check if the list is empty.
231+
if(this.count === 0 || !(this.first instanceof Item)) {
232+
console.log('Empty list.');
233+
return;
234+
}
235+
236+
// Print each item to the console.
157237
let curr = this.first;
158-
while(curr.next) {
238+
while(curr) {
159239
console.log(curr);
160240
curr = curr.next;
161241
}
162-
console.log(curr);
163242
}
164243

165244
/**
166245
* All linked list exports.
167246
*/
168-
module.exports = {
169-
OneLinkList: OneLinkList,
170-
}
247+
module.exports = OneLinkList;
248+
249+
// Use below if exporting multiple items.
250+
// module.exports = {
251+
// OneLinkList: OneLinkList,
252+
// }
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
const err = require('../misc/Errors');
2+
3+
class TwoLinkList {
4+
/**
5+
* TwoLinkList constructor.
6+
* @param {any} data - The data for the first item in the list to hold.
7+
*/
8+
constructor(data) {
9+
// List propterties.
10+
this.count = 0;
11+
this.first = null;
12+
this.last = null;
13+
14+
// Check if first item data was passed.
15+
if(data !== undefined) {
16+
this.AddToEnd(data);
17+
}
18+
}
19+
}
20+
21+
/**
22+
* The item container for a linked list.
23+
*/
24+
class Item {
25+
/**
26+
* Constructor to create a new list item.
27+
* @param {any} data - The data the new item should hold.
28+
*/
29+
constructor(data = null) {
30+
this.data = data;
31+
this.next = null;
32+
this.prev = null;
33+
}
34+
}
35+
36+
/**
37+
* Method to add a new item to the end of the list.
38+
* @param {any} data - The data the new item holds.
39+
*/
40+
TwoLinkList.prototype.AddToEnd = function(data) {
41+
// Check if valid data was passed as an argument.
42+
if(data === undefined) {
43+
throw new Err.DSException(Err.ListErr.InvalidData(), 301);
44+
}
45+
46+
let newItem = new Item(data)
47+
48+
if(this.count === 0) {
49+
this.first = newItem;
50+
this.last = this.first;
51+
} else if(this.count === 1) {
52+
newItem.prev = this.first;
53+
this.first.next = newItem;
54+
this.last = newItem;
55+
} else {
56+
newItem.prev = this.last;
57+
this.last.next = newItem;
58+
this.last = newItem;
59+
}
60+
61+
this.count++;
62+
}
63+
64+
/**
65+
* Returns the item at the desired position in the list.
66+
* @param {Number} position - The position in the list where the item should be located.
67+
*/
68+
TwoLinkList.prototype.FindAt = function(position) {
69+
// Show error when trying to access position outside of list.
70+
if(this.count === 0 || position > this.count || position < 1) {
71+
throw new Err.DSException(Err.ListErr.NonExistant(OneLinkList.name), 101);
72+
} else if(position % 1 != 0 || typeof position != Number.name.toLowerCase()) {
73+
throw new Err.DSException(Err.ListErr.InvalidPosition(), 102);
74+
}
75+
76+
// Sequentially search for item (1 -> last).
77+
let currItem = this.first;
78+
for(let currCount = 1; currCount < position; currCount++) {
79+
currItem = currItem.next;
80+
}
81+
82+
return currItem;
83+
}
84+
85+
/**
86+
* Removes the item at the desired position in the list.
87+
* @param {Number} position - The position in the list where the item should be located.
88+
*/
89+
TwoLinkList.prototype.RemoveAt = function(position) {
90+
// Show error when trying to access position outside of list.
91+
if(this.count === 0 || position > this.count || position < 1) {
92+
throw new Err.DSException(Err.ListErr.NonExistant(OneLinkList.name), 201);
93+
}
94+
// Show error when the position is invalid.
95+
else if(position % 1 != 0 || typeof(position) != Number.name.toLowerCase()) {
96+
throw new Err.DSException(Err.ListErr.InvalidPosition(), 202);
97+
}
98+
99+
// Linearly search for item before desired item (1 -> last).
100+
let currItem = this.first,
101+
beforeItemToRemove, itemToRemove, currCount;
102+
for(currCount = 1; currCount < position; currCount++) {
103+
beforeItemToRemove = currItem;
104+
itemToRemove = currItem.next;
105+
currItem = currItem.next;
106+
}
107+
108+
//if(currCount)
109+
beforeItemToRemove.next = itemToRemove.next;
110+
delete itemToRemove;
111+
this.count--;
112+
}
113+
114+
/**
115+
* Print all items of the list to the console.
116+
*/
117+
TwoLinkList.prototype.PrintAll = function() {
118+
// Check if list is empty.
119+
if(this.count === 0 || !(this.first instanceof Item)) {
120+
console.log('Empty list.');
121+
return;
122+
}
123+
124+
// Print each item to the console sequentially.
125+
let curr = this.first;
126+
while(curr) {
127+
console.log(curr);
128+
curr = curr.next;
129+
}
130+
}
131+
132+
module.exports = TwoLinkList;

0 commit comments

Comments
 (0)