Shortest path in a graph in ES6 - javascript

This is my implementation of a graph, to get the shortest path between A and B.
class Queue {
constructor() {
this.head = null;
this.tail = null;
this.size = 0;
}
offer(item) {
const p = new QueueNode(item);
this.size++;
if (this.head === null) {
this.head = p;
this.tail = p;
return;
}
this.tail.next = p;
this.tail = p;
}
poll() {
if (this.size === 0) {
throw TypeError("Can't deque off an empty queue.");
}
this.size--;
const item = this.head;
this.head = this.head.next;
return item.val;
}
peek() {
if (this.size === 0) {
throw TypeError("Empty Queue.")
}
return this.head.val;
}
isEmpty() {
return this.head === null;
}
}
class QueueNode {
constructor(item) {
this.val = item;
this.next = null;
}
}
class Graph {
constructor(directed = false) {
this.numVertices = 0;
this.directed = directed;
this.dict = {}
}
addEdge(v1, v2, weight = 1) {
let p, q;
if (v1 in this.dict) {
p = this.dict[v1];
} else {
p = new GraphNode(v1);
this.dict[v1] = p;
this.numVertices++;
}
if (v2 in this.dict) {
q = this.dict[v2];
} else {
q = new GraphNode(v2);
this.dict[v2] = q;
this.numVertices++;
}
p.addEdge(q);
if (!this.directed) {
q.addEdge(p);
}
}
stringify() {
for (const [key, value] of Object.entries(this.dict)) {
console.log(`${key}: ${[...value.adjacencySet].map(x => x.data)}`);
}
}
buildDistanceTable(source) {
let p;
if (this.dict[source] === undefined) {
throw TypeError('Vertex not present in graph')
} else {
p = this.dict[source];
}
const distanceTable = {};
for (const [key, value] of Object.entries(this.dict)) {
distanceTable[key] = [-1, -1];
}
distanceTable[p.data] = [0, p.data];
const queue = new Queue();
queue.offer(p);
while (!queue.isEmpty()) {
let curr = queue.poll();
let curr_distance = distanceTable[curr.data][0];
curr.adjacencySet.forEach((item) => {
if (distanceTable[item.data] === -1) {
distanceTable[item.data] = [1 + curr_distance, curr.data];
console.log(distanceTable);
if (item.adjacencySet.length > 0) {
queue.offer(item);
}
}
})
}
return distanceTable;
}
shortestPath(source, destination) {
const distanceTable = this.buildDistanceTable(source);
const path = [destination];
let prev = distanceTable[destination][1];
while (prev !== -1 && prev !== source) {
path.unshift(prev);
prev = distanceTable[prev][1];
}
if (prev === null) {
console.log("There's no path from source to destination");
} else {
path.unshift(source);
path.map(item => {
console.log(item);
});
}
}
}
class GraphNode {
constructor(data) {
this.data = data;
this.adjacencySet = new Set();
}
addEdge(node) {
this.adjacencySet.add(node)
}
}
graph = new Graph(directed = false);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(2, 3);
graph.addEdge(1, 4);
graph.addEdge(3, 5);
graph.addEdge(5, 4);
graph.addEdge(3, 6);
graph.addEdge(6, 7);
graph.addEdge(0, 7);
graph.stringify();
graph.shortestPath(1, 7);
When I run this it give 1, 7 however that's not the shortest path. What am I doing wrong here.

You have 2 issue in your code (that sabotage the building of the distance table):
You missing index in: if (distanceTable[item.data] === -1) { -> each item in the distance table is of array therefor it need to be: if (distanceTable[item.data][0] === -1) {
Set size in node js checked with size and not length (as in documentation) therefor item.adjacencySet.length is always undefined so you need to change: if (item.adjacencySet.length> 0) { to if (item.adjacencySet.size > 0) {
After those 2 changes your code return me path of 1 -> 0 -> 7
Just small side issue: you missing some ; and "new" before throwing TypeError...

Related

How do I recursively reverse a linked list?

Input: 5 -> 9 -> 8 -> 3 -> 1 -> 7
Expected Output: 7 -> 1 -> 3 -> 8 -> 9 -> 5
Issue:
When I display the reversed linked list the result is 5. This is an issue because this should be the tail and not the head. The rest of the nodes are missing in the display well.
Question:
Is there an issue with the code base that is preventing the traversal from the head to the tail and changing the pointers to reverse the list?
Code:
LinkedList:
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
insertFirst(item) {
if (this.head !== null) {
const newHead = new _Node(item);
let oldHead = this.head;
oldHead.prev = newHead;
newHead.next = oldHead;
this.head = newHead;
} else {
this.head = new _Node(item, this.head);
}
this.size++;
}
insertLast(item) {
if (!this.head) {
this.insertFirst(item);
} else {
let tempNode = this.head;
while (tempNode.next !== null) {
tempNode = tempNode.next;
}
tempNode.next = new _Node(item, null, tempNode);
}
this.size++
}
}
module.exports = LinkedList;
Main:
const LinkedList = require("./LinkedLists");
const { reverse } = require("./Reverse");
const { display } = require("./Supplemental");
function main() {
let SLL = new LinkedList();
SLL.insertFirst(5);
SLL.insertLast(9);
SLL.insertLast(8);
SLL.insertLast(3);
SLL.insertLast(1);
SLL.insertLast(7);
reverse(SLL);
display(SLL);
return SLL;
}
console.log(main());
Reverse:
reverse = (SLL) => {
let curr = SLL.head
if (!curr) {
return;
}
if (!curr.next) {
SLL.head = curr;
return;
}
let tmp = reverse(curr.next);
curr.next.next = curr;
curr.next = null;
return tmp;
}
module.exports = { reverse };
Display:
display = (SLL) => {
let currentNode = SLL.head;
if (!SLL.head) {
return null;
}
while (currentNode !== null) {
console.log(currentNode.value);
currentNode = currentNode.next;
}
return;
};
Can someone tell me what return tmp is doing in the Reverse.js file?
(1) Removed display from Main.js
(2) Edited Main.js:
const LinkedList = require("./LinkedLists");
const { reverse } = require("./Reverse");
const { display } = require("./Supplemental");
function main() {
let SLL = new LinkedList();
SLL.insertFirst(5);
SLL.insertLast(9);
SLL.insertLast(8);
SLL.insertLast(3);
SLL.insertLast(1);
SLL.insertLast(7);
const result = reverse(SLL.head);
console.log(result);
return SLL;
}
return main();
(3) Edited Reverse.js:
reverse = (curr, prev = null) => {
if (!curr) {
return prev;
}
let tmp = reverse(curr.next, curr);
const temp = curr.next;
curr.next = prev;
curr.prev = temp;
return tmp;
}
module.exports = { reverse };

How to make binary tree from array in javascript?

I have an array var array = [8,10,12,5,3,6];
Logic
First node would be root node.
If new node value is less or equal =< than parent node, It would be left node of parent node
If new node value is greater > than parent node, It would be right node of parent node
And I am trying to achieve output like below object:
{
value:8,
left:{
value:5,
left:{ value:3 },
right:{value:6}
},
right:{
value:10,
right:{value:12}
}
}
Which would be in image like this
I tried below code:
var arr = [8,10,12,5,3,6];
var root = arr[0];
var rv = {};
for (var i = 0; i < arr.length; i++){
if(arr[i] < root){
rv.left = arr[i];
}else{
rv.right = arr[i];
}
}
console.log(rv);
Please help me to solve this.
You could use a Node instance for new nodes and a function for inserting nodes.
Then iterate the values and build a new tree.
function Node(value) {
this.value = value;
// this.left = null;
// this.right = null;
}
function insertNode(tree, value) {
var node = tree,
key;
while (node.value !== value) {
key = value < node.value ? 'left' : 'right';
if (!node[key]) {
node[key] = new Node(value);
break;
}
node = node[key];
}
return tree;
}
var array = [8, 10, 12, 5, 3, 6],
tree = array.reduce((t, v) => t ? insertNode(t, v) : new Node(v), null);
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
While it is close to Nina's answer i believe to be a little more concise;
var data = [8,10,12,5,3,6],
tree;
function insertBinTree (t = {value: void 0, left: void 0, right: void 0}, n){
t.value !== void 0 ? t.value > n ? t.left = insertBinTree(t.left,n)
: t.right = insertBinTree(t.right,n)
: t.value = n;
return t;
}
tree = data.reduce(insertBinTree, void 0);
console.log(tree);
.as-console-wrapper {
max-height: 100% !important
}
Try something like this by recursive method
var binary = {};
var arr = [8,5,10,3,6,12];
function makeBinary(binary,number){
if(binary.value === undefined){
binary.value = number;
}else if(number > binary.value){
if(binary.right === undefined){
binary.right = {value:number};
}else{
binary.right = makeBinary(binary.right,number);
}
}else{
if(binary.left === undefined){
binary.left = {value:number};
}else{
binary.left = makeBinary(binary.left,number);
}
}
return binary;
}
for(let i in arr){
makeBinary(binary,arr[i]);
}
console.log(binary);
class Node {
constructor(val){
this.val=val;
this.right=null;
this.left=null;
}
}
class Bst{
constructor(){
this.root=null;
}
insert(val){
let newNode= new Node (val)
if (!this.root) this.root=newNode;
let current =this.root;
while (true) {
if(val === current.val) return undefined;
if(current.val<val){
if (current.right===null){
current.right=newNode;
return this
}
else
current=current.right}
if(current.val>val){
if (current.left===null){
current.left=newNode;
return this
}
else
current=current.left}
}
}
print (){
let all="Root=";
let visit=(current=this.root)=>{
if(!current.left && !current.right){
if(all[all.length-1]<current.val)
all+=`,LeR${current.val}`
else
all+=`,LeL${current.val}`
}
else{
if(all[all.length-1]<current.val)
all+=`,FR${current.val}`
else
all+=`,FL${current.val}`
}
if (current.left) visit(current.left)
if (current.right) visit(current.right)
}
visit()
all+=` ,valid bst:${this.isValidBST()}`
return all
}
isValidBST(node=this.root, min = null, max = null) {
if (!node) return true;
if (max !== null && node.data >= max) {
return false;
}
if (min !== null && node.data <= min) {
return false;
}
const leftSide = this.isValidBST(node.left, min, node.data);
const rightSide = this.isValidBST(node.right, node.val, max);
return leftSide && rightSide;
}
find(val){
let found=false
let innerFind=(current=this.root)=>{
if (val>current.val)
if (current.right != null) return innerFind(current.right)
if(val===current.val)
found= true
else
if (current.left != null)return innerFind(current.left)
if(val===current.val)
found= true
return found
}
return innerFind()
}
}
let tree=new Bst
tree.insert(8)
tree.insert(10)
tree.insert(13)
tree.insert(3)
tree.insert(1)
tree.insert(6)
tree.insert(4)
tree.insert(7)
tree.insert(2)
tree.print()
You can do this by technique is called recursion.
make an array with the structure ( left_subtree, key, right_subtree)
in your case
var array = [[3,5,6],8,[null,10,12]
class TreeNode {
constructor(key) {
this.key = key;
this.right = null;
this.left = null;
}
}
function parseTuple(data) {
if (data === null) {
let node = null;
return node;
}
else if (data.length === 3) {
let node = new TreeNode(data[1]);
node.left = parseTuple(data[0]);
node.right = parseTuple(data[2]);
return node;
}
else {
let node = new TreeNode(data);
return node;
}
}

Binary search tree solution not working?

There's a binary search tree, where all nodes to the left are smaller, and all nodes to the right are greater.
I'm trying to create a function isPresent that will check if value is present in the BST. If yes, it returns 1. If no, it returns 0.
this.isPresent = function(root, val) {
if (val == root.data) {
return 1;
}
if (val < root.data) {
if (root.left) {
this.isPresent(root.left, val);
} else {
return 0;
}
} else {
if (root.right) {
this.isPresent(root.right, val);
} else {
return 0;
}
}
}
Entire code:
function Node(data) {
this.data = data;
this.left = null;
this.right = null;
};
function BinarySearchTree() {
this.insert = function(root, data) {
if (root === null) {
this.root = new Node(data);
return this.root;
}
if (data < root.data) {
if (root.left) {
this.insert(root.left, data);
} else {
root.left = new Node(data);
}
} else {
if (root.right) {
this.insert(root.right, data);
} else {
root.right = new Node(data);
}
}
return this.root;
}
this.isPresent = function(root, val) {
if (val == root.data) {
return 1;
}
if (val < root.data) {
if (root.left) {
this.isPresent(root.left, val);
} else {
return 0;
}
} else {
if (root.right) {
this.isPresent(root.right, val);
} else {
return 0;
}
}
}
}
How input is formatted:
process.stdin.resume();
process.stdin.setEncoding('ascii');
var _input = "";
process.stdin.on('data', function(data) {
_input += data;
});
process.stdin.on('end', function() {
var tree = new BinarySearchTree();
var root = null;
var values = _input.spit('\n').map(Number);
var j = 1;
for (var i = 0; i < values[0]; i++) {
root = tree.insert(root, values[j]);
j++;
}
var k = j + 1;
for (var i = 0; i < values[j]; i++) {
process.stdout.write(tree.isPresent(root, values[k]) + '\n');
k++;
}
})
Sample input:
11 <--- this line indicating next 11 lines are values to be inserted to BST
20
10
30
8
12
25
40
6
11
13
23
4 <--- this line indicated the next 4 lines to be tested whether they are present in BST
30
10
12
15

Display Binary Search Tree Traversal on Javascript (Recursive way)

I am trying to console every data in a binary tree. My main problem is that I want to implementing in a recursive way. Basically I have this code so far:
this.levelOrder = function (root) {
if (root.data != null) {
console.log(root.data);
if (root.left != null) {
this.levelOrder(root.left);
}
if (root.right != null) {
this.levelOrder(root.right)
}
} else {
return;
}
};
The output is 3 2 1 5 4 7
But It should be 3 2 5 1 4 7. So Basically I am accessing the first child of the node instead of printing all the children first.
Assuming a tree like this,
4
2 6
1 3 5 7
and an object literal
tree = {
data: 4,
left: {
data: 2,
left: {
data: 1,
left: null,
right: null
},
right: {
data: 3,
left: null,
right: null
}
},
right: {
data: 6,
left: {
data: 5,
left: null,
right: null
},
right: {
data: 7,
left: null,
right: null
}
}
};
you could call the function recursively and get first the left part and then the right part of the tree. The algorithm is called depth-first search.
This function uses a single check, because this is sufficient to check first and then to move on.
var depthFirst = function (node) {
if (node) {
console.log(node.data);
depthFirst(node.left);
depthFirst(node.right)
}
},
tree = { data: 4, left: { data: 2, left: { data: 1, left: null, right: null }, right: { data: 3, left: null, right: null } }, right: { data: 6, left: { data: 5, left: null, right: null }, right: { data: 7, left: null, right: null } } };
depthFirst(tree); // 4 2 1 3 6 5 7
For a breadth-first search, an algorithm which is iterating every level of the tree first, you could use this code with the same tree data as above.
var breadthFirst = function (node) {
function bf(queue) {
var newQueue = [];
queue.forEach(function (node) {
console.log(node.data);
node.left && newQueue.push(node.left);
node.right && newQueue.push(node.right);
});
newQueue.length && bf(newQueue);
}
bf([node]);
},
tree = { data: 4, left: { data: 2, left: { data: 1, left: null, right: null }, right: { data: 3, left: null, right: null } }, right: { data: 6, left: { data: 5, left: null, right: null }, right: { data: 7, left: null, right: null } } };
breadthFirst(tree); // 4 2 6 1 3 5 7
Assuming the Node definition is like this:
export default class Node {
constructor(data) {
this.data = data;
this.left = null;
this.right = null;
}
}
And the Tree definition is something like this:
import Node from './Node.js';
export default class BinarySearchTree {
constructor() {
this.root = null;
}
//methods such as search, traversal, insert, etc...
}
You can perform the traversals like this (preferably as methods of the BinarySearchTree) :
inorder(node) {
if (node !== null) {
this.inorder(node.left);
console.log(node.data);
this.inorder(node.right);
}
}
postorder(node) {
if (node !== null) {
this.postorder(node.left);
this.postorder(node.right);
console.log(node.data);
}
}
preorder(node) {
if (node !== null) {
console.log(node.data);
this.preorder(node.left);
this.preorder(node.right);
}
}
If you want to store the result of the traversal, you could pass down some object the methods would append the values to.
--
BONUS
If you want to display the whole tree in a somewhat pleasing manner, I'd suggest using some additional information stored in the nodes and in the state of your app.
First I'd add some additional info to each Node definition (x,y):
export default class Node {
constructor(data) {
this.data = data;
this.left = null;
this.right = null;
this.x = 0;
this.y = 0;
}
}
Then create an empty grid (matrix) based on the current tree data,
createMatrix = (minX, maxX, depth) => {
let displayMatrix = [];
for (let i = 0; i <= depth; i++) {
let line = [];
for (let j = 0; j <= maxX - minX; j++) {
line.push(' ');
}
displayMatrix.push(line);
}
return displayMatrix;
}
Where minX is the smallest X value among all nodes, and maxX is the largest (getting these values could happen while inserting the nodes into the tree, or by traversing the tree and comparing node properties), and then fill it with the node data and the "\", "/" characters between nodes:
fillMatrix(node, matrix, minX, side = "root") {
if(node !== null){
matrix[node.y][node.x + Math.abs(minX)] = node.data;
if(side === "left"){
matrix[node.y-1][node.x + Math.abs(minX)+1] = '/';
}
else if (side === "right"){
matrix[node.y - 1][node.x + Math.abs(minX) - 1] = '\\';
}
this.fillMatrix(node.left, matrix, minX, "left");
this.fillMatrix(node.right, matrix, minX, "right");
}
return matrix;
}
Then this result matrix would hold a " " where there are no 'lines' and no values, hold the numbers where the node.data are, and hold "/" or "\" as the lines between the nodes.
Then you can use this to display it on a canvas or in the console.
For example, here I created a table dynamically, and in every element there is a div, which is formatted differently based on what kind of character it holds:
/* |
h
/ \
d l
/ \ / \
b f j n
/ \ / \ / \ / \
a c e g i k m o
bt.insert("d");
bt.insert("l");
bt.insert("b");
bt.insert("f");
bt.insert("j");
bt.insert("n");
bt.insert("a");
bt.insert("c");
bt.insert("e");
bt.insert("g");
bt.insert("i");
bt.insert("k");
bt.insert("m");
bt.insert("o");
*/
function printTree(inorder, bredthOrder, size) {
size = size || 2;
const total = inorder.length;
const numberOfLevels = Math.ceil(Math.log2(total));
let pointerBOrder = 0;
let blank = " ";
for (let level = 0; level < numberOfLevels; level++) {
let itemPerLevel = Math.pow(2, level);
let out = [];
let branches = [];
let slantDirection = true;//up
for (let itemNumber = 0; itemNumber < itemPerLevel; itemNumber++) {
let item = bredthOrder[pointerBOrder++];
for (let x = 1; x <= inorder.length; x++) {
const ino = inorder[x - 1];
let nInd = size * (x - 1);
if (item == ino) {
out[nInd] = item;
if (item) {
if (bredthOrder[0] == item) {
branches[nInd] = "|";
} else if (slantDirection) {
branches[nInd + 1] = "/";
} else {
if (nInd - 1 >= 0) {
branches[nInd - 1] = "\\";
}
}
slantDirection = !slantDirection;
}
} else {
out[nInd] = out[nInd] || blank;
}
branches[nInd] = branches[nInd] || blank;
for (let fill = 1; fill <= size - 1; fill++) {
out[nInd + fill] = blank;
branches[nInd + fill] = branches[nInd + fill] || blank;
}
}
}
console.log(branches.join(''));
console.log(out.join(''));
out = [];
}
}
class Node {
constructor(value) {
this.left = null;
this.right = null;
this.value = value;
}
}
class BinaryTree {
constructor(value) {
this.root = value == null ? null : new Node(value);
}
insert(value, node) {
if (node == null) {
node = this.root;
}
if (node == null) {
node = new Node(value);
return;
}
if (node.value >= value) {
if (node.left == null) {
node.left = new Node(value);
return;
} else {
this.insert(value, node.left);
return;
}
} else {
if (node.right == null) {
node.right = new Node(value);
return;
} else {
this.insert(value, node.right);
return;
}
}
}
print(node, acc) {
if (node == null) {
return acc;
} else {
if (node.left != null) {
acc = this.print(node.left, acc);
}
acc.push(node.value);
if (node.right != null) {
acc = this.print(node.right, acc);
}
return acc;
}
}
printInOrder() {
return this.print(this.root, []);
}
getSiblings(node) {
if (node == null) {
return [];
}
let acc = [];
if (node.left != null) {
acc.push(node.left);
}
if (node.right != null) {
acc.push(node.right);
}
return acc;
}
printBredthOrder() {
let result = [];
if (this.root == null) {
} else {
let acc = [this.root];
let workingAcc = [this.root];
let tmpAcc = [];
do {
tmpAcc = [];
for (let i = 0; i < workingAcc.length; i++) {
acc = [...acc, workingAcc[i].left];
acc = [...acc, workingAcc[i].right];
let left = this.getSiblings(workingAcc[i].left);
let right = this.getSiblings(workingAcc[i].right);
tmpAcc = [...tmpAcc, ...left];
tmpAcc = [...tmpAcc, ...right];
}
acc = [...acc, ...tmpAcc];
workingAcc = tmpAcc;
} while (tmpAcc.length != 0);
for (let i = 0; i < acc.length; i++) {
result.push(acc[i].value);
}
}
return result;
}
}
let bt = new BinaryTree("h");
bt.insert("d");
bt.insert("l");
bt.insert("b");
bt.insert("f");
bt.insert("j");
bt.insert("n");
bt.insert("a");
bt.insert("c");
bt.insert("e");
bt.insert("g");
bt.insert("i");
bt.insert("k");
bt.insert("m");
bt.insert("o");
let io = bt.printInOrder();
let bo = bt.printBredthOrder();
printTree(io, bo);
// Node Class
class Node {
constructor (val, left=null, right=null) {
this.val = val;
this.left = left;
this.right = right;
}
}
// Binary Tree
const head = new Node(20,
new Node(10,
new Node(5,
new Node(3,
new Node(2,
new Node(1)),
new Node(4)),
new Node(8,
new Node(7,
new Node(6)),
new Node(9))),
new Node(15,
new Node(13,
new Node(11,
null,
new Node(12)),
new Node(14)),
new Node(18,
new Node(16,
null,
new Node(17)),
new Node(19)))),
new Node(30, new Node(25,
new Node(23,
new Node(22,
new Node(21)),
new Node(24)),
new Node(28,
new Node(27,
new Node(26)),
new Node(29))),
new Node(35,
new Node(33,
new Node(31,
null,
new Node(32)),
new Node(34)),
new Node(38,
new Node(36,
null,
new Node(37)),
new Node(39,
null,
new Node(40))))),
);
// VIEW
// 20
// 10 30
// 5 15 | 25 35
// 3 8 | 13 18 || 23 28 | 33 38
// 2 4 | 7 9 || 11 14 | 16 19 ||| 22 24 | 27 29 || 31 34 | 36 39
//1 n | n n || 6 n | n n ||| n 12 | n n || 17 n | n n |||| 21 n | n n || 26 n | n n |||| n 32 | n n || n 37 | n 40
// In Order Tree Traversal
const inOrder = (node) => {
if(node.left !== null) {
inOrder(node.left);
}
console.log(node.val);
if(node.right !== null) {
inOrder(node.right);
}
}
// Pre Order Tree Traversal
const preOrder = (node) => {
console.log(node.val);
if(node.left !== null) {
preOrder(node.left);
}
if(node.right !== null) {
preOrder(node.right);
}
}
// Post Order Tree Traversal
const postOrder = (node) => {
if(node.left !== null) {
postOrder(node.left);
}
if(node.right !== null) {
postOrder(node.right);
}
console.log(node.val);
}
// Node Count Recursively
const nodeCount = (node) => {
if(node.left !== null) {
nodeCount(node.left);
}
if(node.right !== null) {
nodeCount(node.right);
}
count++;
}
// Sum of all Nodes Recursively
const totalValue = (node) => {
if(node.left !== null) {
totalValue(node.left);
}
if(node.right !== null) {
totalValue(node.right);
}
total += node.val;
}
// inOrder(head);
// preOrder(head);
// postOrder(head);
let count = 0;
nodeCount(head)
console.log(count);
let total = 0;
totalValue(head)
console.log(total);
// NOTE
// if the values are continuous between 1/0 and n then the total is simply (n*(n+!))/2
// if the values are continuous between m and n then the total is simply ((n*(n+!))/2) - ((m*(m+!))/2)

Javascript: algorithm to convert Binary search tree to doubly linked list

I am trying to write the algorithm to convert a BST to a doubly linked list. This is what I have so far. Below is the code:
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
function BinaryTree() {
this.root = null;
}
BinaryTree.prototype.push = function(val) {
var root = this.root;
if(!root) {
this.root = new TreeNode(val);
return;
}
var currentNode = root;
var newNode = new TreeNode(val);
while(currentNode) {
if (val < currentNode.val) {
if(!currentNode.left) {
currentNode.left = newNode;
break;
} else {
currentNode = currentNode.left;
}
} else if(val > currentNode.val) {
if(!currentNode.right) {
currentNode.right = newNode;
break;
} else {
currentNode = currentNode.right;
}
}
}
}
var bt = new BinaryTree();
bt.push(4);
bt.push(2);
bt.push(5);
bt.push(1);
bt.push(3);
//console.log(bt);
//var node = bt.root;
function Node(node) {
//this.data = value;
//this.previous = this.next = null;
var head = null;
var tail = null;
var prev = null;
console.log(bstToLL(node, head, prev, tail));
}
//function DoublyLinkedList() {
// this.head = null;
// this.prev = null;
// this.tail = null;
//}
function bstToLL(node, head, prev, tail) {
if (node === null) {
return;
}
bstToLL(node.left, head, prev, tail);
if (head === null) {
head = node;
//console.log(head)
}
if (prev === null) {
prev = node;
//console.log(prev)
} else {
//console.log(node);
//console.log(prev);
node.left = prev;
prev.right = node;
}
prev = node
bstToLL(node.right, head, prev, tail);
if(node.right === null) {
tail = node;
}
return head;
}
Node(bt.root);
The code works, but I don't think it is getting the right result. The binary tree looks like-
4
/ \
2 5
/ \
1 3
When I return the head from the bstToLL() method, I get an object with val 4 pointing to right child 5 and left child 2 and so on and so forth.
If you run the code, and check the debugger you will see the head object.
Can someone please guide me if I am doing this the right way, and how to fix the result?
Here is some code which converts a binary tree into a LinkedList. It will log 1, 2, 3, 4, and 5, in order:
function TreeNode(left, value, right) {
this.left = left;
this.value = value;
this.right = right;
}
function ListNode(prev, value, next) {
this.prev = prev;
this.value = value;
this.next = next;
}
function LinkedList(head, tail) {
if (tail === undefined) tail = head;
this.head = head;
this.tail = tail;
}
LinkedList.prototype.addToStart = function(list) {
this.head.prev = list.tail;
list.tail.next = this.head;
this.head = list.head;
}
LinkedList.prototype.addToEnd = function(list) {
this.tail.next = list.head;
list.head.prev = this.tail;
this.tail = list.tail;
};
function bstToLL(tree) {
var centerNode = new ListNode(null, tree.value, null);
var list = new LinkedList(centerNode);
if (tree.left) list.addToStart(bstToLL(tree.left));
if (tree.right) list.addToEnd(bstToLL(tree.right));
return list;
}
var tree = new TreeNode(
new TreeNode(
new TreeNode(null, 1, null),
2,
new TreeNode(null, 3, null)
),
4,
new TreeNode(null, 5, null)
);
var linkedList = bstToLL(tree);
for (var node = linkedList.head; node; node = node.next) console.log(node.value);

Categories