diff --git a/src/app/recursion-tree/edge.jsx b/src/app/common/tree/TreeEdge.jsx
similarity index 98%
rename from src/app/recursion-tree/edge.jsx
rename to src/app/common/tree/TreeEdge.jsx
index ff44400..91779fe 100644
--- a/src/app/recursion-tree/edge.jsx
+++ b/src/app/common/tree/TreeEdge.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react';
-class Edge extends Component {
+class TreeEdge extends Component {
constructor() {
super();
this.state={
@@ -91,4 +91,4 @@ class Edge extends Component {
}
}
-export default Edge;
\ No newline at end of file
+export default TreeEdge;
\ No newline at end of file
diff --git a/src/app/recursion-tree/vertex.jsx b/src/app/common/tree/TreeVertex.jsx
similarity index 97%
rename from src/app/recursion-tree/vertex.jsx
rename to src/app/common/tree/TreeVertex.jsx
index ab72f8d..581834b 100644
--- a/src/app/recursion-tree/vertex.jsx
+++ b/src/app/common/tree/TreeVertex.jsx
@@ -1,6 +1,6 @@
import React, {Component} from 'react';
-class Vertex extends Component {
+class TreeVertex extends Component {
constructor() {
super();
@@ -80,4 +80,4 @@ function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
-export default Vertex;
\ No newline at end of file
+export default TreeVertex;
\ No newline at end of file
diff --git a/src/app/components/algorithm-cards.jsx b/src/app/components/algorithm-cards.jsx
index 87647eb..5f15922 100644
--- a/src/app/components/algorithm-cards.jsx
+++ b/src/app/components/algorithm-cards.jsx
@@ -29,6 +29,12 @@ const algorithms = [
description: "Compare different recursive sorting algorithms",
image: '/AlgorithmVisualizer/images/sort.png?height=200&width=300'
},
+ {
+ id: 'heap',
+ title: 'Heap Visualization',
+ description: "Visualize heap data structure operations like insert and delete with max/min heap support",
+ image: '/AlgorithmVisualizer/images/heap.png?height=200&width=300'
+ },
{
id: 'n-queen',
title: 'N Queen',
diff --git a/src/app/heap/canvasSVG.jsx b/src/app/heap/canvasSVG.jsx
new file mode 100644
index 0000000..5b2ef32
--- /dev/null
+++ b/src/app/heap/canvasSVG.jsx
@@ -0,0 +1,46 @@
+import { Component } from 'react';
+import TreeEdge from "../common/tree/TreeEdge";
+import TreeVertex from "../common/tree/TreeVertex";
+
+class CanvasSvg extends Component {
+ render() {
+ let off = this.props.offset;
+
+ return (
+
+
+ {this.props.edges.map((edge, index) => (
+
+ ))}
+
+ {this.props.vertices.map((vertex, index) => (
+
+ ))}
+
+
+ );
+ }
+}
+
+export default CanvasSvg;
diff --git a/src/app/heap/menu.jsx b/src/app/heap/menu.jsx
new file mode 100644
index 0000000..61d1e8b
--- /dev/null
+++ b/src/app/heap/menu.jsx
@@ -0,0 +1,88 @@
+import { CustomSelect } from '@/components/custom-select';
+import { Button } from '@/components/ui/button';
+import { Input } from '@/components/ui/input';
+// import { div } from '@/components/ui/div';
+import { Component } from 'react';
+
+class Menu extends Component {
+ handleInputChange = (event) => {
+ const value = parseInt(event.target.value) || 0;
+ this.props.setInputValue(value);
+ }
+
+ handleHeapTypeChange = (index) => {
+ this.props.setHeapType(index === 0); // 0 = Max Heap, 1 = Min Heap
+ }
+
+ render() {
+ return (
+
+
Heap Controls
+
+
+
+
+
+
+
Heap Info
+
+
Type: {this.props.isMaxHeap ? 'Max Heap' : 'Min Heap'}
+
Size: {this.props.heapSize}
+
+
+
+
+ Push Value
+
+
+
+ Pop Value
+
+
+
+ Reset Heap
+
+
+ );
+ }
+
+ isClickable = () => {
+ if (this.props.disable) {
+ return { cursor: "not-allowed" };
+ } else {
+ return {};
+ }
+ }
+}
+
+export default Menu;
diff --git a/src/app/heap/page.jsx b/src/app/heap/page.jsx
new file mode 100644
index 0000000..dd70d7e
--- /dev/null
+++ b/src/app/heap/page.jsx
@@ -0,0 +1,158 @@
+"use client";
+
+import Navbar from '@/components/navbar';
+import { Component } from 'react';
+import CanvasSvg from "./canvasSVG";
+import { Heap } from "@/lib/heap/Heap";
+import Menu from "./menu";
+
+class HeapVisualization extends Component {
+ constructor() {
+ super();
+ this.state = {
+ heap: new Heap(true), // true for max heap
+ vertices: [],
+ edges: [],
+ current: -1,
+ isMaxHeap: true,
+ inputValue: 0,
+ offset: 0,
+ animating: false
+ }
+ }
+
+ setHeapType = (isMaxHeap) => {
+ this.setState({
+ heap: new Heap(isMaxHeap),
+ isMaxHeap,
+ vertices: [],
+ edges: [],
+ offset: 0
+ });
+ }
+
+ setInputValue = (value) => {
+ this.setState({ inputValue: value });
+ }
+
+ pushValue = async () => {
+ if (this.state.animating) return;
+
+ this.setState({ animating: true });
+ const heap = this.state.heap;
+ heap.push(this.state.inputValue);
+
+ await this.updateVisualization();
+ this.setState({ animating: false });
+ }
+
+ popValue = async () => {
+ if (this.state.animating || this.state.heap.heap.length === 0) return;
+
+ this.setState({ animating: true });
+ const heap = this.state.heap;
+ heap.pop();
+
+ await this.updateVisualization();
+ this.setState({ animating: false });
+ }
+
+ reset = () => {
+ this.setState({
+ heap: new Heap(this.state.isMaxHeap),
+ vertices: [],
+ edges: [],
+ offset: 0,
+ current: -1
+ });
+ }
+
+ updateVisualization = async () => {
+ const tree = this.state.heap.getVisualizationTree();
+
+ if (!tree) {
+ this.setState({ vertices: [], edges: [], offset: 0 });
+ return;
+ }
+
+ this.setState({
+ edges: [],
+ vertices: [],
+ offset: tree.x
+ });
+
+ await this.buildVisualization(tree, undefined);
+ }
+
+ buildVisualization = async (node, parent) => {
+ let vertices = this.state.vertices;
+ let current = vertices.length;
+
+ const vertexData = {
+ label: node.tree.label,
+ val: node.tree.node,
+ x: node.x,
+ y: node.y,
+ px: parent ? parent.x : node.x,
+ py: parent ? parent.y : node.y
+ };
+
+ vertices.push(vertexData);
+ this.setState({ vertices: [...vertices], current });
+
+ if (parent) {
+ let edges = this.state.edges;
+ edges.push({
+ x1: parent.x,
+ y1: parent.y,
+ x2: node.x,
+ y2: node.y
+ });
+ this.setState({ edges: [...edges] });
+ }
+
+ await sleep(300);
+
+ for (let i = 0; i < node.children.length; i++) {
+ await this.buildVisualization(node.children[i], node);
+ }
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+function sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+export default HeapVisualization;
diff --git a/src/app/recursion-tree/bst.js b/src/app/recursion-tree/bst.js
deleted file mode 100644
index 1f08782..0000000
--- a/src/app/recursion-tree/bst.js
+++ /dev/null
@@ -1,25 +0,0 @@
-class Node{
- constructor(val) {
- this.val = val;
- this.left = undefined;
- this.right = undefined;
- }
-}
-export class BST{
- constructor() {
- this.root = undefined;
- }
- insert(x){
- this.root = this.insertX(x,this.root);
- }
- insertX(x,node){
- if( node === undefined ){
- return new Node(x);
- return;
- }
- if( node.value === x ) return node;
- else if( node.value > x ) node.left = this.insertX(x,node.left);
- else node.right = this.insertX(x,node.right);
- }
-
-}
\ No newline at end of file
diff --git a/src/app/recursion-tree/canvasSVG.jsx b/src/app/recursion-tree/canvasSVG.jsx
index 8266246..8b8de0b 100644
--- a/src/app/recursion-tree/canvasSVG.jsx
+++ b/src/app/recursion-tree/canvasSVG.jsx
@@ -1,6 +1,6 @@
import { Component } from 'react';
-import Edge from "./edge";
-import Vertex from "./vertex";
+import TreeEdge from "../common/tree/TreeEdge";
+import TreeVertex from "../common/tree/TreeVertex";
class CanvasSvg extends Component {
constructor() {
@@ -28,7 +28,7 @@ class CanvasSvg extends Component {
{
this.props.edges.map((edge, cellidx) => {
return (
- {
return (
- {
- switch (this.props.algo) {
- case 0:
- return
-
- The Fibonacci sequence, in which each number is the sum of the two preceding ones. The sequence
- commonly starts from 0 and 1
-
-
- N = Nth fibonacchi Number
-
-
- function = nCr(n,r)
-
-
- Fib(0) = 0
- Fib(1) = 1
- Fib(n) = Fib(n-1) + Fib(n-2)
-
-
;
-
- case 1:
- return
-
- In mathematics, the binomial coefficients are the positive integers that occur as coefficients
- in the binomial theorem. It is the coefficient of
- the x^k term in the polynomial expansion of the binomial power (1+x)^n
-
-
- nCr = n! / ( k! * (n-k)! )
-
-
- function = nCr(n,r)
-
-
- nCr(a,a) = 1
- nCr(a,0) = 1
- nCr(n,r) = nCr(n-1,r-1)+nCr(n-1,r)
-
-
;
- case 2:
- return
-
- In combinatorial mathematics, a derangement is a permutation of the elements of a set, such that
- no element appears in its original position.
-
-
- N = Nth Derangement
-
-
- function = der(n)
-
-
- der(0) = 1
- der(1) = 0
- der(n) = (n-1) * ( der(n-1) + der(n-2) )
-
-
;
- case 3:
- return
-
- N = Number
- P = Power
-
-
- function = bigmod(n,p)
-
-
- bigmod(a,0) = 1
- bigmod(a,1) = a
- bigmod(n,p) = bigmod(n,p/2)^2; p is even
- bigmod(n,p) = bigmod(n,(p-1)/2)^2 * n ; p is odd
-
-
;
- case 4:
- return
-
- a Stirling number of the second kind (or Stirling partition number) is the number of ways to
- partition a set of n objects into k non-empty subsets
-
-
- N = Row
- R = Column
-
-
- function = stir2(n,r)
-
-
- stir2(a,a) = 1
- stir2(0,a) = 0
- stir2(n,r) = stir2(n-1,r) * r + stir2(n-1,r-1)
-
-
-
;
-
- default:
- return Henlo ;
-
- }
- }
-
- render() {
- return (
-
- {this.Switcherr()}
-
- );
- }
-}
-
-export default Details;
\ No newline at end of file
diff --git a/src/app/recursion-tree/fib.jsx b/src/app/recursion-tree/fib.jsx
index 2e194c9..0388064 100644
--- a/src/app/recursion-tree/fib.jsx
+++ b/src/app/recursion-tree/fib.jsx
@@ -1,4 +1,5 @@
-import {Tree,buchheim} from './Tree';
+import {TreeNode,buchheim} from '@/lib/tree/Tree';
+
export function getTree(n,algo=0,r=0){
if(algo === 0)
return buchheim( fib(n) );
@@ -13,7 +14,7 @@ export function getTree(n,algo=0,r=0){
}
function fib(n){
- let tree = new Tree(n,[],n+"");
+ let tree = new TreeNode(n,[],n+"");
if( n <2 ) return tree;
tree.children.push( fib(n-1) );
tree.children.push( fib(n-2) );
@@ -22,7 +23,7 @@ function fib(n){
}
function sib(n){
- let tree = new Tree(n,[]);
+ let tree = new TreeNode(n,[]);
if( n <3 ) return tree;
tree.children.push( sib(n-2) );
tree.children.push( sib(n-3) );
@@ -32,16 +33,16 @@ function sib(n){
function NcR(n,r){
if (r > n)
- return new Tree(-1,[],"("+n+","+r+")");
+ return new TreeNode(-1,[],"("+n+","+r+")");
if (n === r)
- return new Tree(1,[],"("+n+","+r+")");
+ return new TreeNode(1,[],"("+n+","+r+")");
if (r === 0)
- return new Tree(1,[],"("+n+","+r+")");;
+ return new TreeNode(1,[],"("+n+","+r+")");;
// nCr(n, r) = nCr(n - 1, r - 1) + nCr(n - 1, r)
- let tree = new Tree(0,[],"("+n+","+r+")");
+ let tree = new TreeNode(0,[],"("+n+","+r+")");
tree.children.push( NcR(n-1,r-1) );
tree.children.push( NcR(n-1,r) );
tree.node = tree.children[0].node+tree.children[1].node;
@@ -49,9 +50,9 @@ function NcR(n,r){
}
function derangement(n){
- if( n == 0 ) return new Tree(1,[],n+"");
- if( n == 1 ) return new Tree(0,[],n+"");
- let tree = new Tree(0,[],n+"");
+ if( n == 0 ) return new TreeNode(1,[],n+"");
+ if( n == 1 ) return new TreeNode(0,[],n+"");
+ let tree = new TreeNode(0,[],n+"");
tree.children.push( derangement(n-1) );
tree.children.push( derangement(n-2) );
tree.node = (n-1)*(tree.children[0].node+tree.children[1].node);
@@ -59,9 +60,9 @@ function derangement(n){
}
function bigmod(n,r){
- if( r === 0 ) return new Tree(1,[],"("+n+","+r+")");
- if( r === 1 ) return new Tree(n,[],"("+n+","+r+")");
- let tree = new Tree(1,[],"("+n+","+r+")");
+ if( r === 0 ) return new TreeNode(1,[],"("+n+","+r+")");
+ if( r === 1 ) return new TreeNode(n,[],"("+n+","+r+")");
+ let tree = new TreeNode(1,[],"("+n+","+r+")");
if( r%2 === 1 ){
tree.children.push( bigmod(n,(r-1)/2 ) );
tree.children.push( bigmod(n,(r-1)/2) );
@@ -77,10 +78,10 @@ function bigmod(n,r){
}
function stirling2(n,r){
- if( n === r ) return new Tree(1,[],"("+n+","+r+")");
- if( r === 0 ) return new Tree(0,[],"("+n+","+r+")");
+ if( n === r ) return new TreeNode(1,[],"("+n+","+r+")");
+ if( r === 0 ) return new TreeNode(0,[],"("+n+","+r+")");
- let tree = new Tree(0,[],"("+n+","+r+")");
+ let tree = new TreeNode(0,[],"("+n+","+r+")");
tree.children.push( stirling2(n-1,r) );
tree.children.push( stirling2(n-1,r-1) );
tree.node = tree.children[0].node*r+tree.children[1].node;
diff --git a/src/app/recursion-tree/vertexOriginal.jsx b/src/app/recursion-tree/vertexOriginal.jsx
deleted file mode 100644
index 4637dd3..0000000
--- a/src/app/recursion-tree/vertexOriginal.jsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import React, {Component} from 'react';
-
-class Vertex extends Component {
-
- constructor() {
- super();
- this.state = {
- prevPoss:{
- x:0,
- y:0
- },
- poss:{
- x:0,
- y:0,
- xx:0,
- yy:0
- },
- prevX:0
- }
- }
-
- componentDidUpdate(prevProps) {
- if (this.state.poss.x !== this.props.pos.x) {
- let pp = this.state.poss;
- pp.xx = pp.x;
- pp.yy = pp.y;
- pp.x = this.props.pos.x;
- pp.y = this.props.pos.y;
- this.setState({poss:pp});
- document.getElementById('vbanim').beginElement();
- }
- }
- render() {
-
- return (
-
-
- {/* */}
-
-
-
- {this.props.label}
-
-
-
-
-
- );
- }
-}
-
-function sleep(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
-}
-
-export default Vertex;
\ No newline at end of file
diff --git a/src/lib/algorithms/bfs.jsx b/src/lib/algorithms/bfs.js
similarity index 100%
rename from src/lib/algorithms/bfs.jsx
rename to src/lib/algorithms/bfs.js
diff --git a/src/lib/heap/Heap.js b/src/lib/heap/Heap.js
new file mode 100644
index 0000000..ae49079
--- /dev/null
+++ b/src/lib/heap/Heap.js
@@ -0,0 +1,121 @@
+import { TreeNode, buchheim } from '@/lib/tree/Tree';
+
+export class Heap {
+ constructor(isMaxHeap = true) {
+ this.heap = [];
+ this.isMaxHeap = isMaxHeap;
+ this.operations = [];
+ }
+
+ compare(a, b) {
+ return this.isMaxHeap ? a > b : a < b;
+ }
+
+ parent(index) {
+ return Math.floor((index - 1) / 2);
+ }
+
+ leftChild(index) {
+ return 2 * index + 1;
+ }
+
+ rightChild(index) {
+ return 2 * index + 2;
+ }
+
+ swap(i, j) {
+ [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
+ }
+
+ push(value) {
+ this.heap.push(value);
+ this.heapifyUp(this.heap.length - 1);
+ this.operations.push({
+ type: 'push',
+ value: value,
+ heap: [...this.heap]
+ });
+ }
+
+ pop() {
+ if (this.heap.length === 0) return null;
+
+ const root = this.heap[0];
+ const lastElement = this.heap.pop();
+
+ if (this.heap.length > 0) {
+ this.heap[0] = lastElement;
+ this.heapifyDown(0);
+ }
+
+ this.operations.push({
+ type: 'pop',
+ value: root,
+ heap: [...this.heap]
+ });
+
+ return root;
+ }
+
+ heapifyUp(index) {
+ if (index === 0) return;
+
+ const parentIndex = this.parent(index);
+ if (this.compare(this.heap[index], this.heap[parentIndex])) {
+ this.swap(index, parentIndex);
+ this.heapifyUp(parentIndex);
+ }
+ }
+
+ heapifyDown(index) {
+ let targetIndex = index;
+ const leftIndex = this.leftChild(index);
+ const rightIndex = this.rightChild(index);
+
+ if (leftIndex < this.heap.length &&
+ this.compare(this.heap[leftIndex], this.heap[targetIndex])) {
+ targetIndex = leftIndex;
+ }
+
+ if (rightIndex < this.heap.length &&
+ this.compare(this.heap[rightIndex], this.heap[targetIndex])) {
+ targetIndex = rightIndex;
+ }
+
+ if (targetIndex !== index) {
+ this.swap(index, targetIndex);
+ this.heapifyDown(targetIndex);
+ }
+ }
+
+ toTreeNode() {
+ if (this.heap.length === 0) return null;
+ return this.buildTreeNode(0);
+ }
+
+ buildTreeNode(index) {
+ if (index >= this.heap.length) return null;
+
+ const children = [];
+ const leftIndex = this.leftChild(index);
+ const rightIndex = this.rightChild(index);
+
+ if (leftIndex < this.heap.length) {
+ children.push(this.buildTreeNode(leftIndex));
+ }
+ if (rightIndex < this.heap.length) {
+ children.push(this.buildTreeNode(rightIndex));
+ }
+
+ return new TreeNode(
+ this.heap[index],
+ children.filter(child => child !== null),
+ this.heap[index].toString()
+ );
+ }
+
+ getVisualizationTree() {
+ const treeNode = this.toTreeNode();
+ return treeNode ? buchheim(treeNode) : null;
+ }
+}
diff --git a/src/app/recursion-tree/Tree.js b/src/lib/tree/Tree.js
similarity index 99%
rename from src/app/recursion-tree/Tree.js
rename to src/lib/tree/Tree.js
index 5137bf3..c20cb5a 100644
--- a/src/app/recursion-tree/Tree.js
+++ b/src/lib/tree/Tree.js
@@ -1,7 +1,7 @@
// draw tree class functions start :/
-export class Tree{
+export class TreeNode {
constructor(node=0,children=[],label="") {
this.id = 0;
this.node = node;