dsa_visualizer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +323 -0
- data/USAGE.md +359 -0
- data/bin/dsa_visualizer +5 -0
- data/lib/dsa_visualizer/algorithms/dynamic_programming.rb +23 -0
- data/lib/dsa_visualizer/algorithms/graph_algorithms.rb +23 -0
- data/lib/dsa_visualizer/algorithms/greedy.rb +11 -0
- data/lib/dsa_visualizer/algorithms/searching.rb +78 -0
- data/lib/dsa_visualizer/algorithms/sorting.rb +77 -0
- data/lib/dsa_visualizer/algorithms/string_algorithms.rb +11 -0
- data/lib/dsa_visualizer/cli.rb +281 -0
- data/lib/dsa_visualizer/comparator.rb +57 -0
- data/lib/dsa_visualizer/data_structures/array.rb +109 -0
- data/lib/dsa_visualizer/data_structures/binary_tree.rb +104 -0
- data/lib/dsa_visualizer/data_structures/bst.rb +11 -0
- data/lib/dsa_visualizer/data_structures/deque.rb +11 -0
- data/lib/dsa_visualizer/data_structures/doubly_linked_list.rb +11 -0
- data/lib/dsa_visualizer/data_structures/graph.rb +11 -0
- data/lib/dsa_visualizer/data_structures/hash_table.rb +61 -0
- data/lib/dsa_visualizer/data_structures/heap.rb +17 -0
- data/lib/dsa_visualizer/data_structures/linked_list.rb +197 -0
- data/lib/dsa_visualizer/data_structures/priority_queue.rb +11 -0
- data/lib/dsa_visualizer/data_structures/queue.rb +110 -0
- data/lib/dsa_visualizer/data_structures/stack.rb +207 -0
- data/lib/dsa_visualizer/data_structures/string.rb +11 -0
- data/lib/dsa_visualizer/data_structures/trie.rb +11 -0
- data/lib/dsa_visualizer/data_structures/union_find.rb +11 -0
- data/lib/dsa_visualizer/fundamentals/complexity.rb +264 -0
- data/lib/dsa_visualizer/fundamentals/memory.rb +285 -0
- data/lib/dsa_visualizer/fundamentals/pointers.rb +311 -0
- data/lib/dsa_visualizer/fundamentals/recursion.rb +63 -0
- data/lib/dsa_visualizer/memory_tracker.rb +49 -0
- data/lib/dsa_visualizer/notes_manager.rb +85 -0
- data/lib/dsa_visualizer/version.rb +3 -0
- data/lib/dsa_visualizer/visualizer.rb +58 -0
- data/lib/dsa_visualizer.rb +114 -0
- metadata +157 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class TreeNode
|
|
4
|
+
attr_accessor :value, :left, :right
|
|
5
|
+
|
|
6
|
+
def initialize(value)
|
|
7
|
+
@value = value
|
|
8
|
+
@left = nil
|
|
9
|
+
@right = nil
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class BinaryTree
|
|
14
|
+
attr_reader :root
|
|
15
|
+
|
|
16
|
+
def initialize
|
|
17
|
+
@root = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def insert(value)
|
|
21
|
+
@root = insert_recursive(@root, value)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def insert_recursive(node, value)
|
|
27
|
+
return TreeNode.new(value) if node.nil?
|
|
28
|
+
|
|
29
|
+
if value < node.value
|
|
30
|
+
node.left = insert_recursive(node.left, value)
|
|
31
|
+
else
|
|
32
|
+
node.right = insert_recursive(node.right, value)
|
|
33
|
+
end
|
|
34
|
+
node
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
public
|
|
38
|
+
|
|
39
|
+
def self.learn
|
|
40
|
+
demo
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.demo
|
|
44
|
+
Visualizer.print_header("BINARY SEARCH TREE - Core Level Visualization")
|
|
45
|
+
|
|
46
|
+
Visualizer.print_section("1. BST Concept")
|
|
47
|
+
puts "\nBinary Search Tree properties:"
|
|
48
|
+
puts " - Left subtree < node < right subtree"
|
|
49
|
+
puts " - Enables O(log n) search in balanced tree"
|
|
50
|
+
puts " - Can degrade to O(n) if unbalanced"
|
|
51
|
+
|
|
52
|
+
Visualizer.print_section("2. Implementation Comparison")
|
|
53
|
+
|
|
54
|
+
ruby_code = <<~RUBY
|
|
55
|
+
class TreeNode
|
|
56
|
+
attr_accessor :value, :left, :right
|
|
57
|
+
def initialize(value)
|
|
58
|
+
@value = value
|
|
59
|
+
@left = @right = nil
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Ruby: object references for children
|
|
64
|
+
# GC handles memory
|
|
65
|
+
RUBY
|
|
66
|
+
|
|
67
|
+
cpp_code = <<~CPP
|
|
68
|
+
struct TreeNode {
|
|
69
|
+
int value;
|
|
70
|
+
TreeNode *left, *right;
|
|
71
|
+
TreeNode(int v) : value(v),
|
|
72
|
+
left(nullptr), right(nullptr) {}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// C++: explicit pointers
|
|
76
|
+
// Manual memory management
|
|
77
|
+
CPP
|
|
78
|
+
|
|
79
|
+
explanation = "Both use pointer-based structure. Ruby uses object references with GC, C++ uses raw pointers requiring manual deletion. Tree traversal is same in both."
|
|
80
|
+
|
|
81
|
+
Visualizer.print_comparison(ruby_code, cpp_code, explanation)
|
|
82
|
+
|
|
83
|
+
tree = BinaryTree.new
|
|
84
|
+
values = [50, 30, 70, 20, 40, 60, 80]
|
|
85
|
+
|
|
86
|
+
Visualizer.print_step(1, "Inserting values: #{values.join(', ')}")
|
|
87
|
+
values.each { |v| tree.insert(v) }
|
|
88
|
+
|
|
89
|
+
puts "\nTree structure:"
|
|
90
|
+
puts " 50"
|
|
91
|
+
puts " / \\"
|
|
92
|
+
puts " 30 70"
|
|
93
|
+
puts " / \\ / \\"
|
|
94
|
+
puts " 20 40 60 80"
|
|
95
|
+
|
|
96
|
+
puts "\n\nšÆ Key Takeaways:".colorize(:green).bold
|
|
97
|
+
puts " 1. BST enables efficient searching: O(log n) average"
|
|
98
|
+
puts " 2. Insertion/deletion: O(log n) average"
|
|
99
|
+
puts " 3. Worst case O(n) for unbalanced tree"
|
|
100
|
+
puts " 4. Self-balancing trees (AVL, Red-Black) maintain O(log n)"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class BST
|
|
4
|
+
def self.learn
|
|
5
|
+
Visualizer.print_header("BINARY SEARCH TREE - Ordered Binary Tree")
|
|
6
|
+
puts "\nš Coming soon: BST properties, search, insert, delete"
|
|
7
|
+
puts "Topics: In-order traversal, balancing, AVL trees"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class Deque
|
|
4
|
+
def self.learn
|
|
5
|
+
Visualizer.print_header("DEQUE - Double-Ended Queue")
|
|
6
|
+
puts "\nš Coming soon: Operations at both ends"
|
|
7
|
+
puts "Topics: Push/pop from front and back, circular buffer implementation"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class DoublyLinkedList
|
|
4
|
+
def self.learn
|
|
5
|
+
Visualizer.print_header("DOUBLY LINKED LIST - Bidirectional Navigation")
|
|
6
|
+
puts "\nš Coming soon: Two-way traversal, prev and next pointers"
|
|
7
|
+
puts "Topics: Insertion, deletion, reverse traversal"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class Graph
|
|
4
|
+
def self.learn
|
|
5
|
+
Visualizer.print_header("GRAPH - Vertices and Edges")
|
|
6
|
+
puts "\nš Coming soon: Graph representations"
|
|
7
|
+
puts "Topics: Adjacency matrix, adjacency list, directed vs undirected"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class HashTable
|
|
4
|
+
def self.learn
|
|
5
|
+
demo
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.demo
|
|
9
|
+
Visualizer.print_header("HASH TABLE - Core Level Visualization")
|
|
10
|
+
|
|
11
|
+
Visualizer.print_section("1. Hash Table Concept")
|
|
12
|
+
puts "\nKey-Value storage with O(1) average access time"
|
|
13
|
+
puts "Uses hash function to map keys to array indices"
|
|
14
|
+
|
|
15
|
+
Visualizer.print_section("2. Implementation Comparison")
|
|
16
|
+
|
|
17
|
+
ruby_code = <<~RUBY
|
|
18
|
+
hash = { "name" => "Alice", "age" => 30 }
|
|
19
|
+
|
|
20
|
+
# Ruby Hash internals:
|
|
21
|
+
# - Uses MurmurHash
|
|
22
|
+
# - Open addressing with linear probing
|
|
23
|
+
# - Maintains insertion order (since Ruby 1.9)
|
|
24
|
+
# - Automatic resizing at 75% capacity
|
|
25
|
+
RUBY
|
|
26
|
+
|
|
27
|
+
cpp_code = <<~CPP
|
|
28
|
+
#include <unordered_map>
|
|
29
|
+
std::unordered_map<std::string, int> map;
|
|
30
|
+
map["name"] = "Alice";
|
|
31
|
+
|
|
32
|
+
// C++ unordered_map:
|
|
33
|
+
// - Uses hash function (std::hash)
|
|
34
|
+
// - Separate chaining (linked lists)
|
|
35
|
+
// - No order guarantee
|
|
36
|
+
// - Rehashing at load factor threshold
|
|
37
|
+
CPP
|
|
38
|
+
|
|
39
|
+
explanation = "Ruby Hash maintains insertion order and uses open addressing. C++ unordered_map uses separate chaining and doesn't maintain order. Both provide O(1) average case, O(n) worst case."
|
|
40
|
+
|
|
41
|
+
Visualizer.print_comparison(ruby_code, cpp_code, explanation)
|
|
42
|
+
|
|
43
|
+
Visualizer.print_section("3. Hash Function Demo")
|
|
44
|
+
|
|
45
|
+
keys = ["apple", "banana", "cherry"]
|
|
46
|
+
puts "\nHash values for keys:"
|
|
47
|
+
keys.each do |key|
|
|
48
|
+
hash_val = key.hash
|
|
49
|
+
bucket = hash_val % 10
|
|
50
|
+
puts " '#{key}' ā hash: #{hash_val} ā bucket: #{bucket}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
puts "\n\nšÆ Key Takeaways:".colorize(:green).bold
|
|
54
|
+
puts " 1. Hash tables provide O(1) average lookup"
|
|
55
|
+
puts " 2. Collision handling: chaining vs open addressing"
|
|
56
|
+
puts " 3. Ruby maintains order, C++ doesn't"
|
|
57
|
+
puts " 4. Load factor triggers resizing"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class Heap
|
|
4
|
+
def self.learn_min
|
|
5
|
+
Visualizer.print_header("MIN HEAP - Complete Binary Tree")
|
|
6
|
+
puts "\nš Coming soon: Heap property, heapify, extract-min"
|
|
7
|
+
puts "Topics: Array representation, priority queue implementation"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.learn_max
|
|
11
|
+
Visualizer.print_header("MAX HEAP - Complete Binary Tree")
|
|
12
|
+
puts "\nš Coming soon: Max heap operations"
|
|
13
|
+
puts "Topics: Heap sort, building heap in O(n)"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class Node
|
|
4
|
+
attr_accessor :data, :next
|
|
5
|
+
|
|
6
|
+
def initialize(data)
|
|
7
|
+
@data = data
|
|
8
|
+
@next = nil
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class LinkedList
|
|
13
|
+
attr_reader :head
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@head = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def append(data)
|
|
20
|
+
new_node = Node.new(data)
|
|
21
|
+
|
|
22
|
+
if @head.nil?
|
|
23
|
+
@head = new_node
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
current = @head
|
|
28
|
+
current = current.next while current.next
|
|
29
|
+
current.next = new_node
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def visualize
|
|
33
|
+
return "Empty list" if @head.nil?
|
|
34
|
+
|
|
35
|
+
result = ""
|
|
36
|
+
current = @head
|
|
37
|
+
while current
|
|
38
|
+
result += "[#{current.data}|ā¢]"
|
|
39
|
+
result += " -> " if current.next
|
|
40
|
+
current = current.next
|
|
41
|
+
end
|
|
42
|
+
result += " -> nil"
|
|
43
|
+
result
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.learn
|
|
47
|
+
demo
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.demo
|
|
51
|
+
Visualizer.print_header("LINKED LIST - Core Level Visualization")
|
|
52
|
+
|
|
53
|
+
# Memory Model
|
|
54
|
+
Visualizer.print_section("1. Memory Model Comparison")
|
|
55
|
+
|
|
56
|
+
ruby_code = <<~RUBY
|
|
57
|
+
class Node
|
|
58
|
+
attr_accessor :data, :next
|
|
59
|
+
def initialize(data)
|
|
60
|
+
@data = data
|
|
61
|
+
@next = nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
# Each node is a Ruby object
|
|
65
|
+
# @next stores reference to next node
|
|
66
|
+
RUBY
|
|
67
|
+
|
|
68
|
+
cpp_code = <<~CPP
|
|
69
|
+
struct Node {
|
|
70
|
+
int data;
|
|
71
|
+
Node* next;
|
|
72
|
+
Node(int d) : data(d), next(nullptr) {}
|
|
73
|
+
};
|
|
74
|
+
// Each node allocated on heap
|
|
75
|
+
// next is explicit pointer
|
|
76
|
+
CPP
|
|
77
|
+
|
|
78
|
+
explanation = "Ruby uses object references (implicit pointers), C++ uses explicit pointers. Both achieve same structure but Ruby adds GC overhead while C++ requires manual memory management."
|
|
79
|
+
|
|
80
|
+
Visualizer.print_comparison(ruby_code, cpp_code, explanation)
|
|
81
|
+
|
|
82
|
+
# Creation
|
|
83
|
+
Visualizer.print_section("2. Creating Linked List")
|
|
84
|
+
tracker = MemoryTracker.new
|
|
85
|
+
list = LinkedList.new
|
|
86
|
+
|
|
87
|
+
Visualizer.print_step(1, "Adding nodes: 10, 20, 30")
|
|
88
|
+
|
|
89
|
+
[10, 20, 30].each do |value|
|
|
90
|
+
list.append(value)
|
|
91
|
+
tracker.track_operation("Append", "Added node with value #{value}")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
puts "\n" + list.visualize
|
|
95
|
+
|
|
96
|
+
puts "\nš¦ Memory Layout:"
|
|
97
|
+
current = list.head
|
|
98
|
+
index = 0
|
|
99
|
+
while current
|
|
100
|
+
puts " Node #{index}:"
|
|
101
|
+
puts " Address: 0x#{current.object_id.to_s(16)}"
|
|
102
|
+
puts " Data: #{current.data}"
|
|
103
|
+
puts " Next: #{current.next ? "0x#{current.next.object_id.to_s(16)}" : "nil"}"
|
|
104
|
+
current = current.next
|
|
105
|
+
index += 1
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
puts "\nš Ruby Internals:"
|
|
109
|
+
puts " - Each Node is a Ruby object (heap allocated)"
|
|
110
|
+
puts " - @next is object reference (managed by GC)"
|
|
111
|
+
puts " - No manual memory management needed"
|
|
112
|
+
puts " - Overhead: object header + reference tracking"
|
|
113
|
+
|
|
114
|
+
puts "\nš C++ Internals:"
|
|
115
|
+
puts " - Each Node allocated with 'new'"
|
|
116
|
+
puts " - next is raw pointer (8 bytes on 64-bit)"
|
|
117
|
+
puts " - Must manually delete nodes"
|
|
118
|
+
puts " - No overhead beyond struct size"
|
|
119
|
+
|
|
120
|
+
# Traversal
|
|
121
|
+
Visualizer.print_section("3. Traversal")
|
|
122
|
+
Visualizer.print_step(2, "Traversing to find value 20")
|
|
123
|
+
|
|
124
|
+
puts "\nProcess:"
|
|
125
|
+
current = list.head
|
|
126
|
+
position = 0
|
|
127
|
+
while current
|
|
128
|
+
if current.data == 20
|
|
129
|
+
puts " Position #{position}: [#{current.data}] ā FOUND!".colorize(:green)
|
|
130
|
+
else
|
|
131
|
+
puts " Position #{position}: [#{current.data}]"
|
|
132
|
+
end
|
|
133
|
+
current = current.next
|
|
134
|
+
position += 1
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
Comparator.compare_complexity(
|
|
138
|
+
"Linked List Traversal",
|
|
139
|
+
"O(n) - must follow references",
|
|
140
|
+
"O(n) - must follow pointers",
|
|
141
|
+
"Both require sequential access. No random access like arrays. Cache performance worse due to non-contiguous memory."
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
# Insertion
|
|
145
|
+
Visualizer.print_section("4. Insertion at Beginning")
|
|
146
|
+
Visualizer.print_step(3, "Inserting 5 at head")
|
|
147
|
+
|
|
148
|
+
puts "\nBefore: " + list.visualize
|
|
149
|
+
|
|
150
|
+
new_node = Node.new(5)
|
|
151
|
+
new_node.next = list.head
|
|
152
|
+
list.instance_variable_set(:@head, new_node)
|
|
153
|
+
tracker.track_operation("Insert", "Inserted 5 at head")
|
|
154
|
+
|
|
155
|
+
puts "After: " + list.visualize
|
|
156
|
+
|
|
157
|
+
puts "\nš Ruby Process:"
|
|
158
|
+
puts " 1. Create new Node object (GC manages)"
|
|
159
|
+
puts " 2. Set new_node.next = current head"
|
|
160
|
+
puts " 3. Update head reference"
|
|
161
|
+
puts " 4. O(1) operation"
|
|
162
|
+
|
|
163
|
+
puts "\nš C++ Process:"
|
|
164
|
+
puts " 1. Allocate: Node* new_node = new Node(5)"
|
|
165
|
+
puts " 2. Set: new_node->next = head"
|
|
166
|
+
puts " 3. Update: head = new_node"
|
|
167
|
+
puts " 4. O(1) operation"
|
|
168
|
+
|
|
169
|
+
# Memory comparison
|
|
170
|
+
Visualizer.print_section("5. Memory Comparison")
|
|
171
|
+
|
|
172
|
+
puts "\nš Array vs Linked List:"
|
|
173
|
+
puts "\nArray:"
|
|
174
|
+
puts " ā Contiguous memory (better cache)"
|
|
175
|
+
puts " ā O(1) random access"
|
|
176
|
+
puts " ā O(n) insertion/deletion (middle)"
|
|
177
|
+
puts " ā Fixed size (or expensive resize)"
|
|
178
|
+
|
|
179
|
+
puts "\nLinked List:"
|
|
180
|
+
puts " ā O(1) insertion/deletion (at known position)"
|
|
181
|
+
puts " ā Dynamic size (no resize needed)"
|
|
182
|
+
puts " ā O(n) random access"
|
|
183
|
+
puts " ā Poor cache locality"
|
|
184
|
+
puts " ā Extra memory for pointers/references"
|
|
185
|
+
|
|
186
|
+
tracker.print_summary
|
|
187
|
+
|
|
188
|
+
puts "\n\nšÆ Key Takeaways:".colorize(:green).bold
|
|
189
|
+
puts " 1. Linked lists trade random access for efficient insertion/deletion"
|
|
190
|
+
puts " 2. Ruby's GC simplifies memory management vs C++ manual management"
|
|
191
|
+
puts " 3. Non-contiguous memory means poor cache performance"
|
|
192
|
+
puts " 4. Each node has pointer/reference overhead"
|
|
193
|
+
puts " 5. Best for frequent insertions/deletions, not random access"
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class PriorityQueue
|
|
4
|
+
def self.learn
|
|
5
|
+
Visualizer.print_header("PRIORITY QUEUE - Heap-Based Queue")
|
|
6
|
+
puts "\nš Coming soon: Priority-based dequeue"
|
|
7
|
+
puts "Topics: Min/max heap implementation, applications in scheduling"
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
module DSAVisualizer
|
|
2
|
+
module DataStructures
|
|
3
|
+
class Queue
|
|
4
|
+
def initialize
|
|
5
|
+
@items = []
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def enqueue(item)
|
|
9
|
+
@items.push(item)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def dequeue
|
|
13
|
+
@items.shift
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def front
|
|
17
|
+
@items.first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def empty?
|
|
21
|
+
@items.empty?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def size
|
|
25
|
+
@items.size
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def visualize
|
|
29
|
+
return "Empty queue" if @items.empty?
|
|
30
|
+
|
|
31
|
+
result = "\nFRONT ā "
|
|
32
|
+
@items.each_with_index do |item, idx|
|
|
33
|
+
result += "[ #{item} ]"
|
|
34
|
+
result += " ā " unless idx == @items.size - 1
|
|
35
|
+
end
|
|
36
|
+
result += " ā REAR"
|
|
37
|
+
result
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.learn
|
|
41
|
+
demo
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.demo
|
|
45
|
+
Visualizer.print_header("QUEUE - Core Level Visualization")
|
|
46
|
+
|
|
47
|
+
Visualizer.print_section("1. Queue Concept (FIFO)")
|
|
48
|
+
puts "\nFirst In, First Out - like a line at a store"
|
|
49
|
+
puts "Operations: enqueue (add at rear), dequeue (remove from front)"
|
|
50
|
+
|
|
51
|
+
Visualizer.print_section("2. Implementation Comparison")
|
|
52
|
+
|
|
53
|
+
ruby_code = <<~RUBY
|
|
54
|
+
class Queue
|
|
55
|
+
def initialize
|
|
56
|
+
@items = []
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def enqueue(item)
|
|
60
|
+
@items.push(item) # O(1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def dequeue
|
|
64
|
+
@items.shift # O(n) - shifts all elements!
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
RUBY
|
|
68
|
+
|
|
69
|
+
cpp_code = <<~CPP
|
|
70
|
+
#include <queue>
|
|
71
|
+
std::queue<int> q;
|
|
72
|
+
|
|
73
|
+
q.push(10); // O(1)
|
|
74
|
+
q.pop(); // O(1)
|
|
75
|
+
|
|
76
|
+
// Internally uses deque (double-ended queue)
|
|
77
|
+
// Efficient operations at both ends
|
|
78
|
+
CPP
|
|
79
|
+
|
|
80
|
+
explanation = "Ruby's Array.shift is O(n) because it shifts all elements. C++'s std::queue uses deque internally for O(1) operations at both ends. For better Ruby performance, use a circular buffer or linked list."
|
|
81
|
+
|
|
82
|
+
Visualizer.print_comparison(ruby_code, cpp_code, explanation)
|
|
83
|
+
|
|
84
|
+
tracker = MemoryTracker.new
|
|
85
|
+
queue = Queue.new
|
|
86
|
+
|
|
87
|
+
Visualizer.print_step(1, "Enqueuing: 10, 20, 30")
|
|
88
|
+
[10, 20, 30].each do |val|
|
|
89
|
+
queue.enqueue(val)
|
|
90
|
+
tracker.track_operation("Enqueue", "Added #{val}")
|
|
91
|
+
puts queue.visualize
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
Visualizer.print_step(2, "Dequeuing")
|
|
95
|
+
dequeued = queue.dequeue
|
|
96
|
+
tracker.track_operation("Dequeue", "Removed #{dequeued}")
|
|
97
|
+
puts "\nRemoved: #{dequeued}".colorize(:red)
|
|
98
|
+
puts queue.visualize
|
|
99
|
+
|
|
100
|
+
tracker.print_summary
|
|
101
|
+
|
|
102
|
+
puts "\n\nšÆ Key Takeaways:".colorize(:green).bold
|
|
103
|
+
puts " 1. Queue is FIFO - First In, First Out"
|
|
104
|
+
puts " 2. Ruby Array.shift is O(n) - inefficient for large queues"
|
|
105
|
+
puts " 3. C++ std::queue uses deque for O(1) operations"
|
|
106
|
+
puts " 4. Use cases: task scheduling, BFS, buffering"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|