implemented linked list, basic testing
This commit is contained in:
@@ -14,6 +14,10 @@ export default class ListNode<T> extends Node<T> {
|
||||
this.next = node;
|
||||
}
|
||||
|
||||
setPreviousNode(node: ListNode<T>) {
|
||||
this.prev = node;
|
||||
}
|
||||
|
||||
get nextNode() {
|
||||
return this.next;
|
||||
}
|
||||
|
||||
180
src/lib/LinkedList/index.ts
Normal file
180
src/lib/LinkedList/index.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import ListNode from "./ListNode";
|
||||
|
||||
export default class LinkedList<T> {
|
||||
private head: ListNode<T> | null
|
||||
private tail: ListNode<T> | null
|
||||
|
||||
constructor(head?: ListNode<T>, tail?: ListNode<T>) {
|
||||
this.head = head || null;
|
||||
this.tail = tail || null;
|
||||
}
|
||||
|
||||
getHead() {
|
||||
return this.head;
|
||||
}
|
||||
|
||||
getTail() {
|
||||
return this.tail;
|
||||
}
|
||||
|
||||
exchange(prev: ListNode<T>, next: ListNode<T>) {
|
||||
prev.setNextNode(next);
|
||||
next.setPreviousNode(prev);
|
||||
}
|
||||
|
||||
addToHead(data: T) {
|
||||
// create a new node for the data to insert, and store the current head
|
||||
const newHead = new ListNode(data);
|
||||
const current = this.head;
|
||||
|
||||
// swap the positions of these elements if current head is defined
|
||||
if (current) this.exchange(current, newHead);
|
||||
|
||||
// assign the new head in the class instance
|
||||
this.head = newHead;
|
||||
|
||||
// if there is no tail after this change, additionally assign the new head as the new tail
|
||||
if (!this.tail) this.tail = newHead;
|
||||
}
|
||||
|
||||
addManyToHead(...items: T[]) {
|
||||
for (let each of items) {
|
||||
this.addToHead(each);
|
||||
}
|
||||
}
|
||||
|
||||
// inverse of the logic above
|
||||
addToTail(data: T) {
|
||||
const newTail = new ListNode(data);
|
||||
const current = this.tail;
|
||||
|
||||
if (current) this.exchange(current, newTail);
|
||||
|
||||
this.tail = newTail;
|
||||
if (!this.head) this.head = newTail;
|
||||
}
|
||||
|
||||
removeHead(): T | null {
|
||||
const toRemove = this.head;
|
||||
|
||||
// if there's nothing to remove, don't remove it
|
||||
if (!toRemove) return null;
|
||||
|
||||
const newHead = toRemove.nextNode;
|
||||
this.head = newHead;
|
||||
|
||||
if (toRemove == this.tail) {
|
||||
this.removeTail();
|
||||
}
|
||||
|
||||
return toRemove.data as T;
|
||||
}
|
||||
|
||||
removeTail(): T | null {
|
||||
const toRemove = this.tail;
|
||||
if (!toRemove) return null;
|
||||
|
||||
const newTail = toRemove.nextNode;
|
||||
this.tail = newTail;
|
||||
|
||||
if (toRemove == this.head) {
|
||||
this.removeHead();
|
||||
}
|
||||
|
||||
return toRemove.data as T;
|
||||
}
|
||||
|
||||
findByNode(node: ListNode<T>): ListNode<T> | null {
|
||||
let current = this.head;
|
||||
while (current !== null) {
|
||||
if (current === node) {
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current.nextNode;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
findByData(data: T): ListNode<T> | null {
|
||||
let current = this.head;
|
||||
while (current !== null) {
|
||||
if (current.data === data) {
|
||||
return current;
|
||||
}
|
||||
|
||||
current = current.nextNode;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
removeByData(data: T): ListNode<T> | null {
|
||||
let targetNode: ListNode<T> | null = null;
|
||||
let current = this.head;
|
||||
while (current !== null) {
|
||||
if (current.data == data) {
|
||||
targetNode = current;
|
||||
break;
|
||||
}
|
||||
|
||||
current = current.nextNode;
|
||||
}
|
||||
|
||||
if (!targetNode) return null;
|
||||
|
||||
// by asserting above that target node is neither undefined, nor the head,
|
||||
// nor the tail of the list, we can assert that next and prev will both be
|
||||
// defined, as targetNode must be somewhere in the middle of the list
|
||||
if (targetNode === this.head) {
|
||||
this.removeHead();
|
||||
} else if (targetNode === this.tail) {
|
||||
this.removeTail();
|
||||
} else {
|
||||
// the method below effectively cuts the target node out of the list by assigning
|
||||
// is surrounding members to fill in the space previously taken up by target node
|
||||
const next = targetNode.nextNode;
|
||||
const prev = targetNode.prevNode;
|
||||
this.exchange(prev!, next!);
|
||||
}
|
||||
|
||||
return targetNode;
|
||||
}
|
||||
|
||||
removeAtPosition(pos: number): ListNode<T> | null {
|
||||
let targetNode: ListNode<T> | null = null;
|
||||
let current = this.head;
|
||||
let i = 0;
|
||||
|
||||
// traverse the list until you reach the end or the desired position,
|
||||
// whichever happens first
|
||||
while (current !== null) {
|
||||
if (i == pos) {
|
||||
targetNode = current;
|
||||
break;
|
||||
}
|
||||
current = current.nextNode;
|
||||
i++;
|
||||
}
|
||||
|
||||
// if you arrive at the end of the list without reaching the desired position,
|
||||
// the removal operation was unsuccessful (no element at this position)
|
||||
if (!targetNode && (i < pos)) {
|
||||
console.log("No element found at position " + pos);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (targetNode === this.head) {
|
||||
this.removeHead();
|
||||
} else if (targetNode === this.tail) {
|
||||
this.removeTail();
|
||||
} else {
|
||||
let next = targetNode?.nextNode;
|
||||
let prev = targetNode?.prevNode;
|
||||
this.exchange(prev!, next!);
|
||||
}
|
||||
|
||||
return targetNode;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
import Event from "../Event";
|
||||
import Graph from "../Graph/Graph";
|
||||
import GraphNode from "../Graph/GraphNode";
|
||||
import { ChordQuality, EventData } from "./index";
|
||||
import LinkedList from "../LinkedList/index";
|
||||
|
||||
const initialData: EventData = {
|
||||
const firstEvent: EventData = {
|
||||
root: "C",
|
||||
quality: ChordQuality.Major,
|
||||
duration: 4,
|
||||
@@ -17,17 +15,19 @@ const secondEvent: EventData = {
|
||||
beatStrength: "Strong"
|
||||
}
|
||||
|
||||
const sampleEvent = new Event(initialData);
|
||||
const nextEvent = new Event(secondEvent);
|
||||
const third = new Event(initialData);
|
||||
const fourth = new Event(secondEvent);
|
||||
const thirdEvent: EventData = {
|
||||
root: "F",
|
||||
quality: ChordQuality.Major,
|
||||
duration: 4,
|
||||
beatStrength: "Strong"
|
||||
}
|
||||
|
||||
third.setNextNode(fourth);
|
||||
nextEvent.setNextNode(third);
|
||||
sampleEvent.setNextNode(nextEvent);
|
||||
|
||||
console.log(sampleEvent.getEventData());
|
||||
console.log(sampleEvent.nextNode);
|
||||
const fourthEvent: EventData = {
|
||||
root: "F",
|
||||
quality: ChordQuality.Minor,
|
||||
duration: 4,
|
||||
beatStrength: "Strong"
|
||||
}
|
||||
|
||||
/***************
|
||||
***************
|
||||
@@ -40,14 +40,9 @@ console.log(sampleEvent.nextNode);
|
||||
***************
|
||||
***************/
|
||||
|
||||
const eventlist = new LinkedList<EventData>();
|
||||
eventlist.addManyToHead(firstEvent, secondEvent, thirdEvent, fourthEvent);
|
||||
|
||||
const sampleGraph = new Graph<EventData>(false, false);
|
||||
console.log(eventlist);
|
||||
|
||||
const pointA = new GraphNode(initialData);
|
||||
const pointB = new GraphNode(secondEvent);
|
||||
|
||||
sampleGraph.addPoints(pointA, pointB);
|
||||
|
||||
sampleGraph.print();
|
||||
|
||||
export default {sampleEvent, sampleGraph};
|
||||
export default { eventlist }
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import data from "./lib/helpers/sample";
|
||||
const { eventlist } = data;
|
||||
|
||||
const { sampleEvent, sampleGraph } = data;
|
||||
const content = JSON.stringify(sampleEvent.getEventData());
|
||||
console.log(sampleGraph.print());
|
||||
|
||||
export default content;
|
||||
// export default content;
|
||||
|
||||
// const parser = new DOMParser();
|
||||
// const document = parser.parseFromString(content, 'text/html');
|
||||
|
||||
Reference in New Issue
Block a user