Skip to content

Commit 3f1d84b

Browse files
feat(queue): queue implemented
1 parent 241f127 commit 3f1d84b

File tree

4 files changed

+216
-0
lines changed

4 files changed

+216
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
export function* queueOp(array, action) {
2+
const arr = [...array];
3+
4+
switch (action.type) {
5+
case "enqueue":
6+
arr.push(action.value);
7+
yield { type: "enqueue", array: [...arr] };
8+
break;
9+
10+
case "dequeue":
11+
if (arr.length === 0) {
12+
yield { type: "error", message: "Queue is empty" };
13+
return;
14+
}
15+
arr.shift();
16+
yield { type: "dequeue", array: [...arr] };
17+
break;
18+
19+
case "front":
20+
if (arr.length > 0) yield { type: "front", highlight: 0, array: [...arr] };
21+
else yield { type: "error", message: "Queue is empty" };
22+
break;
23+
24+
case "clear":
25+
yield { type: "clear", array: [] };
26+
break;
27+
28+
default:
29+
yield { type: "none", array: [...arr] };
30+
}
31+
32+
yield { type: "done", array: [...arr] };
33+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from "react";
2+
import { motion } from "framer-motion";
3+
4+
export default function QueueVisualizer({ array, highlight }) {
5+
return (
6+
<div className="flex justify-center">
7+
<div className="flex items-end gap-2 overflow-x-auto p-2 bg-gray-800/30 rounded-lg border border-indigo-600 shadow-inner min-h-[100px] w-full">
8+
{array.map((item, i) => (
9+
<motion.div
10+
key={i}
11+
initial={{ opacity: 0, y: 30 }}
12+
animate={{ opacity: 1, y: 0 }}
13+
exit={{ opacity: 0, y: 30 }}
14+
className={`min-w-[60px] sm:min-w-[70px] h-[70px] flex items-center justify-center rounded-lg font-bold border-2 text-white text-lg ${
15+
highlight?.highlight === i
16+
? "bg-yellow-500 border-yellow-300 text-black"
17+
: "bg-indigo-600 border-indigo-400"
18+
}`}
19+
>
20+
{item}
21+
</motion.div>
22+
))}
23+
</div>
24+
</div>
25+
);
26+
}

src/pages/dataStructure/datastructurePage.jsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useState } from "react";
22
import { Network, Compass, Rocket } from "lucide-react";
33
import StackPage from "./stack.jsx";
44
import LinkedListPage from "./linkedlist.jsx"; // ✅ Linked List page import
5+
import QueuePage from "./queue.jsx";
56

67
export default function DSPage() {
78
const [selectedDS, setSelectedDS] = useState("");
@@ -22,6 +23,13 @@ export default function DSPage() {
2223
</div>
2324
);
2425

26+
case "queue":
27+
return (
28+
<div className="w-full h-full overflow-auto">
29+
<QueuePage />
30+
</div>
31+
);
32+
2533
default:
2634
return (
2735
<div className="flex flex-col items-center justify-center text-center p-6">

src/pages/dataStructure/queue.jsx

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import React, { useState } from "react";
2+
import { Toaster, toast } from "react-hot-toast";
3+
import { queueOp } from "../../algorithms/dataStructure/queue.js";
4+
import QueueVisualizer from "../../components/dataStructure/queue.jsx";
5+
6+
export default function QueuePage() {
7+
const [array, setArray] = useState([]);
8+
const [input, setInput] = useState("");
9+
const [highlight, setHighlight] = useState(null);
10+
const [isRunning, setIsRunning] = useState(false);
11+
12+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
13+
14+
const runAction = async (action) => {
15+
if (isRunning) return;
16+
setIsRunning(true);
17+
18+
const gen = queueOp(array, action);
19+
for (let step of gen) {
20+
if (step.message) toast.error(step.message);
21+
setHighlight(step);
22+
if (step.array) setArray([...step.array]);
23+
await delay(400);
24+
}
25+
26+
await delay(150);
27+
setHighlight(null);
28+
setIsRunning(false);
29+
};
30+
31+
const handleEnqueue = async () => {
32+
if (!input.trim()) {
33+
toast.error("Enter a value to enqueue");
34+
return;
35+
}
36+
const parsed = input.trim();
37+
const value = parsed.length && !Number.isNaN(Number(parsed)) ? Number(parsed) : parsed;
38+
await runAction({ type: "enqueue", value });
39+
setInput("");
40+
};
41+
42+
const handleDequeue = async () => {
43+
await runAction({ type: "dequeue" });
44+
};
45+
46+
const handleFront = async () => {
47+
await runAction({ type: "front" });
48+
};
49+
50+
const handleClear = async () => {
51+
await runAction({ type: "clear" });
52+
};
53+
54+
const handleReset = () => {
55+
setArray([]);
56+
setInput("");
57+
setHighlight(null);
58+
};
59+
60+
const sampleLoad = () => {
61+
setArray(["A", "B", "C"]);
62+
setHighlight({ type: "done", array: ["A", "B", "C"] });
63+
};
64+
65+
return (
66+
<div className="min-h-screen bg-black text-gray-200 flex flex-col items-center p-4 sm:p-6">
67+
<Toaster position="top-center" />
68+
<h1 className="text-3xl sm:text-4xl font-extrabold mb-6 sm:mb-8 text-indigo-400 drop-shadow-lg text-center">
69+
Queue Visualizer
70+
</h1>
71+
72+
<div className="w-full max-w-2xl">
73+
<div className="bg-gray-900/40 rounded-lg p-4 sm:p-6 shadow-md">
74+
<div className="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4">
75+
<input
76+
value={input}
77+
onChange={(e) => setInput(e.target.value)}
78+
placeholder="Value to enqueue (number or string)"
79+
className="flex-1 w-full border-2 border-indigo-500 bg-gray-900 text-indigo-200 rounded-lg p-3 text-center outline-none shadow-inner"
80+
/>
81+
<button
82+
onClick={handleEnqueue}
83+
disabled={isRunning}
84+
className={`w-full sm:w-auto ${
85+
isRunning ? "bg-indigo-700 cursor-not-allowed" : "bg-indigo-600 hover:bg-indigo-500"
86+
} px-4 py-2 rounded text-white font-semibold`}
87+
>
88+
Enqueue
89+
</button>
90+
</div>
91+
92+
<div className="mt-4 grid grid-cols-1 sm:grid-cols-5 gap-3">
93+
<button
94+
onClick={handleDequeue}
95+
disabled={isRunning}
96+
className={`${
97+
isRunning ? "bg-gray-700 cursor-not-allowed" : "bg-rose-600 hover:bg-rose-500"
98+
} px-4 py-2 rounded text-white font-semibold`}
99+
>
100+
Dequeue
101+
</button>
102+
103+
<button
104+
onClick={handleFront}
105+
disabled={isRunning}
106+
className={`${
107+
isRunning ? "bg-gray-700 cursor-not-allowed" : "bg-yellow-500 hover:bg-yellow-400"
108+
} px-4 py-2 rounded text-white font-semibold`}
109+
>
110+
Front
111+
</button>
112+
113+
<button
114+
onClick={handleClear}
115+
disabled={isRunning}
116+
className={`${
117+
isRunning ? "bg-gray-700 cursor-not-allowed" : "bg-gray-700 hover:bg-gray-600"
118+
} px-4 py-2 rounded text-white font-semibold`}
119+
>
120+
Clear
121+
</button>
122+
123+
<button
124+
onClick={handleReset}
125+
className="bg-gray-600 hover:bg-gray-500 px-4 py-2 rounded text-white font-semibold"
126+
>
127+
Reset
128+
</button>
129+
130+
<button
131+
onClick={sampleLoad}
132+
className="bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-white font-semibold"
133+
>
134+
Load Demo
135+
</button>
136+
</div>
137+
</div>
138+
139+
<div className="mt-6">
140+
<QueueVisualizer array={array} highlight={highlight} />
141+
</div>
142+
143+
<div className="mt-4 text-sm text-slate-400 text-center">
144+
Tip: Front of queue is on the left; Enqueue adds to end; Dequeue removes from front (FIFO).
145+
</div>
146+
</div>
147+
</div>
148+
);
149+
}

0 commit comments

Comments
 (0)