I am trying to implement heapsort in Javascript, but there is a undefined element at array.length - 2 and the element at index 0 is unsorted.
Here is the code:
var heapSort = function(array) {
var swap = function(array, firstIndex, secondIndex) {
var temp = array[firstIndex];
array[firstIndex] = array[secondIndex];
array[secondIndex] = temp;
};
var maxHeap = function(array, i) {
var l = 2 * i;
var r = l + 1;
var largest;
if (l <= array.heapSize && array[l] > array[i]) {
largest = l;
} else {
largest = i;
}
if (r <= array.heapSize && array[r] > array[largest]) {
largest = r;
}
if (largest != i) {
swap(array, i, largest);
maxHeap(array, largest);
}
};
var buildHeap = function(array) {
array.heapSize = array.length;
for (var i = Math.floor(array.length / 2); i >= 1; i--) {
maxHeap(array, i);
}
};
buildHeap(array);
for (var i = array.length; i >= 2; i--) {
swap(array, 1, i);
array.heapSize--;
maxHeap(array, 1);
}
};
var a = [55, 67, 10, 34, 25, 523, 1, -2];
heapSort(a);
document.getElementById("getHeapSort").innerHTML = a;
* {
font-family: Arial, sans-serif;
}
<p id="getHeapSort"></p>
I figured that array[i] == undefined when i = array.length. I tried fixing this (setting i = array.length - 1), but the array came out in an entirely different order. I also figured that 0 was never swapped because i is always greater than 0. Again, I tried, and the array came out in a entirely different order.
You were using 1-based indexing instead of 0-based indexing in JavaScript. I also added a trace for your convenience.
Try this:
var heapSort = function(array) {
var swap = function(array, firstIndex, secondIndex) {
var temp = array[firstIndex];
array[firstIndex] = array[secondIndex];
array[secondIndex] = temp;
};
var maxHeap = function(array, i) {
var l = 2 * i;
var r = l + 1;
var largest;
if (l < array.heapSize && array[l] > array[i]) {
largest = l;
} else {
largest = i;
}
if (r < array.heapSize && array[r] > array[largest]) {
largest = r;
}
if (largest != i) {
swap(array, i, largest);
maxHeap(array, largest);
}
};
var buildHeap = function(array) {
array.heapSize = array.length;
for (var i = Math.floor(array.length / 2); i >= 0; i--) {
maxHeap(array, i);
}
};
buildHeap(array);
for (var i = array.length-1; i >= 1; i--) {
swap(array, 0, i);
array.heapSize--;
maxHeap(array, 0);
document.getElementById("getHeapSort").innerHTML = document.getElementById("getHeapSort").innerHTML + a + "<br>";
}
};
var a = [55, 67, 10, 34, 25, 523, 1, -2];
document.getElementById("getHeapSort").innerHTML = a + "<br>";
heapSort(a);
Here is a JFiddle: http://jsfiddle.net/mbL5enL5/1/
Related
I am writing a program to calculate euclidean distance and then display the lines based, with the below code:
function discreteFrechet(X, Y) {
var M = X.length;
var N = Y.length;
var S = [
[],
[]
];
var backpointers = [
[],
[]
];
var backpaths = [];
var idx;
var path = [];
var paths;
var back = [
[],
[]
];
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
S[i][j] = 0;
backpointers[i][j] = 0;
}
} /* populates S array */
/*sanity check*/
S[0, 0] = euclidian(X, Y, 0, 0);
opt1 = [-1, 0];
opt2 = [0, -1];
opt3 = [-1, -1];
backpaths.push(opt1);
backpaths.push(opt2);
backpaths.push(opt3);
/*backpaths populated*/
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++) {
options = [];
if (i != 0 || j != 0) {
if (i > 0) {
options[0] = S[i - 1, j];
}
if (j > 0) {
options[1] = S[i - 1, j];
}
if (i > 0 && j > 0) {
options[2] = S[i - 1, j];
}
idx = Math.min(options);
backpointers[i][j] = idx;
S[i][j] = Math.max(options[idx], euclidian(X, Y, i, j));
}
}
}
console.log(S);
paths = [
[M - 1, N - 1]
];
path = [
[],
[]
];
path.push(paths);
//Create "path"
i = M - 1;
j = N - 1;
count = 0;
while ((path[path.length - 1][0] != 0) || (path[0][path[1].length - 1] != 0)) {
back[0][1] = backpaths[backpointers[i], [j]];
i += back[0];
j += back[1];
path.push([i, j]);
if (count > 1000) {
console.log("too many loops");
break;
}
count += 1;
}
path.push([0, 0]);
path.reverse();
//returns bottleneck and the path
}
As I am testing, I am running into a problem with an infinite while loop (hence the break statement) any help or suggestions would be greatly appreciated! The goal is to append indicies into the path element, such that I can then take those path indicies and the bottleneck and use them to plot with d3.
I am trying to debug one online coding platform problem. The problem I am facing is to return element occurring most often in array. I am interested in correcting my current code than trying other methods.
function findMostOccured(M, A) { //value of elements in A should not be greater than M
var N = A.length;
var count = new Array(M + 1);
var i;
for (i = 0; i <= M; i++)
count[i] = 0;
var maxOccurence = 1;
var index = -1;
for (i = 0; i < N; i++) {
if (count[A[i]] > 0) {
var tmp = count[A[i]];
if (tmp > maxOccurence) {
maxOccurence = tmp;
index = i;
}
count[A[i]] = tmp + 1;
} else {
count[A[i]] = 1;
}
}
return A[index];
}
Given M = 3 and A = [1, 2, 3, 3, 1, 3, 1]. It should return 3 or 1.
var arr = [1, 2, 3, 3, 1, 3, 1];
var M = 3;
function findMostOccured(M, arr) {
var obj = {};
var result = [];
for (let i = 0; i < arr.length; i++) {
if (obj[arr[i]]) {
obj[arr[i]] = obj[arr[i]] + 1;
} else {
obj[arr[i]] = 1;
}
}
for (var key in obj) {
if (obj[key] === M) {
result.push(parseInt(key));
}
}
return result;
}
console.log(findMostOccured(3, arr));
So... If I input:
4 1 5 3
INSTEAD OF 1,3,4,5
I GET [ 4, 1, 5, 3 ]
Following is the code for merge sort but for the last comparison the program doesn't fetch updated (1,4) (3,5) value rather (4,1) (5,3) thus giving the wrong result.
var a = [4, 1, 5, 3];
q(a);
function q(a) {
var start = 0;
var n = a.length;
var length = parseInt(n / 2);
if (n < 2) {
return n;
}
var l = [], r = [];
for (i = 0; i < length; i++) {
l[i] = a[i]; //left array
}
for (i = 0, j = length; j < n; i++ , j++) {
r[i] = a[j]; //right array
}
q(l); //merge sort left array
q(r); //merge sort right array
comp(l, r);
}
function comp(l, r) {
var k = [], m = 0, i = 0, j = 0;
while (i < ((l.length)) && j < ((r.length))) {
if (l[i] < r[j]) {
k[m] = l[i];
i++;
m++
}
else {
k[m] = r[j];
j++;
m++
}
}
while (i != (l.length)) {
k[m] = l[i];
m++;
i++;
}
while (j != (r.length)) {
k[m] = r[j];
m++;
j++;
}
console.log(k); //for final output it is [ 4, 1, 5, 3 ] instead of [1,3,4,5]
}
You have a couple small problems. The main one is that you are returning the wrong thing from your edge condition:
if (n < 2) {
return n; // n is just a length; doesn't make sense to return it.
}
n is the length, you really want to return the small array here:
if (n < 2) {
return a; // return the array instead
}
Also, you need to pass the result of the recursive call to your comp function. Right now you're just returning the original lists with:
comp(l, r)
Something like this would work better:
let l_sort = q(l); //merge sort left array
let r_sort = q(r); //merge sort right array
return comp(l_sort, r_sort); // merge the arrays when recursion unwinds.
And you need to return things for recursion to work.
Put all together:
function q(a) {
var start = 0;
var n = a.length;
var length = parseInt(n / 2);
if (n < 2) {
return a;
}
var l = [],
r = [];
for (i = 0; i < length; i++) {
l[i] = a[i]; //left array
}
for (i = 0, j = length; j < n; i++, j++) {
r[i] = a[j]; //right array
}
let l_sort = q(l); //merge sort left array
let r_sort = q(r); //merge sort right array
return comp(l_sort, r_sort);
}
function comp(l, r) {
var k = [],
m = 0,
i = 0,
j = 0;
while (i < ((l.length)) && j < ((r.length))) {
if (l[i] < r[j]) {
k[m] = l[i];
i++;
m++
} else {
k[m] = r[j];
j++;
m++
}
}
while (i != (l.length)) {
k[m] = l[i];
m++;
i++;
}
while (j != (r.length)) {
k[m] = r[j];
m++;
j++;
}
return k
}
console.log(q([4, 1, 5, 3]).join(','));
console.log(q([5, 4, 3, 2, 1]).join(','));
console.log(q([2, 3]).join(','));
console.log(q([3, 2]).join(','));
console.log(q([1]).join(','));
I am currently working on my investigation for my Extended Essay. I am testing the comparison between the merge and quick sorting algorithms. I am having this weird anomaly with my results. Every first sort in my second for loop return a much higher time taken than the rest. I have no clue why, could someone maybe explain?
For some reason, JSFiddle will not output anything, though when I run it locally it works fine. So, I'll just post the code here:
function generateRandomArray(l, min, max) {
var a = [];
for (var i = 0; i < l; i++) {
a.push(Math.ceil(Math.random() * max + min - 1));
}
return a;
}
function quickSort(a) {
var less = [],
pivotList = [],
greater = [];
if (a.length <= 1) return a;
var pivot = a[0];
for (var i = 0; i < a.length; i++) {
if (a[i] < pivot) less.push(a[i]);
else if (a[i] > pivot) greater.push(a[i]);
else pivotList.push(a[i]);
}
less = quickSort(less);
greater = quickSort(greater);
return less.concat(pivotList, greater);
}
function mergeSort(left, right) {
if (!left) return right;
if (!right) return left;
var result = [],
leftIndex = 0,
rightIndex = 0;
while (leftIndex < left.length & rightIndex < right.length) {
if (left[leftIndex] <= right[rightIndex]) {
result.push(left[leftIndex]);
leftIndex++;
} else {
result.push(right[rightIndex]);
rightIndex++;
}
}
if (leftIndex != left.length) {
var temp = left.slice(leftIndex, left.length);
result = result.concat(temp);
} else if (rightIndex != right.length) {
var temp = right.slice(rightIndex, right.length);
result = result.concat(temp);
}
return result;
}
function mergeSortSplit(a) {
if (a.length <= 1) return a;
var middle = Math.floor(a.length / 2);
var left = a.slice(0, middle),
right = a.slice(middle, a.length);
left = mergeSortSplit(left);
right = mergeSortSplit(right);
return mergeSort(left, right);
}
window.onload = function() {
var timeResults = [
[[], [], [], [], []],
[[], [], [], [], []]
];
for (var i = 0; i < 10; i++) {
for (var j = 3; j < 6; j++) {
var array = generateRandomArray(Math.pow(10, j), 1, 100);
var mergeSortTime = window.performance.now();
mergeSortSplit(array);
timeResults[0][j - 3].push(window.performance.now() - mergeSortTime);
var quickSortTime = window.performance.now();
quickSort(array);
timeResults[1][j - 3].push(window.performance.now() - quickSortTime);
}
}
for (var i = 0; i < timeResults.length; i++) {
document.getElementById("demo").innerHTML += "<b>" + (i + 1) + ". </b><br>";
for (var j = 0; j < timeResults[i].length; j++) {
document.getElementById("demo").innerHTML += "<b>" + Math.pow(10, j + 3) + ": </b>";
for (k = 0; k < timeResults[i][j].length; k++) {
document.getElementById("demo").innerHTML += timeResults[i][j][k] + "<b> | </b>";
}
document.getElementById("demo").innerHTML += "<br><br>";
}
document.getElementById("demo").innerHTML += "<br><br><br>";
}
console.log(timeResults);
}
<html>
<head>
<meta charset="utf-8">
<title>EE Investigation</title>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<p id="demo"></p>
</body>
</html>
I wrote code in JavaScript but issues with start value ex: ?-9, ?-87...etc
Input: {88, 105, 3, 2, 200, 0, 10}
<script type="text/javascript">
function RangeValues(){
var a = [88, 105, 3, 2, 200, 0, 10];
var n = a.length;
var pq = [];
for(var i = 0; i<n; i++) {
if(a[i] >= 0 && a[i] <= 99)
pq.push(a[i]);
}
var start = 0;
if(!Array.prototype.last) {
Array.prototype.last = function() {
return this[this.length - 1];
}
}
while(pq.length != 0)
{
var num = pq.last();
pq.pop();
if(num - start > 1){
console.log( (start) +','+ (num-1));
}
if((num - start) == 1)
{
start = num + 1;
console.log(start);
}
}
if(start == 99){
console.log('99');
}
else if(start < 100) {
console.log(start+' to '+99);
}
return 0;
}
RangeValues();
</script>
actual output: 0-9,0-1,0-2,0-87,0-99
Expected: 1,4-9,11-87,89-99
First, you should sort number in array pq descending so the last value is the min number. Try with below solution:
function RangeValues(){
var a = [88, 105, 3, 2, 200, 0, 10];
//var a = [12, 105, 23, 1, 200, 4, 21];
var n = a.length;
var pq = [];
for(var i = 0; i<n; i++) {
if(a[i] >= 0 && a[i] <= 99){
pq.push(a[i]);
}
}
// sort array descending
pq.sort(function(a, b){return b-a});
var start = 0;
if(!Array.prototype.last) {
Array.prototype.last = function() {
return this[this.length - 1];
}
}
while(pq.length != 0){
var num = pq.last();
pq.pop();
if (num-start == 2 || num == 1){
console.log(num-1);
} else if((num - start)>2){
var from = start + 1;
var end = num - 1;
console.log(from+" - "+end);
}
start = num;
}
if (start < 98){
var from = start + 1;
console.log(from+" - "+99);
} else if( start == 98){
console.log(start+1);
}
return 0;
}
RangeValues();