@sridhar-mani/dsa-js
Version:
A full-fledged data structure library with linked list and double linked list implementation
228 lines (175 loc) • 5.25 kB
text/typescript
import CompareFunc from '../util/compareFuncs'
import LLNode from './llnode';
export default class LinkedList<T>{
private compare: CompareFunc<T>;
private head: LLNode<T> | null;
private tail: LLNode<T> | null;
private length: number;
constructor(compareFunc?: (a: T, b: T) => number){
this.compare = new CompareFunc<T>(compareFunc);
this.head = null;
this.tail=null
this.length = 0;
}
public append(value: T):this{
const newNode = new LLNode<T>(value);
if(!this.head){
this.head = this.tail= newNode
}else if(this.tail){
this.tail.next = newNode;
this.tail = newNode;
}
this.length++
return this
}
public prepend(value: T):this{
const newNode = new LLNode<T>(value,this.head);
this.head = newNode;
if(!this.tail){
this.tail = newNode
}
this.length++
return this
}
public insert(value:T,indexTo:number):this{
if(indexTo===0){
this.prepend(value)
return this
}else if(indexTo > (this.length-1)){
this.append(value)
return this
}else{
let temp = 0;
let currentNode = this.head;
const newNode = new LLNode(value);
while(temp!==indexTo && currentNode){
currentNode = currentNode?.next;
temp++;
}
if(currentNode){
newNode.next = currentNode.next;
currentNode.next = newNode;
return this
}else{
if(this.tail){
this.tail.next = newNode;
this.tail = newNode;
}else{
this.head = newNode;
this.tail = newNode;
}
}
}
return this
}
public getLength(){
return this.length;
}
public delete(value:any):void |null {
if(!this.head){
return null
}
if(this.head.value===value){
this.head = this.head.next;
this.length--
return
}
let curNode = this.head
while(curNode.next){
if(curNode.next.value===value){
curNode.next=curNode.next.next
this.length--
return
}
curNode=curNode.next
}
return null
}
public find({value,callback}:{value?:T, callback?:(val:T)=>boolean}):LLNode<T> | null{
if(!this.head){
return null
}
let curNode: LLNode<T> | null = this.head
while(curNode ){
if(callback?.(curNode.value)){
return curNode
}
if(value!==undefined && this.compare.equal(curNode.value,value)){
return curNode
}
curNode = curNode.next
}
return null
}
public deleteTail(){
if(!this.head) return null
const deleteTail = this.tail;
if(this.tail===this.head){
this.head=null
this.tail=null
return deleteTail
}
let curNode = this.head;
while( curNode.next && curNode?.next!==this.tail){
curNode=curNode.next
}
curNode.next=null
this.tail =curNode
return deleteTail
}
public deleteHead(){
if(!this.head) return null
const deleteHead = this.head;
if(this.head===this.tail){
this.head=null;
this.tail=null
return deleteHead
}
if(this.head) this.head = this.head?.next
return deleteHead
}
public getHead(){
if(this.head) return this.head
return null
}
public getTail(){
if(this.tail) return this.tail
return null
}
public fromArray(values:Array<T>){
values.forEach(element => this.append(element));
return this
}
public toArray(){
const valuesList:LLNode<T>[]=[]
let curNode = this.head
while(curNode){
valuesList.push(curNode)
curNode=curNode.next
}
return valuesList
}
public toString(callback:(value:T)=> string){
return this.toArray().map((m)=>m.toString(callback)).toString()
}
public reverse(){
let curNode = this.head;
let prevNode:null | LLNode<T> = null;
let nextNode:null | LLNode<T> = null;
while(curNode){
nextNode = curNode.next
curNode.next = prevNode
prevNode = curNode
curNode = nextNode
}
this.tail=this.head;
this.head = prevNode
return this
}
public clear(){
this.head=null
this.tail=null
this.length=0
return this
}
}