Skip to content
Snippets Groups Projects
Commit d4b0ee7f authored by atm2g19's avatar atm2g19
Browse files

Updated and fixed sorting algorithms

parent 3a292f2b
No related branches found
No related tags found
No related merge requests found
Showing
with 290 additions and 22 deletions
......@@ -3,6 +3,10 @@ class Algorithm {
constructor(arr) {
this.elems = arr;
}
sort() {
while (!this.getComplete())
this.sortIteration();
}
}
let Algorithms = [];
//# sourceMappingURL=algo.js.map
\ No newline at end of file
......@@ -4,8 +4,6 @@ class BubbleSort extends Algorithm {
this.noIters = 0;
this.position = 0;
}
sort() {
}
sortIteration() {
let a = this.elems.get(this.position);
let b = this.elems.get(this.position + 1);
......@@ -16,14 +14,15 @@ class BubbleSort extends Algorithm {
}
this.position++;
// console.log(this.position, this.noIters)
if (this.position >= (this.elems.length - this.noIters)) {
if (this.position >= (this.elems.length - this.noIters - 1)) {
this.noIters++;
this.position = 0;
}
}
getComplete() {
return this.noIters >= this.elems.length;
return this.noIters >= (this.elems.length - 1);
}
setOpt(key, val) { }
}
Algorithms.push({
name: "bubble",
......
......@@ -4,8 +4,6 @@ class CocktailShakerSort extends Algorithm {
this.noIters = 0;
this.position = 0;
}
sort() {
}
sortIteration() {
let a = this.elems.get(this.position);
let b = this.elems.get(this.position + 1);
......@@ -18,7 +16,7 @@ class CocktailShakerSort extends Algorithm {
else
this.position--;
// console.log(this.position, this.noIters)
if ((this.position >= (this.elems.length - Math.ceil(this.noIters / 2))) || (this.position < (Math.floor(this.noIters / 2)))) {
if ((this.position >= (this.elems.length - Math.ceil(this.noIters / 2) - 1)) || (this.position < (Math.floor(this.noIters / 2)))) {
this.noIters++;
if (this.noIters % 2 == 0)
this.position++;
......@@ -29,6 +27,7 @@ class CocktailShakerSort extends Algorithm {
getComplete() {
return this.noIters >= this.elems.length;
}
setOpt(key, val) { }
}
Algorithms.push({
name: "cocktailshaker",
......
......@@ -3,8 +3,6 @@ class FisherYates extends Algorithm {
super(...arguments);
this.shuffle_pos = 0;
}
sort() {
}
sortIteration() {
if (this.getComplete())
return;
......@@ -17,5 +15,6 @@ class FisherYates extends Algorithm {
return true;
return false;
}
setOpt(key, val) { }
}
//# sourceMappingURL=fisher-yates.js.map
\ No newline at end of file
var HeapSortState;
(function (HeapSortState) {
HeapSortState[HeapSortState["START"] = 0] = "START";
HeapSortState[HeapSortState["HEAPIFY"] = 1] = "HEAPIFY";
HeapSortState[HeapSortState["SORT"] = 2] = "SORT";
})(HeapSortState || (HeapSortState = {}));
class HeapSort extends Algorithm {
constructor() {
super(...arguments);
this.state = HeapSortState.START;
}
sortIteration() {
if (this.state == HeapSortState.START) {
this.heapSize = this.elems.length;
//0 -> 1,2
//1 -> 3,4
//2 -> 5,6
//n -> 2n+1,2n+2
this.pos = Math.floor((this.heapSize - 1) / 2);
this.filterPos = this.pos;
this.state = HeapSortState.HEAPIFY;
}
else if (this.state == HeapSortState.HEAPIFY) {
if (!this.filterDownIteration()) {
this.pos--;
this.filterPos = this.pos;
if (this.pos < 0) {
this.state = HeapSortState.SORT;
console.log("Heap created");
this.pos = 0;
this.filterPos = this.pos;
this.verifyMaxHeap();
}
}
}
else if (this.state == HeapSortState.SORT) {
// this.heapSize = 0;
// return;
if (this.filterPos == -1) {
this.elems.swap(0, this.heapSize - 1);
this.heapSize--;
this.filterPos = 0;
}
else if (!this.filterDownIteration()) {
this.filterPos = -1;
}
// this.state = HeapSortState.
// this.heapSize = 0;
}
}
filterDownIteration() {
let filtered = false;
let fp = this.filterPos;
if (this.filterPos < 0 || this.filterPos >= this.heapSize) {
debugger;
return;
}
let parent = this.elems.get(this.filterPos);
let childIdx = this.filterPos * 2 + 1;
let c1, c2;
if (childIdx < this.heapSize)
c1 = this.elems.get(childIdx);
if ((childIdx + 1) < this.heapSize)
c2 = this.elems.get(childIdx + 1);
let greaterIdx, greater;
if (c1 != undefined) {
greaterIdx = childIdx;
greater = c1;
if (c2 != undefined && c2 > c1) {
greaterIdx++;
greater = c2;
}
}
if (greaterIdx && greater > parent) {
//swap
this.elems.swap(this.filterPos, greaterIdx);
//now filter child
this.filterPos = greaterIdx;
filtered = true;
}
//check
let a = this.elems.getArr();
if (((fp * 2 + 1) < this.heapSize && a[fp] < a[fp * 2 + 1]) || ((fp * 2 + 2) < this.heapSize && a[fp] < a[fp * 2 + 2])) {
console.error(`INVALID HEAP index ${fp} : ${a[fp]} => ${a[fp * 2 + 1]}, ${a[fp * 2 + 2]}`);
console.log({
parent,
c1,
c2,
greater,
greaterIdx
});
debugger;
}
return filtered;
}
getComplete() {
return this.heapSize <= 0;
}
verifyMaxHeap() {
let a = this.elems.getArr();
for (let i = 0; i < this.heapSize; i++) {
let p = a[i];
let childIdx = i * 2 + 1;
let c1, c2;
c1 = a[childIdx];
c2 = a[childIdx + 1];
if (c1 > p && c2 > p) {
console.error(`INVALID HEAP index ${i} : ${p} => ${c1}, ${c2}`);
debugger;
}
}
}
setOpt(key, val) { }
}
Algorithms.push({
name: "heapsort",
constructor: HeapSort,
});
//# sourceMappingURL=heap-sort.js.map
\ No newline at end of file
......@@ -5,14 +5,21 @@ var QuickSortState;
QuickSortState[QuickSortState["FILTER"] = 2] = "FILTER";
QuickSortState[QuickSortState["SOLVED"] = 3] = "SOLVED";
})(QuickSortState || (QuickSortState = {}));
var QuickSortPivot;
(function (QuickSortPivot) {
QuickSortPivot[QuickSortPivot["LOW"] = 0] = "LOW";
QuickSortPivot[QuickSortPivot["MIDDLE"] = 1] = "MIDDLE";
QuickSortPivot[QuickSortPivot["HIGH"] = 2] = "HIGH";
QuickSortPivot[QuickSortPivot["RANDOM"] = 3] = "RANDOM";
QuickSortPivot[QuickSortPivot["LMH_MEAN"] = 4] = "LMH_MEAN";
})(QuickSortPivot || (QuickSortPivot = {}));
class QuickSort extends Algorithm {
constructor() {
super(...arguments);
this.state = 0;
this.pivotType = 0;
this.bt = [];
}
sort() {
}
sortIteration() {
if (this.state == QuickSortState.START) {
this.hi = this.elems.length - 1;
......@@ -20,7 +27,33 @@ class QuickSort extends Algorithm {
this.state = QuickSortState.GETPIVOT;
}
if (this.state == QuickSortState.GETPIVOT) {
this.pivot = this.elems.get(this.lo); //could be any value really
switch (this.pivotType) {
case QuickSortPivot.LOW:
this.pivotIdx = this.lo + 1;
this.pivot = this.elems.get(this.pivotIdx);
break;
case QuickSortPivot.MIDDLE:
// this.pivot = this.elems.get(this.lo) + this.elems.get(this.hi);
// this.pivot /= 2;
this.pivotIdx = Math.floor((this.lo + this.hi) / 2);
this.pivot = this.elems.get(this.pivotIdx);
break;
case QuickSortPivot.HIGH:
this.pivotIdx = this.hi;
this.pivot = this.elems.get(this.pivotIdx);
break;
case QuickSortPivot.RANDOM:
// this.pivot = this.elems.get(Math.floor(Math.random() * (this.hi - this.lo)));
// this.pivot += this.elems.get(Math.floor(Math.random() * (this.hi - this.lo)));
// this.pivot /= 2;
this.pivotIdx = Math.floor(Math.random() * (this.hi - this.lo)) + this.lo;
this.pivot = this.elems.get(this.pivotIdx);
break;
case QuickSortPivot.LMH_MEAN:
this.pivot = this.elems.get(this.lo) + 1 + this.elems.get(this.hi) + this.elems.get(Math.round((this.lo + this.hi) / 2)); //could be any value really
this.pivot /= 3;
break;
}
this.anchor = this.lo;
this.insert = this.hi;
this.state = QuickSortState.FILTER;
......@@ -55,9 +88,23 @@ class QuickSort extends Algorithm {
getComplete() {
return this.state == QuickSortState.SOLVED;
}
setOpt(key, val) {
if (key == "pivotmode") {
this.pivotType = val;
}
}
}
Algorithms.push({
name: "quicksort",
constructor: QuickSort
constructor: QuickSort,
opts: {
"pivotmode": [
["first", QuickSortPivot.LOW],
["middle", QuickSortPivot.MIDDLE],
["last", QuickSortPivot.HIGH],
["random", QuickSortPivot.RANDOM],
["average", QuickSortPivot.LMH_MEAN]
]
}
});
//# sourceMappingURL=quick-sort.js.map
\ No newline at end of file
......@@ -33,6 +33,9 @@
<li>
<a href="sorter.html?algo=quicksort">Quick Sort</a>
</li>
<li>
<a href="sorter.html?algo=heapsort">Heap Sort</a>
</li>
</ul>
</div>
......
/// <reference path="../../../p5.global-mode.d.ts" />
/// <reference path="./visualiser.ts" />
/// <reference path="./algo.ts" />
let Bar;
let sBar;
let Arr;
let Algo;
let AlgoName;
let Vis;
let visSelect;
let algoSelect;
let sOpts;
let sReset;
let sAccessors;
let sWrites;
let params;
......@@ -25,51 +29,95 @@ function setup() {
speed = parseFloat(params["speed"]);
else
speed = 1;
//@ts-ignore
Bar = createDiv();
Bar.id("bar");
//@ts-ignore
sBar = createSpan();
sBar.parent(Bar);
visSelect = createSelect(false);
visSelect.parent(sBar);
for (let v of Visualisers) {
//@ts-ignore
visSelect.option(v.name);
}
//@ts-ignore
let ShuffleButton = createButton("Shuffle");
ShuffleButton.parent(sBar);
ShuffleButton.mouseClicked(() => {
Algo = new FisherYates(Arr);
AlgoName = "shuffle";
// shuffled = false;
sorting = true;
});
ShuffleButton.doubleClicked(() => {
if (Algo)
Algo.sort();
});
algoSelect = createSelect(false);
algoSelect.parent(sBar);
for (let a of Algorithms) {
//@ts-ignore
algoSelect.option(a.name);
}
algoSelect.value(params["algo"]);
algoSelect.input(createOptSels);
//@ts-ignore
let SortButton = createButton("Sort");
SortButton.parent(sBar);
SortButton.mouseClicked(() => {
if (shuffled && !sorting) {
sorting = true;
if (algoSelect.elt.value) {
let AlgoCon = Algorithms.reduce((a, c) => c.name == algoSelect.elt.value ? c : a, null).constructor;
let A = Algorithms.reduce((a, c) => c.name == algoSelect.elt.value ? c : a, null);
let AlgoCon = A.constructor;
if (AlgoCon) {
Algo = new AlgoCon(Arr);
AlgoName = algoSelect.elt.value;
//set opts
let opts = document.getElementsByClassName("sort_opt");
for (let elem of opts) {
let id = elem.id.split(':')[1];
//@ts-ignore
Algo.setOpt(id, A.opts[id].reduce((a, c) => c[0] == elem.value ? c[1] : a, -1));
}
}
}
// else
// if (params["algo"]) {
// let AlgoCon: AlgorithmConstructor = Algorithms.reduce((a, c) => c.name == params["algo"] ? c : a, null).constructor;
// if (AlgoCon) {
// Algo = new AlgoCon(Arr);
// AlgoName = params["algo"];
// }
// }
}
});
SortButton.doubleClicked(() => {
if (Algo)
Algo.sort();
});
//@ts-ignore
sAccessors = createSpan();
sAccessors.parent(Bar);
//@ts-ignore
sWrites = createSpan();
sWrites.parent(Bar);
//@ts-ignore
sOpts = createSpan();
sOpts.parent(Bar);
sOpts.style("margin-left", "10px");
//@ts-ignore
sReset = createSpan();
sReset.parent(Bar);
sReset.style("position", "relative");
sReset.style("float", "right");
//@ts-ignore
let resetButton = createButton("Reset.");
resetButton.parent(sReset);
resetButton.mouseClicked(() => {
Algo = null;
if (params["count"])
Arr = new WatchedArray(parseInt(params["count"]));
else
Arr = new WatchedArray(100);
});
// resetButton.style("position", "absolute");
// resetButton.style("right", "0");
// resetButton.style("position", "absolute");
createOptSels();
createCanvas(windowWidth - 40, 700);
}
function draw() {
......@@ -101,4 +149,31 @@ function draw() {
function windowResized() {
resizeCanvas(windowWidth - 30, height);
}
function createOptSels() {
let old_opts = document.getElementsByClassName("sort_opt");
while (old_opts.length)
old_opts[0].remove();
//create new opts
let algoOpts = Algorithms.reduce((a, c) => c.name == algoSelect.elt.value ? c : a, null).opts;
if (algoOpts) {
for (let opt_key in algoOpts) {
let optSel = createSelect(false);
optSel.parent(sOpts);
optSel.addClass("sort_opt");
optSel.id(`sort_opt:${opt_key}`);
for (let opt of algoOpts[opt_key]) {
//@ts-ignore
optSel.option(opt[0]);
}
optSel.input(() => {
if (Algo) {
Algo.setOpt(opt_key, algoOpts[opt_key].reduce((a, c) => c[0] == optSel.value() ? c[1] : a, -1));
}
});
}
}
}
// new p5(null, document.getElementById("sorter"));
//@ts-ignore
new p5(null, "sorter");
//# sourceMappingURL=main.js.map
\ No newline at end of file
......@@ -14,11 +14,13 @@
<script src="./visualisers/standard.js"></script>
<script src="./visualisers/spiral.js"></script>
<script src="./visualisers/pie.js"></script>
<script src="./visualisers/scatter.js"></script>
<script src="./algorithms/fisher-yates.js"></script>
<script src="./algorithms/bubble-sort.js"></script>
<script src="./algorithms/cocktail-shaker-sort.js"></script>
<script src="./algorithms/quick-sort.js"></script>
<script src="./algorithms/heap-sort.js"></script>
</head>
......
Visualisers.push({
name: "scatter",
fxn: (arr, c) => {
c.background(180, 180, 180);
c.push();
c.noStroke();
c.colorMode(HSB);
let a = arr.getArr();
translate(0, height);
for (let i = 0; i < a.length; i++) {
let pScale = a[i] / a.length;
let col = c.color(pScale * 360, 100, 100);
c.stroke(col);
c.strokeWeight(10);
c.point(c.width / a.length, -c.height * pScale);
c.translate(c.width / a.length, 0);
}
c.pop();
}
});
//# sourceMappingURL=scatter.js.map
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment