├── Designs ├── V1.xd ├── Landing Page.png ├── Loading Page.png └── colour_palette.jpg ├── js ├── tailwindConfig.js ├── utils.js ├── animation │ ├── animationScript.js │ └── anime.min.js ├── datastructureControllers │ ├── stack.js │ ├── queue │ │ ├── circularqueue.js │ │ ├── priorityqueue │ │ │ ├── UnsortedPriorityQueue.js │ │ │ └── SortedPriorityQueue.js │ │ └── queue.js │ ├── binaryTree.js │ ├── singleLinkedList.js │ ├── doubleLinkedList.js │ └── array.js └── algorithmsControllers │ ├── searchAlgorithms.js │ └── sortAlgorithms.js ├── README.md ├── LICENSE ├── index.html ├── stack.html ├── binary.html ├── doublylinklist.html ├── array.html ├── search.html ├── singlylinklist.html ├── sort.html ├── priorityqueue.html └── queue.html /Designs/V1.xd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashray446/DSA_MADE_EASY/HEAD/Designs/V1.xd -------------------------------------------------------------------------------- /Designs/Landing Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashray446/DSA_MADE_EASY/HEAD/Designs/Landing Page.png -------------------------------------------------------------------------------- /Designs/Loading Page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashray446/DSA_MADE_EASY/HEAD/Designs/Loading Page.png -------------------------------------------------------------------------------- /Designs/colour_palette.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aashray446/DSA_MADE_EASY/HEAD/Designs/colour_palette.jpg -------------------------------------------------------------------------------- /js/tailwindConfig.js: -------------------------------------------------------------------------------- 1 | tailwind.config = { 2 | theme: { 3 | colors : { 4 | 'primary' : '#166D8A', 5 | 'secondary' : '#FDD741', 6 | 'light' : '#F4F3ED', 7 | 'primary10' : '#24B4A5', 8 | 'primary20' : '#8FEDC2', 9 | 'pink' : '#c17c74' 10 | } , 11 | extend: { 12 | fontFamily : { 13 | serif : ['Abel', 'sans'], 14 | sansSerif : ['Abel', 'sans-serif'] 15 | } 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DSA_MADE_EASY 2 | A fun way to learn about DSA concepts 3 | 4 | Checkout the site at https://aashray446.github.io/DSA_MADE_EASY/index.html 5 | 6 | The project is based on plain javascript, HTML, and CSS with no framework purposely, As to help beginners understand the code without getting overwhelmed by any framework code. 7 | 8 | ### How to run the Code ?? 9 | - Just open Index.html (Easy right?? ) 10 | 11 | ![image](https://github.com/Aashray446/DSA_MADE_EASY/assets/69245931/1ccb8545-883d-491c-b3a2-b8f0bb8da242) 12 | 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Aashray Katiyar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /js/utils.js: -------------------------------------------------------------------------------- 1 | // ACCORDION 2 | export default (() => { 3 | let acc = document.getElementsByClassName("accordion"); 4 | for (let i = 0; i < acc.length; i++) { 5 | acc[i].addEventListener("click", function() { 6 | this.classList.toggle("active"); 7 | let panel = this.nextElementSibling; 8 | panel.style.maxHeight ? panel.style.maxHeight = null : panel.style.maxHeight = panel.scrollHeight + "px"; 9 | for (i = 0; i < acc.length; i++) { 10 | if (acc[i] != this && acc[i].classList.contains("active")) { 11 | acc[i].classList.toggle("active"); 12 | acc[i].nextElementSibling.style.maxHeight = null; 13 | } 14 | } 15 | }); 16 | } 17 | })() 18 | 19 | const getRandomInt = (min, max) => { 20 | return Math.floor(Math.random() * (max - min + 1)) + min; 21 | } 22 | 23 | const createElement = (data) => { 24 | const element = document.createElement('div'); 25 | element.classList.add(this.structure) 26 | element.style.backgroundColor = data?.color 27 | element.innerHTML = `

${data?.value}

` 28 | element.classList.add('circlerow') 29 | return element 30 | } 31 | 32 | const getRandomColor = () => { 33 | var trans = '0.3'; 34 | var color = 'rgba('; 35 | for (var i = 0; i < 3; i++) { 36 | color += Math.floor(Math.random() * 255) + ','; 37 | } 38 | color += trans + ')'; 39 | return color; 40 | } 41 | 42 | const wrapFR = (value, isfront) => { 43 | if(isfront) return `

Front is ${value}

` 44 | return `

Rear is ${value}

` 45 | } 46 | 47 | 48 | 49 | function sleep(ms) { 50 | return new Promise( 51 | resolve => setTimeout(resolve, ms) 52 | ); 53 | } 54 | 55 | 56 | export {getRandomInt, createElement, getRandomColor, wrapFR, sleep} -------------------------------------------------------------------------------- /js/animation/animationScript.js: -------------------------------------------------------------------------------- 1 | function fitElementToParent(el, padding) { 2 | var timeout = null; 3 | function resize() { 4 | if (timeout) clearTimeout(timeout); 5 | anime.set(el, {scale: 1}); 6 | var pad = padding || 0; 7 | var parentEl = el.parentNode; 8 | var elOffsetWidth = el.offsetWidth - pad; 9 | var parentOffsetWidth = parentEl.offsetWidth; 10 | var ratio = parentOffsetWidth / elOffsetWidth; 11 | timeout = setTimeout(anime.set(el, {scale: ratio}), 10); 12 | } 13 | resize(); 14 | window.addEventListener('resize', resize); 15 | } 16 | 17 | var advancedStaggeringAnimation = (function() { 18 | 19 | var staggerVisualizerEl = document.querySelector('.stagger-visualizer'); 20 | var dotsWrapperEl = staggerVisualizerEl.querySelector('.dots-wrapper'); 21 | var dotsFragment = document.createDocumentFragment(); 22 | var grid = [10, 10]; 23 | var cell = 50; 24 | var numberOfElements = grid[0] * grid[1]; 25 | var animation; 26 | var paused = true; 27 | 28 | fitElementToParent(staggerVisualizerEl, 0); 29 | 30 | for (var i = 0; i < numberOfElements; i++) { 31 | var dotEl = document.createElement('div'); 32 | dotEl.classList.add('dot'); 33 | dotEl.innerText = Math.floor(Math.random() * 9) + 1; 34 | dotsFragment.appendChild(dotEl); 35 | } 36 | 37 | dotsWrapperEl.appendChild(dotsFragment); 38 | 39 | var index = anime.random(0, numberOfElements-1); 40 | var nextIndex = 0; 41 | 42 | anime.set('.stagger-visualizer .cursor', { 43 | translateX: anime.stagger(-cell, {grid: grid, from: index, axis: 'x'}), 44 | translateY: anime.stagger(-cell, {grid: grid, from: index, axis: 'y'}), 45 | translateZ: 0, 46 | scale: 1.5, 47 | }); 48 | 49 | function play() { 50 | 51 | paused = false; 52 | if (animation) animation.pause(); 53 | 54 | nextIndex = anime.random(0, numberOfElements-1); 55 | 56 | animation = anime.timeline({ 57 | easing: 'easeInOutQuad', 58 | complete: play 59 | }) 60 | .add({ 61 | targets: '.stagger-visualizer .cursor', 62 | keyframes: [ 63 | { scale: .75, duration: 120}, 64 | { scale: 2.5, duration: 220}, 65 | { scale: 1.5, duration: 450}, 66 | ], 67 | duration: 300 68 | }) 69 | .add({ 70 | targets: '.stagger-visualizer .dot', 71 | keyframes: [ 72 | { 73 | translateX: anime.stagger('-2px', {grid: grid, from: index, axis: 'x'}), 74 | translateY: anime.stagger('-2px', {grid: grid, from: index, axis: 'y'}), 75 | duration: 100 76 | }, { 77 | translateX: anime.stagger('4px', {grid: grid, from: index, axis: 'x'}), 78 | translateY: anime.stagger('4px', {grid: grid, from: index, axis: 'y'}), 79 | scale: anime.stagger([2.6, 1], {grid: grid, from: index}), 80 | duration: 225 81 | }, { 82 | translateX: 0, 83 | translateY: 0, 84 | scale: 1, 85 | duration: 1200, 86 | } 87 | ], 88 | delay: anime.stagger(80, {grid: grid, from: index}) 89 | }, 30) 90 | .add({ 91 | targets: '.stagger-visualizer .cursor', 92 | translateX: { value: anime.stagger(-cell, {grid: grid, from: nextIndex, axis: 'x'}) }, 93 | translateY: { value: anime.stagger(-cell, {grid: grid, from: nextIndex, axis: 'y'}) }, 94 | scale: 1.5, 95 | easing: 'cubicBezier(.075, .2, .165, 1)' 96 | }, '-=800') 97 | 98 | index = nextIndex; 99 | 100 | } 101 | 102 | play(); 103 | 104 | })(); -------------------------------------------------------------------------------- /js/datastructureControllers/stack.js: -------------------------------------------------------------------------------- 1 | //Container Variable Definition 2 | const container = document.getElementById("animation-container"); 3 | const structure = "stack"; 4 | const errorBox = document.getElementById("error"); 5 | 6 | const textFieldStack = document.getElementById("push"); 7 | const pushingData = document.getElementById("pushingData"); 8 | const popingData = document.getElementById("popingData"); 9 | 10 | const createElement = function (value) { 11 | const element = document.createElement("div"); 12 | element.classList.add("hidden"); 13 | element.classList.add(structure); 14 | if (value == null) { 15 | element.innerHTML = "-"; 16 | } else { 17 | element.innerHTML = value; 18 | } 19 | container.prepend(element); 20 | }; 21 | 22 | // ------------------------------ ANIMATIONS FUNCTIONS ------------------------------------------------- 23 | 24 | const movePushingElement = function () { 25 | let target = document.getElementById("pushingData"); 26 | let arrayElements = document.getElementsByClassName("stack"); 27 | 28 | // Some Unkown Error BruteForcely Solved 29 | let destination = arrayElements[1]; 30 | if (arrayElements.length == 1) { 31 | destination = arrayElements[0]; 32 | } 33 | 34 | let x = destination.offsetLeft - target.offsetLeft; 35 | let y = destination.offsetTop - target.offsetTop; 36 | 37 | anime({ 38 | targets: target, 39 | translateY: [{ value: y, easing: "linear" }], 40 | translateX: { 41 | value: x, 42 | }, 43 | complete: function () { 44 | document.getElementsByClassName("stack")[0].classList.remove("hidden"); 45 | anime.set(target, { 46 | translateX: 0, 47 | translateY: 0, 48 | }); 49 | }, 50 | }); 51 | }; 52 | 53 | const movePopingData = function () { 54 | let destination = document.getElementById("popingData"); 55 | target = document.getElementsByClassName("stack")[0]; 56 | 57 | let x = destination.offsetLeft - target.offsetLeft; 58 | let y = destination.offsetTop - target.offsetTop; 59 | 60 | anime({ 61 | targets: "stack", 62 | translateY: [{ value: y, easing: "linear" }], 63 | translateX: { 64 | value: x, 65 | }, 66 | complete: function () { 67 | var stackElementHolder = document.getElementsByClassName("stack")[0]; 68 | if (stackElementHolder) { 69 | document.getElementsByClassName("stack")[0].classList.remove("hidden"); 70 | anime.set(target, { 71 | translateX: 0, 72 | translateY: 0, 73 | }); 74 | } 75 | }, 76 | }); 77 | }; 78 | 79 | // ------------------ Implementation of stack with animation ------------------------- 80 | // Stack Implementation with array 81 | class Stack { 82 | 83 | //construtor 84 | constructor() { 85 | this.dataArray = new Array(); 86 | } 87 | push(value) { 88 | 89 | // Check if the value is null or not 90 | if (value == "") { 91 | errorBox.style.display = "block"; 92 | return; 93 | } else { 94 | errorBox.style.display = "none"; 95 | } 96 | 97 | if (this.dataArray.length > 12) { 98 | errorBox.style.display = "block"; 99 | errorBox.innerText = "Stack is Full"; 100 | return; 101 | } 102 | // THIS IS CREATING THE UI PART 103 | document.getElementById("pushingData").innerHTML = value; 104 | createElement(value); 105 | // ACUTAL ARRAY PUTTING 106 | this.dataArray.push(value); 107 | movePushingElement(); 108 | textFieldStack.value = ""; 109 | } 110 | 111 | pop() { 112 | if (this.dataArray.length == 0) { 113 | errorBox.style.display = "block"; 114 | errorBox.innerText = "Stack is Empty"; 115 | return; 116 | } 117 | movePopingData(); 118 | const list = document.getElementsByClassName(structure); 119 | list[0].remove(); 120 | document.getElementById("popingData").innerHTML = this.dataArray.pop(); 121 | } 122 | 123 | reset() { 124 | container.innerHTML = ""; 125 | this.dataArray = new Array(); 126 | errorBox.style.display = "none"; 127 | textFieldStack.value = ""; 128 | popingData.innerHTML = ""; 129 | pushingData.innerHTML = ""; 130 | }; 131 | 132 | peek() { 133 | if (this.dataArray.length == 0) { 134 | errorBox.style.display = "block"; 135 | errorBox.innerText = "Stack is Empty"; 136 | return; 137 | } 138 | const list = document.getElementsByClassName(structure); 139 | document.getElementById("popingData").innerHTML = 140 | this.dataArray[this.dataArray.length - 1]; 141 | } 142 | } 143 | 144 | // Function that will be used by the browser 145 | const stack = new Stack(); -------------------------------------------------------------------------------- /js/datastructureControllers/queue/circularqueue.js: -------------------------------------------------------------------------------- 1 | 2 | class Circularqueue{ 3 | container = document.getElementById('animation-container') 4 | structure = 'queue' 5 | 6 | qf = queue.qf 7 | qr = queue.qr 8 | inf = queue.inf 9 | 10 | createElement = (data) => { 11 | const element = document.createElement('div'); 12 | element.classList.add(this.structure) 13 | element.style.backgroundColor=data?.color 14 | element.innerHTML = `

${data?.value}

` 15 | element.classList.add('circlerow') 16 | return element 17 | } 18 | 19 | wrapFR = (value, isfront) => { 20 | if(isfront) { 21 | return `

Front is ${value}

` 22 | } 23 | return `

Rear is ${value}

` 24 | } 25 | 26 | array = new Array(); 27 | front = -1; 28 | rear = -1; 29 | length = 19; 30 | isactive=false; 31 | 32 | enqueue=(value)=>{ 33 | console.log("circular enqueuing") 34 | if(this.isFull()){ 35 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Overflow! Queue is full!" 36 | this.inf.style.display = 'block' 37 | return false; 38 | } 39 | 40 | let enqinf = document.getElementById('enqueueinfo') 41 | if(value=="" || value<-99 || value>99) { 42 | enqinf.getElementsByTagName('p')[0].innerHTML = "Random number is taken for Enqueue!" 43 | enqinf.style.display = 'block' 44 | value = Math.floor((Math.random() * 99) + 1); 45 | } else { 46 | enqinf.style.display = 'none' 47 | } 48 | 49 | const bg_color = getRandomColor() 50 | let element = this.createElement({'value': value, 'color': bg_color}) 51 | if(this.isEmpty()){ 52 | this.rear=this.front=0; 53 | this.array[this.rear]=value; 54 | this.container.replaceChild(element,this.container.children[this.rear]) 55 | } else{ 56 | this.rear=(this.rear+1)%this.length; 57 | this.array[this.rear]=value; 58 | this.container[this.rear]=value; 59 | this.container.replaceChild(element, this.container.children[this.rear]) 60 | } 61 | this.inf.style.display = 'none' 62 | this.qr.innerHTML = this.wrapFR(this.array[this.rear]||-1, false) 63 | this.qf.innerHTML = this.wrapFR(this.array[this.front]||-1, true) 64 | this.qf.style.display = 'flex' 65 | this.qr.style.display = 'flex' 66 | return true; 67 | } 68 | 69 | dequeue=()=>{ 70 | console.log("circular dequeuing") 71 | if(this.isEmpty()){ 72 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 73 | this.inf.style.display = 'block' 74 | return false; 75 | } 76 | this.container.insertBefore(this.createElement({'value': '-', 'color': 'rgba(255,255,255,0)'}), this.container.children[this.front]) 77 | this.container.removeChild(this.container.children[this.front+1]) 78 | if(this.front==this.rear){ 79 | this.front=-1; 80 | this.rear=-1; 81 | } else{ 82 | this.front=(this.front+1)%this.length; 83 | } 84 | this.inf.style.display = 'none' 85 | this.qr.innerHTML = this.wrapFR(this.array[this.rear]||-1, false) 86 | this.qf.innerHTML = this.wrapFR(this.array[this.front]||-1, true) 87 | this.qf.style.display = 'flex' 88 | this.qr.style.display = 'flex' 89 | return true; 90 | } 91 | 92 | isFull=()=>{ 93 | console.log(this.front, this.rear) 94 | if((this.rear+1)%this.length==this.front){ 95 | return true; 96 | } 97 | return false; 98 | } 99 | 100 | isEmpty=()=>{ 101 | console.log(this.front, this.rear) 102 | if(this.rear==this.front && this.front==-1){ 103 | return true; 104 | } 105 | return false; 106 | } 107 | 108 | reset=()=>{ 109 | this.array = new Array(); 110 | this.front = -1; 111 | this.rear = -1; 112 | this.container.innerHTML = ''; 113 | if(this.isactive) { 114 | this.container.classList.add('circlecontainer') 115 | for (let i = 0; i < this.length; i++) { 116 | this.container.append(this.createElement({'value': '-', 'color': 'rgba(255,255,255,0)'})); 117 | } 118 | }else { 119 | for (let i = 0; i < this.length; i++) { 120 | if(this.container.firstChild) { 121 | this.container.firstChild.remove(); 122 | } 123 | } 124 | } 125 | 126 | } 127 | 128 | handlengthchange=()=>{ 129 | for(let i=0; ithis.length){ 133 | for (let i=this.length; i setTimeout(resolve, ms)); 3 | } 4 | 5 | function bblSort(arr){ 6 | for(var i = 0; i < arr.length; i++){ 7 | for(var j = 0; j < ( arr.length - i -1 ); j++){ 8 | if(arr[j] > arr[j+1]){ 9 | var temp = arr[j] 10 | arr[j] = arr[j + 1] 11 | arr[j+1] = temp 12 | } 13 | } 14 | } 15 | return arr; 16 | } 17 | 18 | class SearchAlgorithms { 19 | container = document.getElementById('animation-container') 20 | display = document.getElementById('search-box') 21 | queinf = document.getElementById('queueinfo') 22 | speed = 600; 23 | 24 | structure = 'queue' 25 | 26 | createElement = (value) => { 27 | const element = document.createElement('div'); 28 | element.classList.add(this.structure) 29 | element.innerHTML = `

${value}

` 30 | return element 31 | } 32 | 33 | array = new Array(); 34 | length; 35 | searchtype = 'linear'; 36 | 37 | render(){ 38 | this.display.style.visibility = 'hidden'; 39 | this.container.innerHTML = ''; 40 | for (let i = 0; i < this.array.length; i++) { 41 | this.container.append(this.createElement(this.array[i])); 42 | } 43 | } 44 | 45 | add(value) { 46 | let enqinf = document.getElementById('enqueueinfo') 47 | if(value=="" || value<-99 || value>99) { 48 | value = Math.floor((Math.random() * 99) + 1); 49 | enqinf.getElementsByTagName('p')[0].innerHTML = "Random number is added!" 50 | enqinf.style.display = 'block' 51 | } else{ 52 | enqinf.style.display = 'none' 53 | } 54 | this.array.push(value); 55 | this.render(); 56 | } 57 | 58 | generateRandomArray(){ 59 | length=20; 60 | this.array = new Array(); 61 | for(let i=0;i index is ${index}

` 97 | this.container.children[index].style.backgroundColor = 'green'; 98 | } else { 99 | this.display.style.visibility = 'visible'; 100 | this.display.innerHTML = `

Element not found

` 101 | } 102 | return index; 103 | } 104 | 105 | async linearSearch(array, target) { 106 | this.render() 107 | for (let i = 0; i < array.length; i++) { 108 | this.display.style.visibility = 'visible'; 109 | this.display.innerHTML = `

Checking element at index ${i}.

` 110 | this.container.children[i].style.backgroundColor = 'orange'; 111 | if (array[i] == target) { 112 | return i; 113 | } 114 | await sleep(this.speed/2); 115 | this.container.children[i].style.backgroundColor = '#24b4a6df'; 116 | } 117 | 118 | return -1; 119 | } 120 | 121 | async binarySearch(array,target) { 122 | array = bblSort(this.array); 123 | this.array=array; 124 | this.render() 125 | let left = 0; 126 | let right = array.length - 1; 127 | let mid = Math.floor((left + right) / 2); 128 | while (left <= right) { 129 | this.display.style.visibility = 'visible'; 130 | this.display.innerHTML = `

Mid is ${mid}, start is ${left}, end is ${right}

` 131 | this.container.children[mid].style.backgroundColor = 'orange'; 132 | if (array[mid] == target) { 133 | return mid; 134 | } else if (array[mid] > target) { 135 | right = mid - 1; 136 | } else { 137 | left = mid + 1; 138 | } 139 | await sleep(this.speed); 140 | this.container.children[mid].style.backgroundColor = '#24b4a6df'; 141 | mid = Math.floor((left + right) / 2); 142 | } 143 | return -1; 144 | } 145 | 146 | reset() { 147 | this.array = new Array(); 148 | this.container.innerHTML = ''; 149 | } 150 | } 151 | 152 | let searchAlgorithms = new SearchAlgorithms(); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 | 81 | 82 | 83 |
84 | 85 | 86 | 87 |
88 | 89 |

Please use Screen larger than 768px to enjoy our app.

90 |

DSA VISUALIZER BY GROUP 14

91 |
92 |
93 |
94 |
95 |
96 |
97 | 98 | 99 |
100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /js/datastructureControllers/binaryTree.js: -------------------------------------------------------------------------------- 1 | // import { getRandomInt, sleep} from "../utils.js"; 2 | 3 | function getRandomInt(min, max) { 4 | return Math.floor(Math.random() * (max - min + 1) + min); 5 | } 6 | 7 | function sleep(ms) { 8 | return new Promise( 9 | resolve => setTimeout(resolve, ms) 10 | ); 11 | } 12 | 13 | const treeContainer = document.getElementById('tree'); 14 | let bst; 15 | 16 | //Input Fields 17 | const allInputFields = document.querySelectorAll("input[type='number']"); 18 | 19 | //Error Indicator 20 | const errorBox = document.getElementById("error1"); 21 | 22 | // Controller Buttons 23 | const createBtn = document.getElementById("createBtn"); 24 | const insertBtn = document.getElementById("insertBtn"); 25 | const searchBtn = document.getElementById("searchBtn"); 26 | const randomBstBtn = document.getElementById("randomBstBtn"); 27 | const resetBtn = document.getElementById("resetBtn"); 28 | 29 | // Inputs 30 | const createInput = document.getElementById('create'); 31 | const insertInput = document.getElementById('insert'); 32 | const searchInput = document.getElementById('search'); 33 | 34 | const createValue = (value) => { 35 | const li = document.createElement('li'); 36 | const a = document.createElement('a'); 37 | a.innerText = value; 38 | li.appendChild(a); 39 | return li; 40 | } 41 | 42 | const clearAllInputFields = () => { 43 | allInputFields.forEach(field => { 44 | field.value = ''; 45 | }); 46 | }; 47 | 48 | 49 | class BinarySearchTree { 50 | 51 | 52 | constructor(value, firstTime) { 53 | this.value = createValue(value); 54 | 55 | if (firstTime == true) { 56 | const roota = document.getElementById('tree'); 57 | const ul = document.createElement('ul'); 58 | ul.appendChild(this.value); 59 | roota.appendChild(ul); 60 | } 61 | 62 | this.left = null; 63 | this.right = null; 64 | 65 | } 66 | 67 | insert(value) { 68 | if (value < parseInt(this.value.firstChild.innerText)) { 69 | 70 | if (this.left == null) { 71 | this.left = new BinarySearchTree(value); 72 | if (this.right == null) { 73 | this.left.value.classList.add('left'); 74 | const ul = document.createElement('ul') 75 | ul.appendChild(this.left.value); 76 | this.value.appendChild(ul); 77 | } 78 | else { 79 | this.value.lastChild.prepend(this.left.value); 80 | } 81 | 82 | } else { 83 | this.left.insert(value); 84 | } 85 | } else { 86 | if (this.right == null) { 87 | this.right = new BinarySearchTree(value); 88 | if (this.left == null) { 89 | this.right.value.classList.add('right'); 90 | const ul = document.createElement('ul') 91 | ul.appendChild(this.right.value); 92 | this.value.appendChild(ul); 93 | } 94 | else { 95 | this.value.lastChild.appendChild(this.right.value); 96 | } 97 | } else { 98 | this.right.insert(value); 99 | } 100 | } 101 | 102 | } 103 | //search in binary tree 104 | async search(value) { 105 | if (value == parseInt(this.value.firstChild.innerText)) { 106 | this.value.firstChild.classList.add('found'); 107 | await sleep(4000); 108 | this.value.firstChild.classList.remove('found'); 109 | return true; 110 | } 111 | else if (value < parseInt(this.value.firstChild.innerText)) { 112 | if (this.left == null) { 113 | //Element not found 114 | errorBox.style.display = "block"; 115 | errorBox.innerHTML = "Element not found!"; 116 | this.left.value.firstChild.classList.add('pointer'); 117 | await sleep(1000) 118 | this.left.value.firstChild.classList.remove('pointer'); 119 | return null; 120 | } 121 | else { 122 | this.left.value.firstChild.classList.add('pointer'); 123 | await sleep(1000) 124 | this.left.value.firstChild.classList.remove('pointer'); 125 | return this.left.search(value); 126 | } 127 | } 128 | else { 129 | if (this.right == null) { 130 | //Element not found 131 | errorBox.style.display = "block"; 132 | errorBox.innerHTML = "Element not found!"; 133 | this.right.value.firstChild.classList.add('pointer'); 134 | await sleep(1000) 135 | this.right.value.firstChild.classList.remove('pointer'); 136 | return null; 137 | } 138 | else { 139 | this.right.value.firstChild.classList.add('pointer'); 140 | await sleep(1000) 141 | this.right.value.firstChild.classList.remove('pointer'); 142 | return this.right.search(value); 143 | } 144 | } 145 | } 146 | 147 | reset() { 148 | bst = null; 149 | treeContainer.innerHTML = ''; 150 | errorBox.style.display = "none"; 151 | clearAllInputFields(); 152 | } 153 | } 154 | 155 | 156 | const setBst = function (value) { 157 | if (bst != null) { 158 | bst.reset(); 159 | bst == null; 160 | } 161 | bst = new BinarySearchTree(value, true); 162 | } 163 | 164 | const generateRandomBst = function () { 165 | if (bst != null) { 166 | bst.reset(); 167 | } 168 | bst = new BinarySearchTree(getRandomInt(0, 100), true); 169 | for (let i = 0; i < 15; i++) { 170 | bst.insert(getRandomInt(0, 100)); 171 | } 172 | } 173 | 174 | 175 | // Button Event Listners Setup 176 | // createBtn.addEventListener('click', ()=>{ 177 | // setBst(createInput.value) 178 | // }); 179 | 180 | insertBtn.addEventListener('click', () => { 181 | if (insertInput.value === '') { 182 | //Don't allow show error and return 183 | errorBox.style.display = "block"; 184 | errorBox.innerHTML = "Value cannot be blank!"; 185 | return; 186 | } else { 187 | errorBox.style.display = "none"; 188 | } 189 | if (bst == null) { 190 | bst = new BinarySearchTree(insertInput.value, true); 191 | } else { 192 | bst.insert(insertInput.value) 193 | } 194 | }); 195 | searchBtn.addEventListener('click', () => { 196 | if (searchInput.value === '') { 197 | //Don't allow show error and return 198 | errorBox.style.display = "block"; 199 | errorBox.innerHTML = "Value cannot be blank!"; 200 | return; 201 | } 202 | if (!bst) { 203 | errorBox.style.display = "block"; 204 | errorBox.innerHTML = "Tree is empty!"; 205 | return; 206 | } 207 | errorBox.style.display = "none"; 208 | bst.search(parseInt(searchInput.value)); 209 | }); 210 | randomBstBtn.addEventListener('click', () => generateRandomBst()) 211 | resetBtn.addEventListener('click', () => bst.reset()); 212 | 213 | -------------------------------------------------------------------------------- /stack.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
32 |

33 | STACK 34 |

35 |
36 | 37 | 38 |
39 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |
62 | 66 |
67 |
68 | 69 | 72 | 73 | 75 | 76 | 77 | 78 | 79 | 80 |
81 |
82 | 86 | 89 |
90 |

91 | A Stack is a linear data structure that follows the LIFO (Last-In-First-Out) principle.In other 92 | words, a stack can be defined as a container in which insertion and deletion can be done from the 93 | one end known as the top of the stack. 94 |

95 |
96 |

97 | Time complexity : O(1) 98 |

99 |
100 |
101 | 102 |
103 |
104 |
105 | 106 |
107 | 108 |
109 | 110 | 111 |
112 | 113 |
114 | 115 |
116 |
117 |
118 | 119 |
120 | 121 |
122 | 123 | 124 |
125 |
126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /js/datastructureControllers/queue/priorityqueue/UnsortedPriorityQueue.js: -------------------------------------------------------------------------------- 1 | class UnsortedPriorityQueue { 2 | head = null; 3 | tail = null; 4 | speed = 300; 5 | 6 | isEmpty = () => { 7 | if(this.tail == null && this.head == null){ 8 | return true; 9 | } 10 | return false; 11 | } 12 | 13 | enqueue = async (key, value) => { 14 | if (parseInt(key) < 1 || parseInt(key) > 99) { 15 | info.getElementsByTagName('p')[0].innerHTML = "Key must be from 1 to 99!" 16 | info.style.display = 'block' 17 | return; 18 | } 19 | if (parseInt(value) < -99 || parseInt(value) > 99) { 20 | info.getElementsByTagName('p')[0].innerHTML = "Value must be from -99 to 99!" 21 | info.style.display = 'block' 22 | return; 23 | } 24 | if (key == '' || value == '') { 25 | info.getElementsByTagName('p')[0].innerHTML = "Key and value must not be empty!" 26 | info.style.display = 'block' 27 | return; 28 | } 29 | let node = new Node(key, value); 30 | if (this.isEmpty()) { 31 | this.head = node; 32 | this.tail = node; 33 | } else { 34 | this.tail.next = node; 35 | node.previous = this.tail; 36 | } 37 | this.tail = node; 38 | this.generate(); 39 | } 40 | 41 | dequeue = async () => { 42 | if (this.isEmpty()) { 43 | info.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 44 | info.style.display = 'block' 45 | } 46 | let min = Number.MAX_VALUE; 47 | let minNode = new Node(min, null); 48 | let node = this.head; 49 | let count = 0; 50 | let count2 = 0; 51 | while (node !== null) { 52 | await sleep(this.speed); 53 | if (container.children[count]) { 54 | container.children[count].style.backgroundColor = 'blue'; 55 | } 56 | await sleep(this.speed); 57 | if (container.children[count]) { 58 | container.children[count].style.backgroundColor = node.color; 59 | } 60 | if (container.children[count + 1]) { 61 | container.children[count + 1].innerHTML = `

>-<

` 62 | } 63 | await sleep(this.speed); 64 | if (container.children[count + 1]) { 65 | container.children[count + 1].innerHTML = `

<->

`; 66 | } 67 | await sleep(this.speed); 68 | if (parseInt(node.key) < min) { 69 | if (container.children[count]) { 70 | container.children[count].style.backgroundColor = 'lightgreen'; 71 | await sleep(this.speed); 72 | container.children[count].style.backgroundColor = node.color; 73 | } 74 | document.getElementById('peekindex').innerHTML = node.address ? node.address : '-'; 75 | document.getElementById('peekkey').innerHTML = node.key ? node.key : '-'; 76 | document.getElementById('peekindex').style.backgroundColor = node.color ? node.color : '-'; 77 | min = node.key; 78 | minNode = node; 79 | count2 = count; 80 | } 81 | count += 2; 82 | node = node.next; 83 | } 84 | await sleep(this.speed); 85 | if (container.children[count2]) { 86 | container.children[count2].style.backgroundColor = 'red'; 87 | } 88 | await sleep(this.speed); 89 | if (container.children[count2]) { 90 | container.children[count2].style.backgroundColor = minNode.color; 91 | } 92 | if(minNode.previous != null) {minNode.previous.next = minNode.next;} 93 | if(minNode.next != null){minNode.next.previous = minNode.previous;} 94 | if(minNode == this.head){this.head = minNode.next;} 95 | if(minNode == this.tail){this.tail = minNode.previous;} 96 | this.generate(); 97 | return node; 98 | } 99 | 100 | min = () => { 101 | if(this.isEmpty()){ 102 | info.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 103 | info.style.display = 'block' 104 | } 105 | let min = Number.MAX_VALUE; 106 | let minNode = new Node(null, null); 107 | let node = this.head; 108 | while(node !== null){ 109 | if(parseInt(node.key) < min){ 110 | min = node.key; 111 | minNode = node; 112 | } 113 | node = node.next; 114 | } 115 | return minNode; 116 | } 117 | 118 | size = () => { 119 | let count = 0; 120 | let node = this.head; 121 | while(node !== null){ 122 | count+=1; 123 | node = node.next; 124 | } 125 | return count; 126 | } 127 | 128 | createelement = (data) => { 129 | const element = document.createElement('div'); 130 | element.classList.add('sudo-pqueue') 131 | element.style.backgroundColor = data.color; 132 | element.innerHTML = ` 133 |
${data?.previous?.address ? data.previous.address : '-'}
134 |
${data?.key}
135 |
${data?.value}
136 |
${data?.next?.address ? data.next.address : '-'}
137 | `; 138 | return element 139 | } 140 | 141 | inb = () => { 142 | const element = document.createElement('div'); 143 | element.classList.add('pqueue-connect') 144 | element.innerHTML = `

<->

` 145 | return element 146 | } 147 | 148 | generate = () => { 149 | info.style.display = 'none' 150 | document.getElementById('peekindex').innerHTML = this?.min()?.address ? this.min().address : '-'; 151 | document.getElementById('peekkey').innerHTML = this?.min()?.key ? this.min().key : '-'; 152 | document.getElementById('peekindex').style.backgroundColor = this?.min()?.color ? this.min().color : '-'; 153 | document.getElementById('sizearea').innerHTML = this.size(); 154 | container.innerHTML = ''; 155 | let node = this.head; 156 | while(node !== null){ 157 | let element = this.createelement({ 158 | key : node?.key ? node.key : '-', 159 | value : node?.value ? node.value : '-', 160 | next : node?.next, 161 | previous : node?.previous, 162 | color : node?.color 163 | }) 164 | container.append(element) 165 | if(node.next){ 166 | container.append(this.inb()) 167 | } 168 | node = node.next; 169 | } 170 | } 171 | 172 | reset = () => { 173 | this.head = null; 174 | this.tail = null; 175 | container.innerHTML = ''; 176 | } 177 | 178 | randomize = () => { 179 | let value = Math.floor((Math.random() * 99) + 1); 180 | let key = Math.floor((Math.random() * 99) + 1); 181 | this.enqueue(key, value); 182 | } 183 | } 184 | 185 | let unsortedpriorityqueue = new UnsortedPriorityQueue(); -------------------------------------------------------------------------------- /js/algorithmsControllers/sortAlgorithms.js: -------------------------------------------------------------------------------- 1 | function sleep(ms) { 2 | return new Promise(resolve => setTimeout(resolve, ms)); 3 | } 4 | 5 | class SortAlgorithms{ 6 | container = document.getElementById('animation-container') 7 | display = document.getElementById('sort-box') 8 | inf = document.getElementById('queueinfo') 9 | isRepresentation=false; 10 | speed = 600; 11 | length = 40; 12 | 13 | structure = 'queue' 14 | 15 | isFull = () => { 16 | return this.array.length >= this.length; 17 | } 18 | 19 | createElement = (value) => { 20 | if(this.isRepresentation) { 21 | const element = document.createElement('div'); 22 | element.classList.add('queue-representation'); 23 | element.style.height = `${value*6}px`; 24 | return element 25 | } 26 | else { 27 | const element = document.createElement('div'); 28 | element.classList.add(this.structure) 29 | element.innerHTML = `

${value}

` 30 | return element 31 | } 32 | } 33 | 34 | array = new Array(); 35 | sorttype = 'bubble'; 36 | 37 | render(){ 38 | this.display.style.visibility = 'hidden'; 39 | this.container.innerHTML = ''; 40 | for (let i = 0; i < this.array.length; i++) { 41 | this.container.append(this.createElement(this.array[i])); 42 | } 43 | } 44 | 45 | add=(value)=>{ 46 | if(this.isFull()) { 47 | this.inf.getElementsByTagName('p')[0].innerHTML = "Array is full !"; 48 | this.inf.style.display = 'block'; 49 | return; 50 | } 51 | let enqinf = document.getElementById('enqueueinfo') 52 | if(value=="" || value<-99 || value>99) { 53 | value = Math.floor((Math.random() * 99) + 1); 54 | enqinf.getElementsByTagName('p')[0].innerHTML = "Random number is added!" 55 | enqinf.style.display = 'block' 56 | } else{ 57 | enqinf.style.display = 'none' 58 | } 59 | this.array.push(value); 60 | this.render(); 61 | } 62 | 63 | generateRandomArray() { 64 | this.array = new Array(); 65 | for (let i = 0; i < this.length; i++) { 66 | this.add(Math.floor((Math.random() * 99) + 1)); 67 | } 68 | this.render(); 69 | } 70 | 71 | remove(index) { 72 | if (index !== -1) { 73 | this.array.pop(index); 74 | this.container.lastChild.remove(); 75 | } 76 | this.render(); 77 | 78 | } 79 | 80 | async sort() { 81 | if(this.array.length==0) { 82 | this.inf.getElementsByTagName('p')[0].innerHTML = "Please add some elements to the Array !"; 83 | this.inf.style.display = 'block'; 84 | return; 85 | } 86 | switch (this.sorttype) { 87 | case 'bubble': 88 | await this.bubbleSort(); 89 | break; 90 | case 'selection': 91 | await this.selectionSort(); 92 | break; 93 | case 'insertion': 94 | await this.insertionSort(); 95 | break; 96 | } 97 | this.render() 98 | this.display.style.visibility = 'visible'; 99 | this.display.innerHTML = `

Sorted

` 100 | } 101 | 102 | async bubbleSort() { 103 | let i, j, temp; 104 | for (i = 0; i < this.array.length; i++) { 105 | for (j = 0; j < this.array.length - i - 1; j++) { 106 | if (this.array[j] > this.array[j + 1]) { 107 | this.container.children[j].style.backgroundColor = 'orange'; 108 | this.container.children[j+1].style.backgroundColor = 'lightgreen'; 109 | await sleep(this.speed/2); 110 | temp = this.array[j]; 111 | this.array[j] = this.array[j + 1]; 112 | this.array[j + 1] = temp; 113 | this.render(); 114 | this.container.children[j].style.backgroundColor = 'lightgreen'; 115 | this.container.children[j+1].style.backgroundColor = 'orange'; 116 | await sleep(this.speed/2); 117 | this.container.children[j].style.backgroundColor = '#24b4a6df'; 118 | this.container.children[j+1].style.backgroundColor = '#24b4a6df'; 119 | 120 | } 121 | } 122 | } 123 | } 124 | 125 | async selectionSort() { 126 | let i, j, min, temp; 127 | for (i = 0; i < this.array.length; i++) { 128 | min = i; 129 | for (j = i + 1; j < this.array.length; j++) { 130 | if (this.array[j] < this.array[min]) { 131 | min = j; 132 | } 133 | } 134 | await sleep(this.speed/3); 135 | this.render(); 136 | this.container.children[min].style.backgroundColor = 'orange'; 137 | this.container.children[i].style.backgroundColor = 'lightgreen'; 138 | await sleep(this.speed/3); 139 | temp = this.array[i]; 140 | this.array[i] = this.array[min]; 141 | this.array[min] = temp; 142 | this.render(); 143 | this.container.children[min].style.backgroundColor = 'lightgreen'; 144 | this.container.children[i].style.backgroundColor = 'orange'; 145 | await sleep(this.speed/3); 146 | } 147 | } 148 | 149 | async insertionSort() { 150 | let i, j, temp; 151 | for (i = 1; i < this.array.length; i++) { 152 | this.container.children[i].style.backgroundColor = 'orange'; 153 | temp = this.array[i]; 154 | this.display.style.visibility = 'visible'; 155 | this.display.innerHTML = `

Temp-> ${temp}

` 156 | j = i - 1; 157 | while (j >= 0 && this.array[j] > temp) { 158 | this.display.innerHTML = `

Temp-> ${temp}

` 159 | this.container.children[i].style.backgroundColor = 'orange'; 160 | if(i>=j+2) { 161 | this.container.children[j + 1].style.backgroundColor = 'lightblue'; 162 | if(!this.isRepresentation) { 163 | this.container.children[j + 2].text = `

${temp}

`; 164 | } 165 | } 166 | this.display.style.visibility = 'visible'; 167 | this.array[j + 1] = this.array[j]; 168 | this.container.children[j + 1].style.backgroundColor = 'lightblue'; 169 | if(!this.isRepresentation) { 170 | this.container.children[j + 1].innerHTML = `

${temp}

`; 171 | } 172 | j = j - 1; 173 | await sleep(this.speed/3); 174 | this.render(); 175 | } 176 | this.array[j + 1] = temp; 177 | this.container.children[i].style.backgroundColor = 'orange'; 178 | if(!this.isRepresentation) { 179 | this.container.children[j + 1].innerHTML = `

${temp}

`; 180 | } 181 | this.container.children[j + 1].style.backgroundColor = 'lightblue'; 182 | await sleep(this.speed/3); 183 | this.container.children[j + 1].style.backgroundColor = 'green'; 184 | await sleep(this.speed/3); 185 | this.render() 186 | } 187 | } 188 | 189 | reset() { 190 | this.array = new Array(); 191 | this.container.innerHTML = ''; 192 | } 193 | } 194 | 195 | let sortAlgorithms = new SortAlgorithms(); -------------------------------------------------------------------------------- /js/datastructureControllers/queue/priorityqueue/SortedPriorityQueue.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(key, value, color = getRandomColor(), address = generateRandomTwoLetterWord()) { 3 | this.key = key; 4 | this.value = value; 5 | this.next = null; 6 | this.previous = null; 7 | this.address = address; 8 | this.color=color; 9 | } 10 | } 11 | 12 | function sleep(ms) { 13 | return new Promise(resolve => setTimeout(resolve, ms)); 14 | } 15 | 16 | function getRandomColor() { 17 | let color = "#"; 18 | for (let i = 0; i < 3; i++) 19 | color += ("0" + Math.floor(Math.random() * Math.pow(16, 2) / 2).toString(16)).slice(-2); 20 | return color; 21 | } 22 | 23 | const addresses = []; 24 | 25 | function generateRandomTwoLetterWord(){ 26 | const result = Math.random().toString(36).substring(2,5); 27 | for (let i = 0; i < addresses.length; i++) { 28 | if(addresses[i] == result) { 29 | return generateRandomTwoLetterWord(); 30 | } 31 | } 32 | console.log(addresses) 33 | addresses.push(result); 34 | return result; 35 | } 36 | 37 | const container = document.getElementById('animation-container') 38 | const info = document.getElementById('info') 39 | 40 | class SortedPriorityQueue { 41 | isSorted = false; 42 | head = null; 43 | tail = null; 44 | speed = 300; 45 | 46 | isEmpty = () => { 47 | if(this.tail == null && this.head == null){ 48 | return true; 49 | } 50 | return false; 51 | } 52 | 53 | enqueue = async (key, value) => { 54 | if (parseInt(key) < 1 || parseInt(key) > 99) { 55 | info.getElementsByTagName('p')[0].innerHTML = "Key must be from 1 to 99!" 56 | info.style.display = 'block' 57 | return; 58 | } 59 | if (parseInt(value) < -99 || parseInt(value) > 99) { 60 | info.getElementsByTagName('p')[0].innerHTML = "Value must be from -99 to 99!" 61 | info.style.display = 'block' 62 | return; 63 | } 64 | if (key == '' || value == '') { 65 | info.getElementsByTagName('p')[0].innerHTML = "Key and value must not be empty!" 66 | info.style.display = 'block' 67 | return; 68 | } 69 | let start = this.head; 70 | let temp = new Node(key, value); 71 | if (this.isEmpty()) { 72 | this.head = temp; 73 | this.tail = temp; 74 | } else { 75 | let count = 0; 76 | if (this.head.key > key) { 77 | temp.next = this.head; 78 | this.head.previous = temp; 79 | this.head = temp; 80 | } else { 81 | while (start != null) { 82 | await sleep(this.speed); 83 | if(container.children[count]) { 84 | container.children[count].style.backgroundColor = 'lightgreen'; 85 | } 86 | await sleep(this.speed); 87 | if(container.children[count]) { 88 | container.children[count].style.backgroundColor = start.color; 89 | } 90 | if(container.children[count+1]) { 91 | container.children[count + 1].innerHTML = `

>-<

` 92 | } 93 | await sleep(this.speed); 94 | if(container.children[count+1]) { 95 | container.children[count+1].innerHTML = `

<->

`; 96 | } 97 | await sleep(this.speed); 98 | if (Number.parseInt(start.key) > Number.parseInt(temp.key)) { 99 | temp.next = start; 100 | temp.previous = start.previous; 101 | start.previous.next = temp; 102 | start.previous = temp; 103 | this.generate(); 104 | return; 105 | } 106 | count+=2; 107 | start = start.next; 108 | } 109 | this.tail.next = temp; 110 | temp.previous = this.tail; 111 | this.tail = temp; 112 | } 113 | } 114 | this.generate(); 115 | return; 116 | } 117 | 118 | dequeue = async () => { 119 | console.log("sorted dequeue") 120 | if (this.isEmpty()) { 121 | info.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 122 | info.style.display = 'block' 123 | return null; 124 | } 125 | container.children[0].style.backgroundColor = 'red'; 126 | await sleep(this.speed); 127 | let temp = this.head 128 | if (temp !== null) { 129 | this.head = temp.next; 130 | if (this.head !== null) { 131 | this.head.previous = null; 132 | } else { 133 | this.tail = null; 134 | this.head = null; 135 | } 136 | } 137 | this.size(); 138 | this.generate(); 139 | return temp; 140 | } 141 | 142 | min = () => { 143 | if(this.isEmpty()){ 144 | info.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 145 | info.style.display = 'block' 146 | return null; 147 | } 148 | return this.head; 149 | } 150 | 151 | size = () => { 152 | let count = 0; 153 | let node = this.head; 154 | while(node !== null){ 155 | count+=1; 156 | node = node.next; 157 | } 158 | return count; 159 | } 160 | 161 | createelement = (data) => { 162 | const element = document.createElement('div'); 163 | element.classList.add('sudo-pqueue') 164 | element.style.backgroundColor = data.color; 165 | element.innerHTML = ` 166 |
${data?.previous?.address ? data.previous.address : '-'}
167 |
${data?.key}
168 |
${data?.value}
169 |
${data?.next?.address ? data.next.address : '-'}
170 | `; 171 | return element 172 | } 173 | 174 | inb = () => { 175 | const element = document.createElement('div'); 176 | element.classList.add('pqueue-connect') 177 | element.innerHTML = `

<->

` 178 | return element 179 | } 180 | 181 | 182 | generate = () => { 183 | info.style.display = 'none' 184 | document.getElementById('peekindex').innerHTML = this?.head?.address ? this.head.address : '-'; 185 | document.getElementById('peekkey').innerHTML = this?.head?.key ? this.head.key : '-'; 186 | document.getElementById('peekindex').style.backgroundColor = this?.head?.color ? this.head.color : ''; 187 | document.getElementById('sizearea').innerHTML = this.size(); 188 | container.innerHTML = ''; 189 | let node = this.head; 190 | while(node !== null){ 191 | let element = this.createelement({ 192 | key : node?.key ? node.key : '-', 193 | value : node?.value ? node.value : '-', 194 | next : node?.next, 195 | previous : node?.previous, 196 | color : node?.color 197 | }) 198 | container.append(element) 199 | if(node.next){ 200 | container.append(this.inb()) 201 | } 202 | node = node.next; 203 | } 204 | } 205 | 206 | 207 | reset = () => { 208 | this.head = null; 209 | this.tail = null; 210 | this.generate(); 211 | } 212 | 213 | randomize = () => { 214 | let value = Math.floor((Math.random() * 99) + 1); 215 | let key = Math.floor((Math.random() * 99) + 1); 216 | this.enqueue(key, value); 217 | } 218 | 219 | } 220 | 221 | let sortedPriorityQueue = new SortedPriorityQueue(); -------------------------------------------------------------------------------- /binary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | DSA VISUALIZATION 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
31 |

32 | BINARY SEARCH TREE 33 |

34 |
35 | 36 | 37 |
38 | 54 | 55 | 56 | 57 |
58 |
59 |
60 | 65 |
66 |
67 | 68 | 74 | 75 | 78 | 79 | 81 | 82 | 84 | 85 | 86 | 88 | 89 | 92 | 95 |
96 |
97 | 102 | 105 |
106 |

107 | Binary Search Tree is a node-based binary tree data structure which has the 108 | following properties: 109 | The left subtree of a node contains only nodes with keys lesser than the node’s 110 | key. 111 | The right subtree of a node contains only nodes with keys greater than the 112 | node’s key. 113 | The left and right subtree each must also be a binary search tree. 114 |

115 |
116 |

117 |

Time Complexity
118 | Searching: time complexity is O(h) where h is height of BST. 119 | Insertion: O(h) 120 | Deletion: O(h). 121 |

122 |
123 |
124 |
125 |
126 |
127 | 128 | 129 |
130 | 131 |
132 | 133 | 134 |
135 | 137 | 138 |
139 | 140 |
141 |
142 | 143 | 144 |
145 |
146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /doublylinklist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
31 |

32 | DOUBLY LINKED LIST 33 |

34 |
35 | 36 | 37 |
38 | 54 | 55 | 56 | 57 | 58 |
59 |
60 |
61 | 65 |
66 |
67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 |
80 |
81 | 85 | 88 |
89 |

90 | Doubly linked list is a complex type of linked list in which a node contains a pointer to the previous as well as the next node in the sequence. Therefore, in a doubly linked list, a node consists of three parts: node data, pointer to the next node in sequence (next pointer) , pointer to the previous node (previous pointer). 91 |

92 |
93 |

94 | Time complexity: 95 |

    96 |
  • Insertion At Start,End: O(1)
  • 97 |
  • Insertion At Middle: O(n)
  • 98 |
  • Deletion At Start,End : O(1)
  • 99 |
  • Deletion At Middle: O(n)
  • 100 |
  • Search: O(n)
  • 101 |
  • Traversal: O(n)
  • 102 |
103 |

104 |
105 |
106 | 107 |
108 |
109 |
110 | 111 |
112 | 113 |
114 | 115 | 116 |
117 | 118 |
119 |
120 | 121 |

Current Process : -

None

122 |

Current Node Memory : -

None

123 |

Current Node Data : -

None

124 |

Current Head Memory : -

None

125 |

Current Tail Memory: -

None

126 | 127 | 128 | 129 |
130 | 131 | 132 |
133 |
-
134 |
--
135 |
-
136 |
137 | 138 |
139 | 140 |
141 | 142 | 143 | 144 |
145 | 146 | 147 | 148 |
149 | 150 | 151 |
152 |
153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /array.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
32 |

33 | ARRAY 34 |

35 |
36 | 37 | 38 |
39 | 55 | 56 | 57 | 58 | 59 | 60 |
61 |
62 |
63 | 66 |
67 |
68 | 69 | 70 | 71 | 72 | 73 |
74 | 75 | 76 |
77 | 78 | 79 | 80 |
81 | 82 | 83 |
84 | 85 | 86 | 87 |
88 | 89 | 90 |
91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |
101 |
102 | 106 | 109 |
110 |

111 | An Array is a data structure that contains a group of elements. Typically these elements are all of the same data type, such as an integer or string. Arrays are commonly used in computer programs to organize data so that a related set of values can be easily sorted or searched. 112 |

113 |
114 |

115 | Time complexity : 116 |
Insertion : O(n) 117 |
Deletion : O(n) 118 |
Replace : O(1) 119 |
Search : O(n) 120 |
Reverse : O(n) 121 | 122 |

123 |
124 |
125 | 126 |
127 |
128 |
129 |
130 | 131 |
132 | 133 | 134 | 135 |
136 | 137 | 138 |
139 | 140 |
141 | 142 | 143 |
144 | 145 | 146 |
147 |
148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /js/datastructureControllers/queue/queue.js: -------------------------------------------------------------------------------- 1 | const container = document.getElementById('animation-container') 2 | const structure = 'queue' 3 | 4 | const createElement = (data) => { 5 | const element = document.createElement('div'); 6 | element.classList.add(structure) 7 | element.style.backgroundColor=data?.color 8 | element.innerHTML = `

${data?.value}

` 9 | return element 10 | } 11 | 12 | 13 | const getRandomColor = () => { 14 | var trans = '0.3'; 15 | var color = 'rgba('; 16 | for (var i = 0; i < 3; i++) { 17 | color += Math.floor(Math.random() * 255) + ','; 18 | } 19 | color += trans + ')'; 20 | return color; 21 | } 22 | 23 | const wrapFR = (value, isfront) => { 24 | if(isfront) { 25 | return `

Front is ${value}

` 26 | } 27 | return `

Rear is ${value}

` 28 | } 29 | 30 | 31 | class Queue { 32 | dataArray = new Array(); 33 | front=-1; 34 | rear=-1; 35 | length=19; 36 | detailed=false; 37 | isdeque=false; 38 | 39 | qf = document.getElementById('queueFront') 40 | qr = document.getElementById('queueRear') 41 | inf = document.getElementById('queueinfo') 42 | 43 | enqueue=(value)=>{ 44 | 45 | if(this.isFull()) { 46 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Overflow! Queue is full!" 47 | this.inf.style.display = 'block' 48 | } 49 | else { 50 | let enqinf = document.getElementById('enqueueinfo') 51 | if(value=="" || value<-99 || value>99) { 52 | enqinf.getElementsByTagName('p')[0].innerHTML = "Random number is taken for Enqueue!" 53 | enqinf.style.display = 'block' 54 | value = Math.floor((Math.random() * 99) + 1); 55 | } else { 56 | enqinf.style.display = 'none' 57 | } 58 | this.inf.style.display = 'none' 59 | const bg_color = getRandomColor() 60 | this.qr.innerHTML = wrapFR(value, false) 61 | this.qr.style.backgroundColor = bg_color 62 | container.append(createElement({'value': value, 'color': bg_color})) 63 | this.dataArray.push(value) 64 | if (this.detailed){ 65 | this.qf.innerHTML = wrapFR(this.dataArray[this.front],true) 66 | } 67 | if (this.rear == -1) { 68 | this.front = 0; 69 | this.qf.innerHTML = wrapFR(this.dataArray[this.front],true) 70 | this.rear = 0; 71 | this.qf.style.display = 'flex' 72 | this.qr.style.display = 'flex' 73 | } else { 74 | this.rear++; 75 | } 76 | } 77 | 78 | } 79 | 80 | enqueueFront=(value)=>{ 81 | if(this.isFull()) { 82 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Overflow! Queue is full!" 83 | this.inf.style.display = 'block' 84 | } 85 | else { 86 | let enqinf = document.getElementById('enqueueinfo') 87 | if(value=="" || value<-99 || value>99) { 88 | enqinf.getElementsByTagName('p')[0].innerHTML = "Random number is taken for Enqueue!" 89 | enqinf.style.display = 'block' 90 | value = Math.floor((Math.random() * 99) + 1); 91 | } else { 92 | enqinf.style.display = 'none' 93 | } 94 | this.inf.style.display = 'none' 95 | const bg_color = getRandomColor() 96 | this.qf.innerHTML = wrapFR(value, true) 97 | this.qf.style.backgroundColor = bg_color 98 | container.prepend(createElement({'value': value, 'color': bg_color})) 99 | this.dataArray.unshift(value) 100 | if (this.rear == -1) { 101 | this.rear = 0; 102 | this.qf.innerHTML = wrapFR(this.dataArray[this.rear],true) 103 | this.front = 0; 104 | this.qf.style.display = 'flex' 105 | this.qr.style.display = 'flex' 106 | } else { 107 | this.rear++; 108 | } 109 | } 110 | } 111 | 112 | dequeue=()=>{ 113 | if(this.isEmpty()) { 114 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 115 | this.inf.style.display = 'block' 116 | } else { 117 | this.inf.style.display = 'none' 118 | const list = document.getElementsByClassName(structure) 119 | if(this.detailed){ 120 | if(list[this.front]) { 121 | list[this.front].style.opacity = '0.1' 122 | } 123 | if (this.dataArray[this.front+1]) { 124 | this.qf.innerHTML = wrapFR(this.dataArray[this.front+1],true) 125 | } else { 126 | this.qf.innerHTML = wrapFR(-1,true) 127 | this.qr.innerHTML = wrapFR(-1,false) 128 | } 129 | this.front++; 130 | }else{ 131 | list[0].remove() 132 | this.dataArray?.pop() 133 | this.qf.innerHTML = wrapFR(list[0]?.getElementsByTagName('p')[0]?.innerHTML || -1,true) 134 | this.qf.style.backgroundColor = list[0]?.style?.backgroundColor 135 | this.front++; 136 | } 137 | } 138 | if(this.dataArray.length == 0 || this.front>this.rear+1) { 139 | if(!this.detailed) { 140 | this.front = -1; 141 | this.rear = -1; 142 | } else{ 143 | this.front--; 144 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 145 | this.inf.style.display = 'block' 146 | } 147 | console.log(this.dataArray.length,this.length,"this") 148 | this.qf.innerHTML = wrapFR(-1,true) 149 | this.qr.innerHTML = wrapFR(-1,false) 150 | } 151 | } 152 | 153 | dequeueRear=()=> { 154 | if (this.isEmpty()) { 155 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 156 | this.inf.style.display = 'block' 157 | } else { 158 | this.inf.style.display = 'none' 159 | const list = document.getElementsByClassName(structure) 160 | if (this.detailed) { 161 | if (list[this.rear]) { 162 | list[this.rear].style.opacity = '0.1' 163 | } 164 | if (this.dataArray[this.rear - 1]) { 165 | this.qr.innerHTML = wrapFR(this.dataArray[this.rear - 1], false) 166 | } else { 167 | this.qf.innerHTML = wrapFR(-1, true) 168 | this.qr.innerHTML = wrapFR(-1, false) 169 | } 170 | this.rear--; 171 | } else { 172 | list[list.length - 1].remove() 173 | this.dataArray?.pop() 174 | this.qr.innerHTML = wrapFR(list[list.length - 1]?.getElementsByTagName('p')[0]?.innerHTML || -1, false) 175 | this.qr.style.backgroundColor = list[list.length - 1]?.style?.backgroundColor 176 | this.rear--; 177 | } 178 | } 179 | if (this.dataArray.length == 0 || this.front > this.rear + 1) { 180 | if (!this.detailed) { 181 | this.front = -1; 182 | this.rear = -1; 183 | } else { 184 | this.rear--; 185 | this.inf.getElementsByTagName('p')[0].innerHTML = "Queue Underflow! Queue is empty!" 186 | this.inf.style.display = 'block' 187 | } 188 | this.qf.innerHTML = wrapFR(-1, true) 189 | this.qr.innerHTML = wrapFR(-1, false) 190 | } 191 | } 192 | 193 | isFull=()=>{ 194 | if(this.dataArray.length > this.length) { 195 | return true; 196 | } 197 | return false; 198 | } 199 | 200 | isEmpty=()=>{ 201 | if(this.front == -1) { 202 | this.qf.innerHTML = wrapFR(-1,true) 203 | this.qr.innerHTML = wrapFR(-1,false) 204 | return true; 205 | } 206 | return false; 207 | } 208 | 209 | reset = () => { 210 | this.inf.style.display = 'none' 211 | this.qf.innerHTML = wrapFR(-1,true) 212 | this.qr.innerHTML = wrapFR(-1,false) 213 | container.innerHTML = '' 214 | this.dataArray = new Array(); 215 | this.front=-1; 216 | this.rear=-1; 217 | } 218 | 219 | toggledeque = () => { 220 | if(this.isdeque) { 221 | this.qf.style.display = 'flex' 222 | this.qr.style.display = 'flex' 223 | document.getElementById('dequeuerearbutton').style.display = 'block' 224 | document.getElementById('enqueuefrontbutton').style.display = 'block' 225 | document.getElementById('enqueuebuttongroup').classList.add('grid-cols-2') 226 | document.getElementById('dequeuebuttongroup').classList.add('grid-cols-2') 227 | } else { 228 | this.qf.style.display = 'none' 229 | this.qr.style.display = 'none' 230 | document.getElementById('dequeuerearbutton').style.display = 'none' 231 | document.getElementById('enqueuefrontbutton').style.display = 'none' 232 | document.getElementById('enqueuebuttongroup').classList.remove('grid-cols-2') 233 | document.getElementById('dequeuebuttongroup').classList.remove('grid-cols-2') 234 | } 235 | } 236 | } 237 | 238 | let queue = new Queue() 239 | 240 | 241 | 242 | 243 | 244 | -------------------------------------------------------------------------------- /search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | 20 |
21 | 22 |
23 |

24 | SEARCH ALGORITHMS 25 |

26 |
27 |
28 | 44 | 45 |
46 |
47 | 48 |
49 | 56 |
57 |
58 | 59 | 63 | 67 | 71 | 74 | 78 | 82 | 86 |
87 |
88 | 92 | 95 |
96 |

97 | Linear search is also called as sequential search algorithm. 98 | It is the simplest searching algorithm. In Linear search, we simply traverse the list 99 | completely and match each element of the list with the item whose location is to be found. 100 | If the match is found, then the location of the item is returned; otherwise, the algorithm returns NULL. 101 |

102 |
103 | 106 |
107 |

108 | Binary Search is a searching algorithm for finding an element's position in a sorted array. 109 | In this approach, the element is always searched in the middle of a portion of an array. 110 |

111 |

112 | Binary search is faster than linear search. In case of binary search, array elements must be in ascending order. 113 |

114 |
115 |
116 | × 117 |

Navigate through sections to change simulation.

118 |
119 |
120 |
121 |
122 |
123 |
124 | 125 |
126 | 129 |
130 |
131 |
132 |
Seek to change Speed
133 |
134 |
135 | 136 |
137 |
138 | 139 | 140 | 141 | 142 | 159 | 160 | -------------------------------------------------------------------------------- /singlylinklist.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
31 |

32 | SINGLY LINKED LIST 33 |

34 |
35 | 36 | 37 |
38 | 54 | 55 | 56 | 57 | 58 |
59 |
60 |
61 | 65 |
66 |
67 | 68 | 69 | 70 | 71 | 72 | 73 | 76 | 77 | 78 |
79 | 80 | 81 | 82 | 83 | 84 |
85 |
86 | 90 | 93 |
94 |

95 | A Singlely Linked List is a linear data structure in which the elements are not connected to each other. 96 | Singly linked list can be defined as the collection of ordered set of elements. 97 | The number of elements may vary according to need of the program. A node in the singly linked list consist of two parts: data part and link part. 98 | Data part of the node stores actual information that is to be represented by the node while the link part of the node stores the address of its immediate successor. 99 |

100 |
101 |

102 | Time complexity 103 |

    104 |
  • Insertion At Start: O(1)
  • 105 |
  • Insertion : O(n)
  • 106 |
  • Deletion At Start: O(1)
  • 107 |
  • Deletion : O(n)
  • 108 |
  • Search: O(n)
  • 109 |
  • Traversal: O(n)
  • 110 |
111 |

112 |
113 |
114 | 115 |
116 |
117 |
118 |
119 | 120 |
121 | 122 | 123 |
124 | 125 |
126 |
127 | 128 |

Current Process : -

None

129 |

Current Node Memory : -

None

130 |

Current Node Data : -

None

131 |

Current Head Memory : -

None

132 | 133 | 134 | 135 |
136 | 137 | 138 |
139 |
--
140 |
-
141 |
142 | 143 |
144 | 145 |
146 | 147 | 148 | 149 |
150 | 151 | 152 | 153 |
154 | 155 | 156 |
157 |
158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /sort.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 |
19 | 20 |
21 |

22 | SORT ALGORITHMS 23 |

24 |
25 |
26 | 42 | 43 |
44 |
45 | 46 |
47 | 54 |
55 |
56 | 57 | 61 | 65 | 69 | 73 | 77 | 81 | 85 |
86 |
87 | 91 | 94 |
95 |

96 | Bubble sort is a sorting algorithm that compares two adjacent elements and swaps them 97 | until they are not in the intended order. 98 | Just like the movement of air bubbles in the water that rise up to the surface, each 99 | element of the array move to the end in each iteration. Therefore, it is called a bubble sort. 100 |

101 |
102 | 105 |
106 |

107 | Insertion sort is a sorting algorithm that places an unsorted element at its suitable place in each iteration. 108 | 109 | Insertion sort works similarly as we sort cards in our hand in a card game. 110 | 111 | We assume that the first card is already sorted then, we select an unsorted card. 112 | If the unsorted card is greater than the card in hand, it is placed on the right otherwise, 113 | to the left. In the same way, other unsorted cards are taken and put in their right place. 114 |

115 |
116 | 119 |
120 |

121 | Selection sort is a sorting algorithm that selects the smallest element from an unsorted 122 | list in each iteration and places that element at the beginning of the unsorted list. 123 |

124 |
125 |
126 | × 127 |

Navigate through sections to change simulation.

128 |
129 |
130 |
131 |
132 |
133 |
134 | 135 |
136 | 139 |
140 |
141 |
142 |
Seek to change Speed
143 |
144 |
145 | 146 |
147 |
148 | 149 | 150 | 151 | 152 | 168 | 169 | -------------------------------------------------------------------------------- /js/datastructureControllers/singleLinkedList.js: -------------------------------------------------------------------------------- 1 | //Container Variable Definition 2 | const container = document.getElementById('animation-container') 3 | const process = document.getElementById('process') 4 | const currentNodeMemory = document.getElementById('currentNodeMemory') 5 | const currentNodeData = document.getElementById('currentNodeData') 6 | const currentHeadMemory = document.getElementById('currentHeadMemory') 7 | const currentTailMemory = document.getElementById('currentTailMemory') 8 | 9 | const nodeShowcase = document.getElementById('nodeShowcase') 10 | const insertButton = document.getElementById('insertButton') 11 | const traverseButton = document.getElementById('traverseButton') 12 | 13 | function showcase_updateData(value){ 14 | nodeShowcase.children[0].innerHTML = value 15 | } 16 | 17 | function showcase_updateNext(value){ 18 | nodeShowcase.children[1].innerHTML = value 19 | } 20 | 21 | 22 | // Create a div in dom for showing nodes of double link list 23 | const createNode = function(currentData, nextData) { 24 | const element = document.createElement('div'); 25 | element.classList.add('node') 26 | 27 | // Current Value 28 | var data = document.createElement('div'); 29 | data.classList.add('data'); 30 | data.classList.add('value'); 31 | data.innerHTML = currentData; 32 | 33 | //Next Address 34 | var next = document.createElement('div'); 35 | next.classList.add('data'); 36 | if( nextData == null) { 37 | nextData.innerHTML = ' - ' 38 | } 39 | else { 40 | next.innerHTML = nextData; 41 | } 42 | 43 | 44 | element.appendChild(data) 45 | element.appendChild(next) 46 | container.append(element) 47 | 48 | } 49 | 50 | const addArrow = function() { 51 | const element = document.createElement('div'); 52 | element.classList.add('arrow-5'); 53 | container.append(element) 54 | } 55 | 56 | const getPointer = function(pointerName) { 57 | const element = document.createElement('div'); 58 | element.classList.add(pointerName); 59 | return element; 60 | } 61 | 62 | 63 | // Pointer animation related information 64 | // move pointer to next node 65 | const movePointerNext = function(pointerName){ 66 | for (let i = 0; i < container.childElementCount; i++) { 67 | // This is two ignore the arrows 68 | if(container.children[i].classList.contains('arrow-5')){ 69 | continue; 70 | } 71 | if(container.children[i].lastChild.classList.contains(pointerName)){ 72 | container.children[i+2].appendChild(getPointer(pointerName)) 73 | container.children[i].removeChild(container.children[i].lastChild) 74 | return; 75 | } 76 | } 77 | } 78 | 79 | const movePointerPrev = function(pointerName){ 80 | for (let i = 0; i < container.childElementCount; i++) { 81 | if(container.children[i].classList.contains('arrow-5')){ 82 | continue; 83 | } 84 | if(container.children[i].lastChild.classList.contains(pointerName)){ 85 | container.children[i].removeChild(container.children[i].lastChild) 86 | container.children[i-2].appendChild(getPointer(pointerName)) 87 | return; 88 | } 89 | } 90 | } 91 | 92 | const getPresentPointerPos = function(pointerName){ 93 | for (let i = 0; i < container.childElementCount; i++) { 94 | if(container.children[i].classList.contains('arrow-5')){ 95 | continue; 96 | } 97 | if(container.children[i].lastChild.classList.contains(pointerName)){ 98 | return i; 99 | } 100 | } 101 | } 102 | 103 | //return a random number between 0-90 104 | const randomNumber = function() { 105 | return Math.floor(Math.random() * (90 - 0 + 1)) + 0; 106 | } 107 | 108 | const disableButton = function(element) { 109 | element.setAttribute("disabled", ""); 110 | } 111 | const enableButton = function(element) { 112 | element.removeAttribute("disabled"); 113 | } 114 | 115 | 116 | 117 | // ------------------------------------ SINGLE LINKED LIST IMPLEMENTATION ------------------------------------ 118 | class node{ 119 | constructor(value){ 120 | this.value = value; 121 | this.next = null; 122 | this.nextMemory= null; 123 | this.myMemory = null; 124 | } 125 | } 126 | 127 | 128 | class SinglyLinkedList { 129 | 130 | constructor() { 131 | this.head = null; 132 | this.tail = null; 133 | this.size = 0; 134 | } 135 | 136 | 137 | //insert in doubly linked List 138 | async insert(value) { 139 | disableButton(insertButton) 140 | updateInfoScreen(process, 'Creating a new node') 141 | await sleep(getDelay()) 142 | const newNode = new node(value); 143 | showcase_updateData(newNode.value) 144 | updateInfoScreen(currentNodeData, value); 145 | 146 | newNode.myMemory = randomNumber(); 147 | updateInfoScreen(currentNodeMemory, newNode.myMemory) 148 | await sleep(getDelay()) 149 | // if list is empty 150 | updateInfoScreen(process, 'Checking if list is empty') 151 | await sleep(getDelay()) 152 | if (this.head === null) { 153 | updateInfoScreen(process, 'List is empty') 154 | await sleep(getDelay()) 155 | updateInfoScreen(process, 'Setting Head to new Node') 156 | this.head = newNode; 157 | updateInfoScreen(currentHeadMemory, newNode.myMemory) 158 | this.size++; 159 | await sleep(getDelay()) 160 | //Psuedo Memory Address 161 | newNode.nextMemory = " - " 162 | updateInfoScreen(process, 'Setting next memory') 163 | await sleep(getDelay()) 164 | // Drawing the node 165 | updateInfoScreen(process, 'Drawing the node') 166 | createNode(value, newNode.nextMemory) 167 | await sleep(getDelay()) 168 | updateInfoScreen(process, 'Node drawn') 169 | //add pointer to the node 170 | container.lastChild.appendChild(getPointer('head')) 171 | enableButton(insertButton) 172 | return; 173 | } 174 | 175 | 176 | // if list is not empty 177 | updateInfoScreen(process, 'List is not empty') 178 | await sleep(getDelay()) 179 | var tmp = this.head; 180 | updateInfoScreen(process, 'Creating a tmp pointer') 181 | await sleep(getDelay()) 182 | container.firstElementChild.appendChild(getPointer('pointer')) 183 | while(true) { 184 | updateInfoScreen(process, 'Checking if tmp is null') 185 | await sleep(getDelay()) 186 | if(tmp.next == null) { 187 | updateInfoScreen(process, 'next is null') 188 | break; 189 | } 190 | updateInfoScreen(process, 'next is not null') 191 | await sleep(getDelay()) 192 | tmp = tmp.next; 193 | updateInfoScreen(currentNodeData, tmp.value) 194 | updateInfoScreen(currentNodeMemory, tmp.myMemory) 195 | await sleep(getDelay()) 196 | updateInfoScreen(process, 'Moving the pointer to next node') 197 | await sleep(getDelay()) 198 | movePointerNext('pointer') 199 | } 200 | updateInfoScreen(process, 'Changing the next of tmp to new node address') 201 | await sleep(getDelay()) 202 | tmp.next = newNode; 203 | this.changePrevMemory(tmp.myMemory) 204 | this.size++; 205 | addArrow(); 206 | updateInfoScreen(process, 'Setting next memory') 207 | await sleep(getDelay()) 208 | // Drawing the node 209 | updateInfoScreen(process, 'Drawing the node') 210 | createNode(value, ' - ') 211 | await sleep(getDelay()) 212 | movePointerNext('pointer') 213 | await sleep(getDelay()) 214 | container.lastChild.removeChild(container.lastChild.lastChild) 215 | updateInfoScreen(process, 'Deleting the temp pointer') 216 | 217 | await sleep(getDelay()) 218 | updateInfoScreen(process, 'Done') 219 | enableButton(insertButton) 220 | return; 221 | } 222 | 223 | //insert at index in single linked list 224 | insertAt() { 225 | 226 | } 227 | 228 | 229 | //traverse the list 230 | async traverse() { 231 | disableButton(traverseButton) 232 | var tmp = this.head; 233 | updateInfoScreen(process, 'Creating a tmp pointer') 234 | await sleep(getDelay()) 235 | container.firstElementChild.appendChild(getPointer('pointer')) 236 | while(true) { 237 | updateInfoScreen(process, 'Checking if tmp is null') 238 | await sleep(getDelay()) 239 | if(tmp.next == null) { 240 | updateInfoScreen(process, 'next is null') 241 | break; 242 | } 243 | movePointerNext('pointer') 244 | updateInfoScreen(process, 'next is not null') 245 | await sleep(getDelay()) 246 | updateInfoScreen(process, 'Moving the pointer to next node') 247 | tmp = tmp.next; 248 | updateInfoScreen(currentNodeData, tmp.value) 249 | updateInfoScreen(currentNodeMemory, tmp.myMemory) 250 | await sleep(getDelay()) 251 | 252 | } 253 | container.lastChild.removeChild(container.lastChild.lastChild) 254 | updateInfoScreen(process, 'Deleting the temp pointer') 255 | 256 | await sleep(getDelay()) 257 | updateInfoScreen(process, 'Done') 258 | enableButton(traverseButton) 259 | return; 260 | 261 | } 262 | 263 | // CHAINING THE MEMORY 264 | changePrevMemory(memory){ 265 | container.lastChild.children[1].innerHTML = memory 266 | } 267 | 268 | reset(){ 269 | this.head = null; 270 | this.tail = null; 271 | this.size = 0; 272 | container.innerHTML = "" ; 273 | } 274 | 275 | 276 | } 277 | 278 | 279 | 280 | const sll = new SinglyLinkedList() 281 | 282 | //get Delay Value 283 | function getDelay() { 284 | return document.getElementById('delay').value 285 | } 286 | 287 | // Update The infoScreen 288 | function updateInfoScreen(element, information) { 289 | element.innerHTML = information; 290 | } 291 | 292 | // Util functions 293 | function sleep(ms) { 294 | return new Promise( 295 | resolve => setTimeout(resolve, ms) 296 | ); 297 | } 298 | 299 | // Preserving the -------------------------------------------------------------------------------- /priorityqueue.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | DSA VISUALIZATION 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 |
19 | 20 |
21 |

22 | PRIORITY QUEUE 23 |

24 |
25 |
26 | 42 | 43 |
44 |
45 |
46 | 53 |
54 |
55 | 56 | 60 | 64 | 71 | 75 | 79 | 83 |
84 |
85 | 89 | 90 | 93 |
94 |

95 | An unsorted priority queue is one in which we insert at the end and remove elements 96 | based on priority(i,e; smallest value in the queue). The unsorted priority queue 97 | makes adding very fast - add operations are O(1), because items are just added to 98 | the end of the list, in no particular order. 99 |

100 |
101 | 102 | 105 |
106 |
107 |

108 | A sorted priority queue is one in which we insert at the position and remove elements 109 | based on priority(i,e; smallest value in the queue). The sorted priority queue 110 | makes deleting and finding minimum value very fast - delete and peek operations are O(1), because items are just deleted from 111 | the end of the list, in no particular order. 112 |

113 |
114 |
115 |
116 | × 117 |

Navigate through sections to change simulation.

118 |
119 | 120 |
121 |
122 |
123 |
124 |
125 | 126 |
127 |
128 |
129 |
MIN
130 |
-
131 |
-
132 |
133 |
134 |
LEN
135 |
-
136 |
137 |
138 |
139 |
140 |
141 |
Seek to change Speed
142 |
143 |
144 | 145 |
146 |
147 | 148 | 149 | 150 | 151 | 152 | 172 | 173 | -------------------------------------------------------------------------------- /js/datastructureControllers/doubleLinkedList.js: -------------------------------------------------------------------------------- 1 | //imports 2 | import { sleep } from "../utils.js" 3 | 4 | //Container Variable Definition 5 | const container = document.getElementById('animation-container') 6 | const process = document.getElementById('process') 7 | const currentNodeMemory = document.getElementById('currentNodeMemory') 8 | const currentNodeData = document.getElementById('currentNodeData') 9 | const currentHeadMemory = document.getElementById('currentHeadMemory') 10 | const currentTailMemory = document.getElementById('currentTailMemory') 11 | 12 | const nodeShowcase = document.getElementById('nodeShowcase') 13 | const insertButton = document.getElementById('insertButton') 14 | const traverseFromBackButton = document.getElementById('traverseFromBack') 15 | const traverseFromFrontButton = document.getElementById('traverseFromFront') 16 | 17 | //Controller Buttons 18 | const insertBtnController = document.getElementById('insertButton') 19 | const traverseFromBackBtnController = document.getElementById('traverseFromBack') 20 | const traverseFromFrontBtnController = document.getElementById('traverseFromFront') 21 | const resetBtnController = document.getElementById('resetButton') 22 | 23 | function showcase_updateData(value){ 24 | nodeShowcase.children[1].innerHTML = value 25 | } 26 | function showcase_updatePrev(value){ 27 | nodeShowcase.children[0].innerHTML = value 28 | } 29 | function showcase_updateNext(value){ 30 | nodeShowcase.children[2].innerHTML = value 31 | } 32 | 33 | 34 | // Create a div in dom for showing nodes of double link list 35 | const createNode = function(prevData, currentData, nextData) { 36 | const element = document.createElement('div'); 37 | element.classList.add('node') 38 | 39 | // Previous Address 40 | var prev = document.createElement('div'); 41 | prev.classList.add('data'); 42 | prevData == null ? prev.innerHTML = 'NULL' : prev.innerHTML = prevData; 43 | 44 | // Current Value 45 | var data = document.createElement('div'); 46 | data.classList.add('data'); 47 | data.classList.add('value'); 48 | data.innerHTML = currentData; 49 | 50 | //Next Address 51 | var next = document.createElement('div'); 52 | next.classList.add('data'); 53 | !nextData ? nextData.innerHTML = ' - ' : next.innerHTML = nextData; 54 | 55 | element.appendChild(prev) 56 | element.appendChild(data) 57 | element.appendChild(next) 58 | container.append(element) 59 | 60 | } 61 | 62 | const addArrow = function() { 63 | const element = document.createElement('div'); 64 | element.classList.add('arrow-6'); 65 | container.append(element) 66 | } 67 | 68 | const getPointer = function(pointerName) { 69 | const element = document.createElement('div'); 70 | element.classList.add(pointerName); 71 | return element; 72 | } 73 | 74 | 75 | // Pointer animation related information 76 | // move pointer to next node 77 | const movePointerNext = function(pointerName){ 78 | for (let i = 0; i < container.childElementCount; i++) { 79 | // This is two ignore the arrows 80 | if(container.children[i].classList.contains('arrow-6')){ 81 | continue; 82 | } 83 | if(container.children[i].lastChild.classList.contains(pointerName)){ 84 | container.children[i+2].appendChild(getPointer(pointerName)) 85 | container.children[i].removeChild(container.children[i].lastChild) 86 | return; 87 | } 88 | } 89 | } 90 | const movePointerPrev = function(pointerName){ 91 | for (let i = 0; i < container.childElementCount; i++) { 92 | if(container.children[i].classList.contains('arrow-6')){ 93 | continue; 94 | } 95 | if(container.children[i].lastChild.classList.contains(pointerName)){ 96 | container.children[i].removeChild(container.children[i].lastChild) 97 | container.children[i-2].appendChild(getPointer(pointerName)) 98 | return; 99 | } 100 | } 101 | } 102 | 103 | const disableButton = function(element) { 104 | element.setAttribute("disabled", ""); 105 | } 106 | 107 | const enableButton = function(element) { 108 | element.removeAttribute("disabled"); 109 | } 110 | 111 | //return a random number between 0-90 112 | const randomNumber = function() { 113 | return Math.floor(Math.random() * (90 - 0 + 1)) + 0; 114 | } 115 | 116 | 117 | 118 | 119 | // ------------------------------------ DOUBLY LINKED LIST IMPLEMENTATION ------------------------------------ 120 | class node{ 121 | constructor(value){ 122 | this.value = value; 123 | this.next = null; 124 | this.prev = null; 125 | this.prevMemory = null; 126 | this.nextMemory= null; 127 | this.myMemory = null; 128 | } 129 | } 130 | 131 | 132 | class DoublyLinkedList { 133 | 134 | constructor() { 135 | this.head = null; 136 | this.tail = null; 137 | this.size = 0; 138 | } 139 | 140 | 141 | //insert in doubly linked List 142 | async insert(value) { 143 | 144 | disableButton(insertButton) 145 | updateInfoScreen(process, 'Creating a new node') 146 | await sleep(getDelay()) 147 | const newNode = new node(value); 148 | 149 | showcase_updateData(newNode.value) 150 | updateInfoScreen(currentNodeData, value); 151 | 152 | newNode.myMemory = randomNumber(); 153 | updateInfoScreen(currentNodeMemory, newNode.myMemory) 154 | await sleep(getDelay()) 155 | // if list is empty 156 | updateInfoScreen(process, 'Checking if list is empty') 157 | await sleep(getDelay()) 158 | if (this.head === null) { 159 | updateInfoScreen(process, 'List is empty') 160 | await sleep(getDelay()) 161 | updateInfoScreen(process, 'Setting Head and tail to new node') 162 | this.head = newNode; 163 | this.tail = newNode; 164 | updateInfoScreen(currentHeadMemory, newNode.myMemory) 165 | updateInfoScreen(currentTailMemory, newNode.myMemory) 166 | this.size++; 167 | await sleep(getDelay()) 168 | //Psuedo Memory Address 169 | newNode.nextMemory = " - " 170 | newNode.prevMemory = " - " 171 | showcase_updatePrev(newNode.nextMemory) 172 | showcase_updateNext(newNode.prevMemory) 173 | updateInfoScreen(process, 'Setting next and prev memory') 174 | await sleep(getDelay()) 175 | // Drawing the node 176 | updateInfoScreen(process, 'Drawing the node') 177 | createNode(newNode.prevMemory, value, newNode.nextMemory) 178 | await sleep(getDelay()) 179 | updateInfoScreen(process, 'Node drawn') 180 | //add pointer to the node 181 | container.lastChild.appendChild(getPointer('head')) 182 | container.lastChild.appendChild(getPointer('tail')) 183 | enableButton(insertButton) 184 | return; 185 | } 186 | 187 | 188 | // if list is not empty 189 | updateInfoScreen(process, 'List is not empty') 190 | await sleep(getDelay()) 191 | updateInfoScreen(process, 'Getting Tail Information') 192 | await sleep(getDelay()) 193 | updateInfoScreen(process, 'Setting Tail to new node') 194 | this.tail.nextMemory = newNode.myMemory; 195 | updateInfoScreen(process, 'Setting previous node next memory') 196 | await sleep(getDelay()) 197 | this.changePrevMemory(newNode.myMemory); 198 | await sleep(getDelay()) 199 | updateInfoScreen(process, 'Setting Current Node Prev Memory') 200 | await sleep(getDelay()) 201 | showcase_updatePrev(this.tail.myMemory) 202 | newNode.prevMemory = this.tail.myMemory 203 | this.tail.next = newNode; 204 | newNode.prev = this.tail; 205 | this.tail = newNode; 206 | newNode.nextMemory = " - " 207 | this.size++; 208 | addArrow(); 209 | createNode(newNode.prevMemory, value, newNode.nextMemory) 210 | updateInfoScreen(process, 'Node drawn') 211 | await sleep(getDelay()) 212 | updateInfoScreen(process, 'Changing the tail') 213 | await sleep(getDelay()) 214 | movePointerNext('tail') 215 | updateInfoScreen(currentTailMemory, newNode.myMemory) 216 | updateInfoScreen(process, 'Done') 217 | enableButton(insertButton) 218 | return; 219 | } 220 | 221 | //insert at index 222 | insertAt(value, index) { 223 | if (index > this.size) { 224 | return; 225 | } 226 | if (index === 0) { 227 | this.insert(value); 228 | return; 229 | } 230 | const newNode = new node(value); 231 | let current = this.head; 232 | let count = 0; 233 | while (count < index - 1) { 234 | current = current.next; 235 | count++; 236 | } 237 | newNode.next = current.next; 238 | current.next = newNode; 239 | newNode.prev = current; 240 | newNode.next.prev = newNode; 241 | createNode(5, value, 5); 242 | this.size++; 243 | return; 244 | } 245 | 246 | 247 | //traverse the list 248 | async traverseFromFront() { 249 | disableButton(traverseFromFrontButton) 250 | updateInfoScreen(process, 'Traversing the list') 251 | await sleep(getDelay()) 252 | 253 | updateInfoScreen(process, 'Getting Head Information to temp pointer') 254 | await sleep(getDelay()) 255 | let current = this.head; 256 | container.firstElementChild.appendChild(getPointer('pointer')) 257 | 258 | updateInfoScreen(process, 'Checking if the next node is null') 259 | await sleep(getDelay()) 260 | while (current) { 261 | updateInfoScreen(process, 'The node is not null') 262 | // Setting The data of the current node 263 | updateInfoScreen(process, 'Getting the data of the current node') 264 | await sleep(getDelay()) 265 | updateInfoScreen(currentNodeData, current.value) 266 | updateInfoScreen(currentNodeMemory, current.myMemory) 267 | console.log(current.value); 268 | current = current.next; 269 | await sleep(getDelay()) 270 | updateInfoScreen(process, 'Moving the pointer to the next node') 271 | await sleep(getDelay()) 272 | if(current == null){ 273 | continue 274 | } 275 | movePointerNext('pointer') 276 | } 277 | 278 | updateInfoScreen(process, 'The Node is null') 279 | await sleep(getDelay()) 280 | updateInfoScreen(process, 'Removing temp pointer and terminating traversal') 281 | await sleep(getDelay()) 282 | container.lastChild.removeChild(container.lastChild.lastChild) 283 | enableButton(traverseFromFrontButton) 284 | } 285 | 286 | async traverseFromBack() { 287 | disableButton(traverseFromBackButton) 288 | updateInfoScreen(process, 'Traversing the list') 289 | await sleep(getDelay()) 290 | 291 | updateInfoScreen(process, 'Getting Tail Information to temp pointer') 292 | await sleep(getDelay()) 293 | let current = this.tail; 294 | container.lastElementChild.appendChild(getPointer('pointer')) 295 | 296 | updateInfoScreen(process, 'Checking if the prev node is null') 297 | await sleep(getDelay()) 298 | while (current) { 299 | updateInfoScreen(process, 'The node is not null') 300 | // Setting The data of the current node 301 | updateInfoScreen(process, 'Getting the data of the current node') 302 | await sleep(getDelay()) 303 | updateInfoScreen(currentNodeData, current.value) 304 | updateInfoScreen(currentNodeMemory, current.myMemory) 305 | current = current.prev; 306 | await sleep(getDelay()) 307 | updateInfoScreen(process, 'Moving the pointer to the next node') 308 | await sleep(getDelay()) 309 | if(current == null){ 310 | continue 311 | } 312 | movePointerPrev('pointer') 313 | } 314 | 315 | updateInfoScreen(process, 'The Node is null') 316 | await sleep(getDelay()) 317 | updateInfoScreen(process, 'Removing temp pointer and terminating traversal') 318 | await sleep(getDelay()) 319 | 320 | container.firstElementChild.removeChild(container.firstElementChild.lastChild) 321 | enableButton(traverseFromBackButton) 322 | } 323 | 324 | reset() { 325 | this.head = null; 326 | this.tail = null; 327 | this.size = 0; 328 | container.innerHTML = ''; 329 | updateInfoScreen(process, 'List reset') 330 | updateInfoScreen(currentHeadMemory, ' - ') 331 | updateInfoScreen(currentTailMemory, ' - ') 332 | updateInfoScreen(currentNodeMemory, ' - ') 333 | updateInfoScreen(currentNodeData, ' - ') 334 | 335 | } 336 | 337 | // CHAINING THE MEMORY 338 | changePrevMemory(memory){ 339 | container.lastChild.children[2].innerHTML = memory 340 | } 341 | 342 | 343 | 344 | } 345 | 346 | 347 | 348 | const dll = new DoublyLinkedList() 349 | 350 | //get Delay Value 351 | function getDelay() { 352 | return document.getElementById('delay').value 353 | } 354 | 355 | // Update The infoScreen 356 | function updateInfoScreen(element, information) { 357 | element.innerHTML = information; 358 | } 359 | 360 | 361 | 362 | // Button Event Listners Setup 363 | insertBtnController.addEventListener('click', () => dll.insert(document.getElementById('nodeData').value)) 364 | traverseFromBackBtnController.addEventListener('click', () => dll.traverseFromBack()) 365 | traverseFromFrontBtnController.addEventListener('click', () => dll.traverseFromFront()) 366 | resetBtnController.addEventListener('click', () => dll.reset()) -------------------------------------------------------------------------------- /js/datastructureControllers/array.js: -------------------------------------------------------------------------------- 1 | //Imports 2 | import { getRandomInt, sleep} from "./utils"; 3 | 4 | // Animation related Elements 5 | const container = document.getElementById('animation-container') 6 | const container2 = document.getElementById('animation-container2') 7 | const structure = 'arrayBox' 8 | const errorBox = document.getElementById("error"); 9 | const reverse = document.getElementById("reverse"); 10 | 11 | 12 | // User Input Elements 13 | const arrayLength = document.getElementById("arrayLength"); 14 | const insertData = document.getElementById("insertData"); 15 | const index = document.getElementById("index"); 16 | const deleteAtIndex = document.getElementById("delIndex"); 17 | const deleteValue = document.getElementById("delValue"); 18 | const replaceIndex = document.getElementById("replaceIndex"); 19 | const replaceValue = document.getElementById("replaceValue"); 20 | const searchValue = document.getElementById("search"); 21 | 22 | const reverseBtn = document.getElementById("reverseBtn"); 23 | const randomBtn = document.getElementById("randomBtn"); 24 | const resetBtn = document.getElementById("resetBtn"); 25 | const createBtn = document.getElementById("createBtn"); 26 | const replaceBtn = document.getElementById("replaceBtn"); 27 | const deleteBtn = document.getElementById("deleteBtn"); 28 | const insertBtn = document.getElementById("insertBtn"); 29 | 30 | const allInputFields = document.querySelectorAll("#simulationPanel input"); 31 | const numberFields = document.querySelectorAll("input[type='number']"); 32 | 33 | const disableAllInputFields = () => { 34 | allInputFields.forEach(input => { 35 | input.disabled = true; 36 | }); 37 | } 38 | 39 | const enableAllInputFields = () => { 40 | allInputFields.forEach(input => { 41 | input.disabled = false; 42 | }); 43 | } 44 | 45 | const disableAllInputFieldsExceptLength = () => { 46 | allInputFields.forEach(input => { 47 | //console.log(input); 48 | if (input.id === "arrayLength") { 49 | input.disabled = false; 50 | } else { 51 | input.disabled = true; 52 | } 53 | }); 54 | }; 55 | 56 | const clearNumberFields = () => { 57 | numberFields.forEach(field => { 58 | field.value = ''; 59 | }); 60 | }; 61 | 62 | const createElement = (value, ind) => { 63 | const element = document.createElement('div'); 64 | element.classList.add(structure) 65 | 66 | 67 | // Current Value 68 | var data = document.createElement('div'); 69 | data.classList.add('data'); 70 | data.innerHTML = value; 71 | 72 | //Next Address 73 | var index = document.createElement('div'); 74 | index.classList.add('index'); 75 | index.innerHTML = ind; 76 | 77 | 78 | element.appendChild(data) 79 | element.appendChild(index) 80 | // container.append(element) 81 | 82 | return element; 83 | 84 | } 85 | 86 | class ArrayList { 87 | 88 | dataArray = new Array(); 89 | reverseArray = new Array(); 90 | arrayIndex = 0; 91 | length = 0; 92 | 93 | setLength(value) { 94 | this.length = parseInt(value); 95 | this.reset(); 96 | if (value == '') { 97 | errorBox.style.display = "block"; 98 | errorBox.innerHTML = "Please enter length"; 99 | return; 100 | } 101 | errorBox.style.display = "block"; 102 | errorBox.innerText = "An Array of length " + value + " is created"; 103 | } 104 | 105 | insert(value) { 106 | errorBox.style.display = "none"; 107 | if (this.length == -1) { 108 | errorBox.style.display = "block"; 109 | errorBox.innerHTML = "Please enter length"; 110 | return; 111 | } 112 | if (this.isFull()) { 113 | errorBox.style.display = "block"; 114 | errorBox.innerText = "Array is Full"; 115 | } 116 | else { 117 | if (value == '' || value == undefined || value >= 99 || value <= -99) { 118 | value = getRandomInt(0, 99); 119 | } 120 | container.append(createElement(value, this.arrayIndex)); 121 | this.dataArray.push(value); 122 | this.arrayIndex++; 123 | } 124 | 125 | } 126 | 127 | insertAtIndex(value, index) { 128 | if (this.isFull()) { 129 | errorBox.style.display = "block"; 130 | errorBox.innerText = "Array is Full"; 131 | return; 132 | } 133 | if (index == '') { 134 | this.insert(value); 135 | return; 136 | } else { 137 | if (index == 0 && this.dataArray.length == 0) { 138 | this.insert(value); 139 | return; 140 | } 141 | 142 | console.log(container.children[parseInt(index)]); 143 | this.dataArray.splice(parseInt(index), 0, value); 144 | this.arrayIndex++; 145 | container.children[parseInt(index)].insertAdjacentElement("beforeBegin", createElement(value, parseInt(index) + 1)); 146 | this.replaceIndex(index); 147 | 148 | } 149 | 150 | } 151 | 152 | replaceIndex(index) { 153 | for (let i = parseInt(index); i < this.dataArray.length; i++) { 154 | container.children[i].children[1].innerHTML = i; 155 | } 156 | } 157 | 158 | deleteAll(index, value) { 159 | if (index == '' && value == '') { 160 | this.delete(); 161 | return; 162 | } 163 | else if (index == '' && value != '') { 164 | this.deleteAtValue(value); 165 | return; 166 | } 167 | else if (value == '' && index != '') { 168 | this.deleteAtIndex(index); 169 | return; 170 | } 171 | else { 172 | errorBox.style.display = "block"; 173 | errorBox.innerText = "Please enter either index or value"; 174 | } 175 | } 176 | 177 | 178 | async delete() { 179 | 180 | if (this.isEmpty()) { 181 | errorBox.style.display = "block"; 182 | errorBox.innerText = "Array is Empty"; 183 | } 184 | else { 185 | container.children[this.dataArray.length - 1].children[0].classList.add('active'); 186 | await sleep(300); 187 | this.dataArray.pop(); 188 | container.children[this.dataArray.length].remove(); 189 | //container.children[this.dataArray.length].children[0].classList.remove('active'); 190 | this.arrayIndex--; 191 | 192 | 193 | } 194 | } 195 | 196 | async deleteAtIndex(index) { 197 | 198 | if (index == '') { 199 | this.delete(value); 200 | return; 201 | } 202 | if (index >= this.dataArray.length) { 203 | errorBox.style.display = "block"; 204 | errorBox.innerText = "Index is out of range"; 205 | 206 | } 207 | else if (this.isEmpty()) { 208 | errorBox.style.display = "block"; 209 | errorBox.innerText = "Array is Empty"; 210 | } 211 | else { 212 | container.children[index].children[0].classList.add('active'); 213 | await sleep(300); 214 | container.children[index].remove(); 215 | container.children[index].children[0].classList.remove('active'); 216 | this.replaceIndex(index - 1) 217 | this.dataArray.splice(index, 1) 218 | //console.log(this.dataArray) 219 | } 220 | } 221 | 222 | async deleteAtValue(value) { 223 | let index = -1; 224 | if (this.isEmpty()) { 225 | errorBox.style.display = "block"; 226 | errorBox.innerText = "Array is Empty"; 227 | } 228 | else { 229 | for (let i = 0; i < this.dataArray.length; i++) { 230 | container.children[i].children[0].classList.add('active'); 231 | if (this.dataArray[i] == value) { 232 | await sleep(300); 233 | container.children[i].children[0].classList.remove('active'); 234 | index = i; 235 | break; 236 | 237 | } 238 | await sleep(300); 239 | container.children[i].children[0].classList.remove('active'); 240 | } 241 | if (index == -1) { 242 | errorBox.style.display = "block"; 243 | errorBox.innerText = "Value is not found"; 244 | } 245 | else { 246 | container.children[index].remove(); 247 | this.replaceIndex(index - 1) 248 | this.dataArray.splice(index, 1) 249 | } 250 | } 251 | } 252 | 253 | 254 | isFull() { 255 | //console.log(this.dataArray.length) 256 | if (this.dataArray.length === this.length) { 257 | return true; 258 | } 259 | return false; 260 | } 261 | 262 | isEmpty() { 263 | if (this.dataArray.length === 0) { 264 | return true; 265 | } 266 | return false; 267 | } 268 | 269 | reset = function () { 270 | errorBox.style.display = "none"; 271 | reverse.style.display = "none"; 272 | container.innerHTML = '' 273 | container2.innerHTML = '' 274 | this.dataArray = new Array(); 275 | this.arrayIndex = 0; 276 | clearNumberFields(); 277 | disableAllInputFieldsExceptLength(); 278 | } 279 | 280 | async search(value) { 281 | if (this.isEmpty()) { 282 | errorBox.style.display = "block"; 283 | errorBox.innerText = "Array is Empty"; 284 | } 285 | else { 286 | for (let i = 0; i < this.dataArray.length; i++) { 287 | container.children[i].children[0].classList.add('active'); 288 | if (this.dataArray[i] == value) { 289 | await sleep(300); 290 | errorBox.style.display = "block"; 291 | errorBox.innerText = "Value is found at index " + i; 292 | container.children[i].children[0].classList.remove('active'); 293 | return i; 294 | 295 | } 296 | await sleep(300); 297 | container.children[i].children[0].classList.remove('active'); 298 | } 299 | errorBox.style.display = "block"; 300 | errorBox.innerText = "Value not found"; 301 | } 302 | } 303 | 304 | async reverse() { 305 | container2.innerHTML = ' '; 306 | if (this.isEmpty()) { 307 | errorBox.style.display = "block"; 308 | errorBox.innerText = "Array is Empty"; 309 | } 310 | else { 311 | errorBox.style.display = "block"; 312 | errorBox.innerText = "Original Array";; 313 | for (let i = this.dataArray.length - 1; i >= 0; i--) { 314 | container.children[i].children[0].classList.add('active'); 315 | this.reverseArray.push(this.dataArray[i]); 316 | await sleep(300); 317 | container.children[i].children[0].classList.remove('active'); 318 | reverse.style.display = "block"; 319 | reverse.innerHTML = "Reversed Array"; 320 | container2.append(createElement(this.dataArray[i], (this.dataArray.length - i - 1))); 321 | } 322 | this.reverseArray = new Array(); 323 | await sleep(2000); 324 | container2.innerHTML = ''; 325 | reverse.style.display = "none"; 326 | 327 | } 328 | } 329 | 330 | 331 | randomArray() { 332 | this.length = 10; 333 | this.dataArray = new Array(); 334 | errorBox.style.display = "block"; 335 | errorBox.innerText = "Random Array"; 336 | container.innerHTML = ' '; 337 | arrayLength.value = '10'; 338 | enableAllInputFields(); 339 | 340 | for (let i = 0; i < 10; i++) { 341 | let a = getRandomInt(0, 99); 342 | this.dataArray.push(a); 343 | container.append(createElement(a, i)); 344 | } 345 | } 346 | 347 | async replaceValue(index, value) { 348 | if (index == '' || value == '') { 349 | errorBox.style.display = "block"; 350 | errorBox.innerText = "Please enter both value and index"; 351 | } 352 | else if (this.dataArray.length < parseInt(index)) { 353 | errorBox.style.display = "block"; 354 | errorBox.innerText = "Index is out of range"; 355 | } 356 | else if (this.isEmpty()) { 357 | errorBox.style.display = "block"; 358 | errorBox.innerText = "Array is Empty"; 359 | } 360 | else { 361 | container.children[index].children[0].classList.add('active'); 362 | await sleep(300); 363 | container.children[index].children[0].classList.remove('active'); 364 | container.children[index].innerHTML = ""; 365 | container.children[index].append(createElement(value, index)); 366 | this.dataArray[index] = value; 367 | } 368 | } 369 | } 370 | 371 | const array = new ArrayList(); 372 | 373 | // Button Event Listners Setup 374 | reverseBtn.addEventListener('click', async function () { 375 | // disableAllInputFields(); 376 | this.disabled = true; 377 | await array.reverse() 378 | this.disabled = false; 379 | // enableAllInputFields(); 380 | }); 381 | resetBtn.addEventListener('click', () => array.reset()); 382 | randomBtn.addEventListener('click', () => array.randomArray()); 383 | 384 | searchBtn.addEventListener('click', async function () { 385 | disableAllInputFields(); 386 | await array.search(searchValue.value); 387 | searchValue.value = ''; 388 | enableAllInputFields(); 389 | }); 390 | 391 | replaceBtn.addEventListener('click', async function () { 392 | //disableAllInputFields(); 393 | await array.replaceValue(replaceIndex.value, replaceValue.value); 394 | replaceIndex.value = ''; 395 | replaceValue.value = ''; 396 | //enableAllInputFields(); 397 | }); 398 | 399 | deleteBtn.addEventListener('click', async function () { 400 | array.deleteAll(deleteAtIndex.value, deleteValue.value); 401 | deleteAtIndex.value = ''; 402 | deleteValue.value = ''; 403 | }); 404 | 405 | insertBtn.addEventListener('click', async function () { 406 | array.insertAtIndex(insertData.value, index.value); 407 | }); 408 | 409 | createBtn.addEventListener('click', async function () { 410 | //console.log(arrayLength.value); 411 | if (arrayLength.value == '') { 412 | errorBox.style.display = "block"; 413 | errorBox.innerText = 'Please enter a valid length.'; 414 | return; 415 | } 416 | enableAllInputFields(); 417 | array.setLength(arrayLength.value); 418 | //arrayLength.value = ''; 419 | }); 420 | 421 | disableAllInputFieldsExceptLength(); 422 | 423 | -------------------------------------------------------------------------------- /queue.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | DSA VISUALIZATION 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 |
18 | 19 |
20 |

21 | QUEUE 22 |

23 |
24 |
25 | 41 | 42 |
43 |
44 |
45 | 52 |
53 |
54 | 55 |
56 | LENGTH 57 |
58 | 63 |
64 | 71 | 76 |
77 | 81 |
82 | 86 | 91 |
92 | 96 |
97 |
98 | 102 | 103 | 106 |
107 |

108 | A linear queue is a linear data structure that serves the request first, 109 | which has been arrived first. It consists of data elements which are connected 110 | in a linear fashion. It has two pointers, i.e., front and rear, where the 111 | insertion takes place from the front end, and deletion occurs from the front end. 112 |

113 |
114 |

115 | Time complexity: 116 |

    117 |
  • Dequeue: O(1)
  • 118 |
  • Enqueue: O(1)
  • 119 |
120 |

121 |
122 |
123 | 124 | 127 |
128 |
129 |

130 | In a Linear queue, once the queue is completely full, 131 | it's not possible to insert more elements. Even if we dequeue the queue to 132 | remove some of the elements, until the queue is reset, 133 | no new elements can be inserted. You must be wondering why? 134 |

135 |
136 |

137 | When we dequeue any element to remove it from the queue, we are actually moving 138 | the front of the queue forward, thereby reducing the overall size of the queue. 139 | And we cannot insert new elements, because the rear pointer is still at the end 140 | of the queue. 141 |

142 |
143 |
144 | 147 |
148 |
149 |

150 | Deque or Double Ended Queue is a type of queue in which insertion and removal of 151 | elements can either be performed from the front or the rear. Thus, it does not 152 | follow FIFO rule (First In First Out). 153 |

154 |
155 |

156 | New items can be added at either the front or the rear. Likewise, existing items 157 | can be removed from either end. In a sense, this hybrid linear structure provides 158 | all the capabilities of stacks and queues in a single data structure. 159 |

160 |
161 |

162 | Time complexity: 163 |

    164 |
  • Dequeue: O(1)
  • 165 |
  • Enqueue: O(1)
  • 166 |
167 |

168 |
169 |
170 |
171 | 172 | 175 |
176 |
177 |

178 | A circular queue is the extended version of a regular queue where the last 179 | element is connected to the first element. Thus forming a circle-like structure. 180 | Circular queue representation. 181 | The circular queue solves the major limitation of the normal queue. 182 |

183 |
184 |

185 | The circular queue solves the major limitation of the normal queue. In a normal queue, 186 | after a bit of insertion and deletion, there will be non-usable empty space. 187 |

188 |
189 |

190 | Time complexity: 191 |

    192 |
  • Dequeue: O(1)
  • 193 |
  • Enqueue: O(1)
  • 194 |
195 |

196 |
197 |
198 |
199 |
200 | × 201 |

Navigate through sections to change simulation.

202 |
203 | 204 |
205 |
206 |
207 |
208 |
209 | 210 |
211 |
212 |
213 |

Front is -1

214 |
215 |
216 |

Rear is -1

217 |
218 |
219 |
220 |
221 | 222 |
223 |
224 | 225 | 226 | 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /js/animation/anime.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * anime.js v3.2.0 3 | * (c) 2020 Julian Garnier 4 | * Released under the MIT license 5 | * animejs.com 6 | */ 7 | 8 | !function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):n.anime=e()}(this,function(){"use strict";var n={update:null,begin:null,loopBegin:null,changeBegin:null,change:null,changeComplete:null,loopComplete:null,complete:null,loop:1,direction:"normal",autoplay:!0,timelineOffset:0},e={duration:1e3,delay:0,endDelay:0,easing:"easeOutElastic(1, .5)",round:0},r=["translateX","translateY","translateZ","rotate","rotateX","rotateY","rotateZ","scale","scaleX","scaleY","scaleZ","skew","skewX","skewY","perspective","matrix","matrix3d"],t={CSS:{},springs:{}};function a(n,e,r){return Math.min(Math.max(n,e),r)}function o(n,e){return n.indexOf(e)>-1}function u(n,e){return n.apply(null,e)}var i={arr:function(n){return Array.isArray(n)},obj:function(n){return o(Object.prototype.toString.call(n),"Object")},pth:function(n){return i.obj(n)&&n.hasOwnProperty("totalLength")},svg:function(n){return n instanceof SVGElement},inp:function(n){return n instanceof HTMLInputElement},dom:function(n){return n.nodeType||i.svg(n)},str:function(n){return"string"==typeof n},fnc:function(n){return"function"==typeof n},und:function(n){return void 0===n},hex:function(n){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(n)},rgb:function(n){return/^rgb/.test(n)},hsl:function(n){return/^hsl/.test(n)},col:function(n){return i.hex(n)||i.rgb(n)||i.hsl(n)},key:function(r){return!n.hasOwnProperty(r)&&!e.hasOwnProperty(r)&&"targets"!==r&&"keyframes"!==r}};function c(n){var e=/\(([^)]+)\)/.exec(n);return e?e[1].split(",").map(function(n){return parseFloat(n)}):[]}function s(n,e){var r=c(n),o=a(i.und(r[0])?1:r[0],.1,100),u=a(i.und(r[1])?100:r[1],.1,100),s=a(i.und(r[2])?10:r[2],.1,100),f=a(i.und(r[3])?0:r[3],.1,100),l=Math.sqrt(u/o),d=s/(2*Math.sqrt(u*o)),p=d<1?l*Math.sqrt(1-d*d):0,h=1,v=d<1?(d*l-f)/p:-f+l;function g(n){var r=e?e*n/1e3:n;return r=d<1?Math.exp(-r*d*l)*(h*Math.cos(p*r)+v*Math.sin(p*r)):(h+v*r)*Math.exp(-r*l),0===n||1===n?n:1-r}return e?g:function(){var e=t.springs[n];if(e)return e;for(var r=0,a=0;;)if(1===g(r+=1/6)){if(++a>=16)break}else a=0;var o=r*(1/6)*1e3;return t.springs[n]=o,o}}function f(n){return void 0===n&&(n=10),function(e){return Math.ceil(a(e,1e-6,1)*n)*(1/n)}}var l,d,p=function(){var n=11,e=1/(n-1);function r(n,e){return 1-3*e+3*n}function t(n,e){return 3*e-6*n}function a(n){return 3*n}function o(n,e,o){return((r(e,o)*n+t(e,o))*n+a(e))*n}function u(n,e,o){return 3*r(e,o)*n*n+2*t(e,o)*n+a(e)}return function(r,t,a,i){if(0<=r&&r<=1&&0<=a&&a<=1){var c=new Float32Array(n);if(r!==t||a!==i)for(var s=0;s=.001?function(n,e,r,t){for(var a=0;a<4;++a){var i=u(e,r,t);if(0===i)return e;e-=(o(e,r,t)-n)/i}return e}(t,l,r,a):0===d?l:function(n,e,r,t,a){for(var u,i,c=0;(u=o(i=e+(r-e)/2,t,a)-n)>0?r=i:e=i,Math.abs(u)>1e-7&&++c<10;);return i}(t,i,i+e,r,a)}}}(),h=(l={linear:function(){return function(n){return n}}},d={Sine:function(){return function(n){return 1-Math.cos(n*Math.PI/2)}},Circ:function(){return function(n){return 1-Math.sqrt(1-n*n)}},Back:function(){return function(n){return n*n*(3*n-2)}},Bounce:function(){return function(n){for(var e,r=4;n<((e=Math.pow(2,--r))-1)/11;);return 1/Math.pow(4,3-r)-7.5625*Math.pow((3*e-2)/22-n,2)}},Elastic:function(n,e){void 0===n&&(n=1),void 0===e&&(e=.5);var r=a(n,1,10),t=a(e,.1,2);return function(n){return 0===n||1===n?n:-r*Math.pow(2,10*(n-1))*Math.sin((n-1-t/(2*Math.PI)*Math.asin(1/r))*(2*Math.PI)/t)}}},["Quad","Cubic","Quart","Quint","Expo"].forEach(function(n,e){d[n]=function(){return function(n){return Math.pow(n,e+2)}}}),Object.keys(d).forEach(function(n){var e=d[n];l["easeIn"+n]=e,l["easeOut"+n]=function(n,r){return function(t){return 1-e(n,r)(1-t)}},l["easeInOut"+n]=function(n,r){return function(t){return t<.5?e(n,r)(2*t)/2:1-e(n,r)(-2*t+2)/2}}}),l);function v(n,e){if(i.fnc(n))return n;var r=n.split("(")[0],t=h[r],a=c(n);switch(r){case"spring":return s(n,e);case"cubicBezier":return u(p,a);case"steps":return u(f,a);default:return u(t,a)}}function g(n){try{return document.querySelectorAll(n)}catch(n){return}}function m(n,e){for(var r=n.length,t=arguments.length>=2?arguments[1]:void 0,a=[],o=0;o1&&(r-=1),r<1/6?n+6*(e-n)*r:r<.5?e:r<2/3?n+(e-n)*(2/3-r)*6:n}if(0==u)e=r=t=i;else{var f=i<.5?i*(1+u):i+u-i*u,l=2*i-f;e=s(l,f,o+1/3),r=s(l,f,o),t=s(l,f,o-1/3)}return"rgba("+255*e+","+255*r+","+255*t+","+c+")"}(n):void 0;var e,r,t,a}function C(n){var e=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(n);if(e)return e[1]}function B(n,e){return i.fnc(n)?n(e.target,e.id,e.total):n}function P(n,e){return n.getAttribute(e)}function I(n,e,r){if(x([r,"deg","rad","turn"],C(e)))return e;var a=t.CSS[e+r];if(!i.und(a))return a;var o=document.createElement(n.tagName),u=n.parentNode&&n.parentNode!==document?n.parentNode:document.body;u.appendChild(o),o.style.position="absolute",o.style.width=100+r;var c=100/o.offsetWidth;u.removeChild(o);var s=c*parseFloat(e);return t.CSS[e+r]=s,s}function T(n,e,r){if(e in n.style){var t=e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),a=n.style[e]||getComputedStyle(n).getPropertyValue(t)||"0";return r?I(n,a,r):a}}function D(n,e){return i.dom(n)&&!i.inp(n)&&(P(n,e)||i.svg(n)&&n[e])?"attribute":i.dom(n)&&x(r,e)?"transform":i.dom(n)&&"transform"!==e&&T(n,e)?"css":null!=n[e]?"object":void 0}function E(n){if(i.dom(n)){for(var e,r=n.style.transform||"",t=/(\w+)\(([^)]*)\)/g,a=new Map;e=t.exec(r);)a.set(e[1],e[2]);return a}}function F(n,e,r,t){var a,u=o(e,"scale")?1:0+(o(a=e,"translate")||"perspective"===a?"px":o(a,"rotate")||o(a,"skew")?"deg":void 0),i=E(n).get(e)||u;return r&&(r.transforms.list.set(e,i),r.transforms.last=e),t?I(n,i,t):i}function N(n,e,r,t){switch(D(n,e)){case"transform":return F(n,e,t,r);case"css":return T(n,e,r);case"attribute":return P(n,e);default:return n[e]||0}}function A(n,e){var r=/^(\*=|\+=|-=)/.exec(n);if(!r)return n;var t=C(n)||0,a=parseFloat(e),o=parseFloat(n.replace(r[0],""));switch(r[0][0]){case"+":return a+o+t;case"-":return a-o+t;case"*":return a*o+t}}function L(n,e){if(i.col(n))return O(n);if(/\s/g.test(n))return n;var r=C(n),t=r?n.substr(0,n.length-r.length):n;return e?t+e:t}function j(n,e){return Math.sqrt(Math.pow(e.x-n.x,2)+Math.pow(e.y-n.y,2))}function S(n){for(var e,r=n.points,t=0,a=0;a0&&(t+=j(e,o)),e=o}return t}function q(n){if(n.getTotalLength)return n.getTotalLength();switch(n.tagName.toLowerCase()){case"circle":return o=n,2*Math.PI*P(o,"r");case"rect":return 2*P(a=n,"width")+2*P(a,"height");case"line":return j({x:P(t=n,"x1"),y:P(t,"y1")},{x:P(t,"x2"),y:P(t,"y2")});case"polyline":return S(n);case"polygon":return r=(e=n).points,S(e)+j(r.getItem(r.numberOfItems-1),r.getItem(0))}var e,r,t,a,o}function $(n,e){var r=e||{},t=r.el||function(n){for(var e=n.parentNode;i.svg(e)&&i.svg(e.parentNode);)e=e.parentNode;return e}(n),a=t.getBoundingClientRect(),o=P(t,"viewBox"),u=a.width,c=a.height,s=r.viewBox||(o?o.split(" "):[0,0,u,c]);return{el:t,viewBox:s,x:s[0]/1,y:s[1]/1,w:u/s[2],h:c/s[3]}}function X(n,e){function r(r){void 0===r&&(r=0);var t=e+r>=1?e+r:0;return n.el.getPointAtLength(t)}var t=$(n.el,n.svg),a=r(),o=r(-1),u=r(1);switch(n.property){case"x":return(a.x-t.x)*t.w;case"y":return(a.y-t.y)*t.h;case"angle":return 180*Math.atan2(u.y-o.y,u.x-o.x)/Math.PI}}function Y(n,e){var r=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g,t=L(i.pth(n)?n.totalLength:n,e)+"";return{original:t,numbers:t.match(r)?t.match(r).map(Number):[0],strings:i.str(n)||e?t.split(r):[]}}function Z(n){return m(n?y(i.arr(n)?n.map(b):b(n)):[],function(n,e,r){return r.indexOf(n)===e})}function Q(n){var e=Z(n);return e.map(function(n,r){return{target:n,id:r,total:e.length,transforms:{list:E(n)}}})}function V(n,e){var r=M(e);if(/^spring/.test(r.easing)&&(r.duration=s(r.easing)),i.arr(n)){var t=n.length;2===t&&!i.obj(n[0])?n={value:n}:i.fnc(e.duration)||(r.duration=e.duration/t)}var a=i.arr(n)?n:[n];return a.map(function(n,r){var t=i.obj(n)&&!i.pth(n)?n:{value:n};return i.und(t.delay)&&(t.delay=r?0:e.delay),i.und(t.endDelay)&&(t.endDelay=r===a.length-1?e.endDelay:0),t}).map(function(n){return k(n,r)})}function z(n,e){var r=[],t=e.keyframes;for(var a in t&&(e=k(function(n){for(var e=m(y(n.map(function(n){return Object.keys(n)})),function(n){return i.key(n)}).reduce(function(n,e){return n.indexOf(e)<0&&n.push(e),n},[]),r={},t=function(t){var a=e[t];r[a]=n.map(function(n){var e={};for(var r in n)i.key(r)?r==a&&(e.value=n[r]):e[r]=n[r];return e})},a=0;a-1&&(_.splice(o,1),r=_.length)}else a.tick(e);t++}n()}else U=cancelAnimationFrame(U)}return n}();function rn(r){void 0===r&&(r={});var t,o=0,u=0,i=0,c=0,s=null;function f(n){var e=window.Promise&&new Promise(function(n){return s=n});return n.finished=e,e}var l,d,p,h,v,g,y,b,x=(d=w(n,l=r),p=w(e,l),h=z(p,l),v=Q(l.targets),g=W(v,h),y=J(g,p),b=K,K++,k(d,{id:b,children:[],animatables:v,animations:g,duration:y.duration,delay:y.delay,endDelay:y.endDelay}));f(x);function M(){var n=x.direction;"alternate"!==n&&(x.direction="normal"!==n?"normal":"reverse"),x.reversed=!x.reversed,t.forEach(function(n){return n.reversed=x.reversed})}function O(n){return x.reversed?x.duration-n:n}function C(){o=0,u=O(x.currentTime)*(1/rn.speed)}function B(n,e){e&&e.seek(n-e.timelineOffset)}function P(n){for(var e=0,r=x.animations,t=r.length;e2||(b=Math.round(b*p)/p)),h.push(b)}var k=d.length;if(k){g=d[0];for(var O=0;O0&&(x.began=!0,I("begin")),!x.loopBegan&&x.currentTime>0&&(x.loopBegan=!0,I("loopBegin")),d<=r&&0!==x.currentTime&&P(0),(d>=l&&x.currentTime!==e||!e)&&P(e),d>r&&d=e&&(u=0,x.remaining&&!0!==x.remaining&&x.remaining--,x.remaining?(o=i,I("loopComplete"),x.loopBegan=!1,"alternate"===x.direction&&M()):(x.paused=!0,x.completed||(x.completed=!0,I("loopComplete"),I("complete"),!x.passThrough&&"Promise"in window&&(s(),f(x)))))}return x.reset=function(){var n=x.direction;x.passThrough=!1,x.currentTime=0,x.progress=0,x.paused=!0,x.began=!1,x.loopBegan=!1,x.changeBegan=!1,x.completed=!1,x.changeCompleted=!1,x.reversePlayback=!1,x.reversed="reverse"===n,x.remaining=x.loop,t=x.children;for(var e=c=t.length;e--;)x.children[e].reset();(x.reversed&&!0!==x.loop||"alternate"===n&&1===x.loop)&&x.remaining++,P(x.reversed?x.duration:0)},x.set=function(n,e){return R(n,e),x},x.tick=function(n){i=n,o||(o=i),T((i+(u-o))*rn.speed)},x.seek=function(n){T(O(n))},x.pause=function(){x.paused=!0,C()},x.play=function(){x.paused&&(x.completed&&x.reset(),x.paused=!1,_.push(x),C(),U||en())},x.reverse=function(){M(),x.completed=!x.reversed,C()},x.restart=function(){x.reset(),x.play()},x.reset(),x.autoplay&&x.play(),x}function tn(n,e){for(var r=e.length;r--;)x(n,e[r].animatable.target)&&e.splice(r,1)}return"undefined"!=typeof document&&document.addEventListener("visibilitychange",function(){document.hidden?(_.forEach(function(n){return n.pause()}),nn=_.slice(0),rn.running=_=[]):nn.forEach(function(n){return n.play()})}),rn.version="3.2.0",rn.speed=1,rn.running=_,rn.remove=function(n){for(var e=Z(n),r=_.length;r--;){var t=_[r],a=t.animations,o=t.children;tn(e,a);for(var u=o.length;u--;){var i=o[u],c=i.animations;tn(e,c),c.length||i.children.length||o.splice(u,1)}a.length||o.length||t.pause()}},rn.get=N,rn.set=R,rn.convertPx=I,rn.path=function(n,e){var r=i.str(n)?g(n)[0]:n,t=e||100;return function(n){return{property:n,el:r,svg:$(r),totalLength:q(r)*(t/100)}}},rn.setDashoffset=function(n){var e=q(n);return n.setAttribute("stroke-dasharray",e),e},rn.stagger=function(n,e){void 0===e&&(e={});var r=e.direction||"normal",t=e.easing?v(e.easing):null,a=e.grid,o=e.axis,u=e.from||0,c="first"===u,s="center"===u,f="last"===u,l=i.arr(n),d=l?parseFloat(n[0]):parseFloat(n),p=l?parseFloat(n[1]):0,h=C(l?n[1]:n)||0,g=e.start||0+(l?d:0),m=[],y=0;return function(n,e,i){if(c&&(u=0),s&&(u=(i-1)/2),f&&(u=i-1),!m.length){for(var v=0;v-1&&_.splice(o,1);for(var s=0;s