Created
February 17, 2020 22:23
-
-
Save RP-3/b2e8fac98de0a0c74d27e55bdae44b84 to your computer and use it in GitHub Desktop.
O(1) Queue in Javascript.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Queue = function(){ | |
this.storage = new Array(10); | |
this.start = -1; // index of first element in array | |
this.end = -1; // index of last element in array | |
}; | |
Queue.prototype.size = function(){ | |
if(this.start === -1) return 0; | |
if(this.start < this.end) return this.end - this.start + 1; | |
if(this.start === this.end) return 1; | |
return (this.storage.length - this.start) + this.end + 1; | |
} | |
Queue.prototype.peakLeft = function(){ | |
return this.size() === 0 ? null : this.storage[this.start]; | |
} | |
Queue.prototype.peakRight = function(){ | |
return this.size() === 0 ? null : this.storage[this.end]; | |
} | |
Queue.prototype.popLeft = function(){ | |
if(this.size() === 0) return null; | |
let tmp; // return val | |
// one element left | |
if(this.start === this.end){ | |
tmp = this.storage[this.start]; | |
this.start = -1; | |
this.end = -1; | |
} | |
// start is at final index | |
else if(this.start ===(this.storage.length -1)){ | |
tmp = this.storage[this.start]; | |
this.start = 0; | |
} | |
// start and end are different | |
else { | |
tmp = this.storage[this.start]; | |
this.start++; | |
} | |
if((this.storage.length > 10) && this.storage.length > (this.size() * 4)){ | |
this.resize(false); | |
} | |
return tmp; | |
} | |
Queue.prototype.resize = function(upsize=true){ | |
const newSize = upsize ? (this.storage.length * 2) : Math.max(10, Math.floor(this.storage.length / 2)); | |
const newStorage = new Array(newSize); | |
let lastElementAt = -1; | |
if(this.start < this.end){ | |
for(let i=this.start; i<=this.end; i++){ | |
newStorage[++lastElementAt] = this.storage[i]; | |
} | |
} else { | |
for(let i=this.start; i<this.storage.length; i++){ | |
newStorage[++lastElementAt] = this.storage[i]; | |
} | |
for(let i=0; i<=this.end; i++){ | |
newStorage[++lastElementAt] = this.storage[i]; | |
} | |
} | |
this.storage = newStorage; | |
this.start = 0; | |
this.end = lastElementAt; | |
return this.size(); | |
} | |
Queue.prototype.pushRight = function(val){ | |
// empty storage | |
if(this.start === -1) { | |
this.storage[0] = val; | |
this.start = 0; | |
this.end = 0; | |
return this.size(); | |
} | |
// start ---- end | |
if(this.end > this.start){ | |
// if we've run out of space | |
if((this.end + 1) === this.storage.length){ | |
// but have room to wrap around | |
if(this.start > 0){ | |
// wrap around | |
this.storage[0] = val; | |
this.end = 0; | |
return this.size(); | |
}else{ | |
// no room to wrap around. Resize | |
this.resize(true); | |
this.pushRight(val); | |
return this.size(); | |
} | |
} else { | |
// not run out of space | |
this.storage[++this.end] = val; | |
return this.size(); | |
} | |
} | |
// end --- start | |
else if(this.end < this.start){ | |
// there's space between the pointers | |
if((this.start - this.end) > 1){ | |
this.storage[++this.end] = val; | |
return this.size(); | |
}else{ | |
this.resize(true); | |
this.pushRight(val); | |
return this.size(); | |
} | |
} | |
// end === start | |
else { | |
// there's space after end | |
if((this.end + 1) < this.storage.length){ | |
this.storage[++this.end] = val; | |
return this.size(); | |
} | |
// there's space before start | |
else if(this.start > 0){ | |
this.storage[--this.start] = val; | |
return this.size(); | |
} | |
throw new Error('Invariant violation: End and start cannot be equal and have no space on either side'); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment