dsa_visualizer 0.1.1 → 0.1.2

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.
@@ -1,10 +1,311 @@
1
1
  module DSAVisualizer
2
2
  module DataStructures
3
3
  class BST
4
+ class Node
5
+ attr_accessor :value, :left, :right
6
+
7
+ def initialize(value)
8
+ @value = value
9
+ @left = nil
10
+ @right = nil
11
+ end
12
+ end
13
+
4
14
  def self.learn
5
15
  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"
16
+
17
+ puts "\nšŸ“– CONCEPT:"
18
+ puts "A Binary Search Tree (BST) is a binary tree where:"
19
+ puts "• Left subtree contains nodes with values less than parent"
20
+ puts "• Right subtree contains nodes with values greater than parent"
21
+ puts "• Both left and right subtrees are also BSTs"
22
+ puts "• Enables efficient searching, insertion, and deletion"
23
+
24
+ puts "\nā±ļø TIME COMPLEXITY:"
25
+ puts "• Search: O(log n) average, O(n) worst case"
26
+ puts "• Insert: O(log n) average, O(n) worst case"
27
+ puts "• Delete: O(log n) average, O(n) worst case"
28
+ puts "• Traversal: O(n)"
29
+
30
+ puts "\nšŸ’¾ SPACE COMPLEXITY: O(n)"
31
+
32
+ demonstrate_bst
33
+ demonstrate_operations
34
+ demonstrate_traversals
35
+ show_ruby_vs_cpp
36
+ show_practice_problems
37
+ end
38
+
39
+ def self.demonstrate_bst
40
+ puts "\n" + "="*60
41
+ puts "DEMONSTRATION: Building a BST"
42
+ puts "="*60
43
+
44
+ bst = BSTImplementation.new
45
+ values = [50, 30, 70, 20, 40, 60, 80]
46
+
47
+ puts "\nInserting values: #{values.join(', ')}"
48
+ values.each do |val|
49
+ bst.insert(val)
50
+ puts "Inserted #{val}"
51
+ end
52
+
53
+ puts "\nšŸ“Š Tree Structure:"
54
+ puts " 50"
55
+ puts " / \\"
56
+ puts " 30 70"
57
+ puts " / \\ / \\"
58
+ puts " 20 40 60 80"
59
+
60
+ puts "\nšŸ” Searching for values:"
61
+ [40, 90].each do |val|
62
+ result = bst.search(val)
63
+ puts "Search #{val}: #{result ? 'āœ“ Found' : 'āœ— Not found'}"
64
+ end
65
+ end
66
+
67
+ def self.demonstrate_operations
68
+ puts "\n" + "="*60
69
+ puts "BST OPERATIONS"
70
+ puts "="*60
71
+
72
+ bst = BSTImplementation.new
73
+ [50, 30, 70, 20, 40, 60, 80].each { |v| bst.insert(v) }
74
+
75
+ puts "\n1ļøāƒ£ FIND MINIMUM:"
76
+ puts "Minimum value: #{bst.find_min}"
77
+
78
+ puts "\n2ļøāƒ£ FIND MAXIMUM:"
79
+ puts "Maximum value: #{bst.find_max}"
80
+
81
+ puts "\n3ļøāƒ£ DELETE NODE:"
82
+ puts "Deleting 30 (node with two children)..."
83
+ bst.delete(30)
84
+ puts "āœ“ Deleted successfully"
85
+ end
86
+
87
+ def self.demonstrate_traversals
88
+ puts "\n" + "="*60
89
+ puts "TREE TRAVERSALS"
90
+ puts "="*60
91
+
92
+ bst = BSTImplementation.new
93
+ [50, 30, 70, 20, 40, 60, 80].each { |v| bst.insert(v) }
94
+
95
+ puts "\n1ļøāƒ£ IN-ORDER (Left → Root → Right):"
96
+ puts "Result: #{bst.inorder.join(', ')}"
97
+ puts "Note: Gives sorted order!"
98
+
99
+ puts "\n2ļøāƒ£ PRE-ORDER (Root → Left → Right):"
100
+ puts "Result: #{bst.preorder.join(', ')}"
101
+
102
+ puts "\n3ļøāƒ£ POST-ORDER (Left → Right → Root):"
103
+ puts "Result: #{bst.postorder.join(', ')}"
104
+ end
105
+
106
+ def self.show_ruby_vs_cpp
107
+ puts "\n" + "="*60
108
+ puts "RUBY vs C++ IMPLEMENTATION"
109
+ puts "="*60
110
+
111
+ puts "\nšŸ”“ RUBY:"
112
+ puts <<~RUBY
113
+ class Node
114
+ attr_accessor :value, :left, :right
115
+ def initialize(value)
116
+ @value = value
117
+ @left = @right = nil
118
+ end
119
+ end
120
+
121
+ class BST
122
+ def insert(value, node = @root)
123
+ return Node.new(value) if node.nil?
124
+ if value < node.value
125
+ node.left = insert(value, node.left)
126
+ else
127
+ node.right = insert(value, node.right)
128
+ end
129
+ node
130
+ end
131
+
132
+ def search(value, node = @root)
133
+ return false if node.nil?
134
+ return true if node.value == value
135
+ value < node.value ? search(value, node.left) : search(value, node.right)
136
+ end
137
+ end
138
+ RUBY
139
+
140
+ puts "\nšŸ”µ C++:"
141
+ puts <<~CPP
142
+ struct Node {
143
+ int value;
144
+ Node* left;
145
+ Node* right;
146
+ Node(int val) : value(val), left(nullptr), right(nullptr) {}
147
+ };
148
+
149
+ class BST {
150
+ Node* root;
151
+ public:
152
+ Node* insert(Node* node, int value) {
153
+ if (node == nullptr) return new Node(value);
154
+ if (value < node->value)
155
+ node->left = insert(node->left, value);
156
+ else
157
+ node->right = insert(node->right, value);
158
+ return node;
159
+ }
160
+
161
+ bool search(Node* node, int value) {
162
+ if (node == nullptr) return false;
163
+ if (node->value == value) return true;
164
+ return value < node->value ?
165
+ search(node->left, value) : search(node->right, value);
166
+ }
167
+ };
168
+ CPP
169
+ end
170
+
171
+ def self.show_practice_problems
172
+ puts "\n" + "="*60
173
+ puts "PRACTICE PROBLEMS"
174
+ puts "="*60
175
+
176
+ problems = [
177
+ "1. Validate if a binary tree is a valid BST",
178
+ "2. Find the kth smallest element in a BST",
179
+ "3. Convert sorted array to balanced BST",
180
+ "4. Find lowest common ancestor in BST",
181
+ "5. Check if two BSTs are identical",
182
+ "6. Find the inorder successor of a node",
183
+ "7. Convert BST to sorted doubly linked list",
184
+ "8. Find the distance between two nodes"
185
+ ]
186
+
187
+ problems.each { |p| puts p }
188
+
189
+ puts "\nšŸ’” TIP: In-order traversal of BST gives sorted order!"
190
+ puts "šŸ’” TIP: BST property: left < root < right for all nodes"
191
+ end
192
+
193
+ class BSTImplementation
194
+ attr_reader :root
195
+
196
+ def initialize
197
+ @root = nil
198
+ end
199
+
200
+ def insert(value)
201
+ @root = insert_recursive(@root, value)
202
+ end
203
+
204
+ def search(value)
205
+ search_recursive(@root, value)
206
+ end
207
+
208
+ def delete(value)
209
+ @root = delete_recursive(@root, value)
210
+ end
211
+
212
+ def find_min
213
+ node = @root
214
+ node = node.left while node&.left
215
+ node&.value
216
+ end
217
+
218
+ def find_max
219
+ node = @root
220
+ node = node.right while node&.right
221
+ node&.value
222
+ end
223
+
224
+ def inorder
225
+ result = []
226
+ inorder_recursive(@root, result)
227
+ result
228
+ end
229
+
230
+ def preorder
231
+ result = []
232
+ preorder_recursive(@root, result)
233
+ result
234
+ end
235
+
236
+ def postorder
237
+ result = []
238
+ postorder_recursive(@root, result)
239
+ result
240
+ end
241
+
242
+ private
243
+
244
+ def insert_recursive(node, value)
245
+ return Node.new(value) if node.nil?
246
+
247
+ if value < node.value
248
+ node.left = insert_recursive(node.left, value)
249
+ elsif value > node.value
250
+ node.right = insert_recursive(node.right, value)
251
+ end
252
+
253
+ node
254
+ end
255
+
256
+ def search_recursive(node, value)
257
+ return false if node.nil?
258
+ return true if node.value == value
259
+
260
+ value < node.value ? search_recursive(node.left, value) : search_recursive(node.right, value)
261
+ end
262
+
263
+ def delete_recursive(node, value)
264
+ return nil if node.nil?
265
+
266
+ if value < node.value
267
+ node.left = delete_recursive(node.left, value)
268
+ elsif value > node.value
269
+ node.right = delete_recursive(node.right, value)
270
+ else
271
+ # Node to delete found
272
+ return node.right if node.left.nil?
273
+ return node.left if node.right.nil?
274
+
275
+ # Node has two children
276
+ min_node = find_min_node(node.right)
277
+ node.value = min_node.value
278
+ node.right = delete_recursive(node.right, min_node.value)
279
+ end
280
+
281
+ node
282
+ end
283
+
284
+ def find_min_node(node)
285
+ node = node.left while node.left
286
+ node
287
+ end
288
+
289
+ def inorder_recursive(node, result)
290
+ return if node.nil?
291
+ inorder_recursive(node.left, result)
292
+ result << node.value
293
+ inorder_recursive(node.right, result)
294
+ end
295
+
296
+ def preorder_recursive(node, result)
297
+ return if node.nil?
298
+ result << node.value
299
+ preorder_recursive(node.left, result)
300
+ preorder_recursive(node.right, result)
301
+ end
302
+
303
+ def postorder_recursive(node, result)
304
+ return if node.nil?
305
+ postorder_recursive(node.left, result)
306
+ postorder_recursive(node.right, result)
307
+ result << node.value
308
+ end
8
309
  end
9
310
  end
10
311
  end
@@ -3,8 +3,214 @@ module DSAVisualizer
3
3
  class Deque
4
4
  def self.learn
5
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"
6
+
7
+ puts "\nšŸ“– CONCEPT:"
8
+ puts "A Deque (Double-Ended Queue) allows insertion and deletion at both ends:"
9
+ puts "• Push/Pop from front"
10
+ puts "• Push/Pop from back"
11
+ puts "• Can be used as both stack and queue"
12
+ puts "• Often implemented using circular array or doubly linked list"
13
+
14
+ puts "\nā±ļø TIME COMPLEXITY:"
15
+ puts "• Push front/back: O(1)"
16
+ puts "• Pop front/back: O(1)"
17
+ puts "• Access front/back: O(1)"
18
+ puts "• Search: O(n)"
19
+
20
+ puts "\nšŸ’¾ SPACE COMPLEXITY: O(n)"
21
+
22
+ demonstrate_deque
23
+ demonstrate_operations
24
+ show_ruby_vs_cpp
25
+ show_practice_problems
26
+ end
27
+
28
+ def self.demonstrate_deque
29
+ puts "\n" + "="*60
30
+ puts "DEMONSTRATION: Deque Operations"
31
+ puts "="*60
32
+
33
+ deque = DequeImplementation.new
34
+
35
+ puts "\nPush back: 10, 20, 30"
36
+ deque.push_back(10)
37
+ deque.push_back(20)
38
+ deque.push_back(30)
39
+ deque.display
40
+
41
+ puts "\nPush front: 5, 1"
42
+ deque.push_front(5)
43
+ deque.push_front(1)
44
+ deque.display
45
+
46
+ puts "\nšŸ“Š Current state: [1, 5, 10, 20, 30]"
47
+ puts "Front: #{deque.front}, Back: #{deque.back}"
48
+ end
49
+
50
+ def self.demonstrate_operations
51
+ puts "\n" + "="*60
52
+ puts "DEQUE OPERATIONS"
53
+ puts "="*60
54
+
55
+ deque = DequeImplementation.new
56
+ [10, 20, 30].each { |v| deque.push_back(v) }
57
+
58
+ puts "\n1ļøāƒ£ POP FRONT:"
59
+ puts "Popped: #{deque.pop_front}"
60
+ deque.display
61
+
62
+ puts "\n2ļøāƒ£ POP BACK:"
63
+ puts "Popped: #{deque.pop_back}"
64
+ deque.display
65
+
66
+ puts "\n3ļøāƒ£ USING AS STACK (LIFO):"
67
+ stack_deque = DequeImplementation.new
68
+ stack_deque.push_back(1)
69
+ stack_deque.push_back(2)
70
+ stack_deque.push_back(3)
71
+ puts "Push: 1, 2, 3"
72
+ puts "Pop: #{stack_deque.pop_back}, #{stack_deque.pop_back}"
73
+
74
+ puts "\n4ļøāƒ£ USING AS QUEUE (FIFO):"
75
+ queue_deque = DequeImplementation.new
76
+ queue_deque.push_back(1)
77
+ queue_deque.push_back(2)
78
+ queue_deque.push_back(3)
79
+ puts "Enqueue: 1, 2, 3"
80
+ puts "Dequeue: #{queue_deque.pop_front}, #{queue_deque.pop_front}"
81
+ end
82
+
83
+ def self.show_ruby_vs_cpp
84
+ puts "\n" + "="*60
85
+ puts "RUBY vs C++ IMPLEMENTATION"
86
+ puts "="*60
87
+
88
+ puts "\nšŸ”“ RUBY:"
89
+ puts <<~RUBY
90
+ class Deque
91
+ def initialize
92
+ @items = []
93
+ end
94
+
95
+ def push_front(item)
96
+ @items.unshift(item)
97
+ end
98
+
99
+ def push_back(item)
100
+ @items.push(item)
101
+ end
102
+
103
+ def pop_front
104
+ @items.shift
105
+ end
106
+
107
+ def pop_back
108
+ @items.pop
109
+ end
110
+
111
+ def front
112
+ @items.first
113
+ end
114
+
115
+ def back
116
+ @items.last
117
+ end
118
+ end
119
+ RUBY
120
+
121
+ puts "\nšŸ”µ C++:"
122
+ puts <<~CPP
123
+ #include <deque>
124
+
125
+ std::deque<int> dq;
126
+
127
+ // Operations
128
+ dq.push_front(10); // Add to front
129
+ dq.push_back(20); // Add to back
130
+ dq.pop_front(); // Remove from front
131
+ dq.pop_back(); // Remove from back
132
+
133
+ int front = dq.front(); // Access front
134
+ int back = dq.back(); // Access back
135
+
136
+ // Or manual implementation with circular array
137
+ class Deque {
138
+ int* arr;
139
+ int front, rear, size, capacity;
140
+ public:
141
+ void pushFront(int x) {
142
+ front = (front - 1 + capacity) % capacity;
143
+ arr[front] = x;
144
+ size++;
145
+ }
146
+ };
147
+ CPP
148
+ end
149
+
150
+ def self.show_practice_problems
151
+ puts "\n" + "="*60
152
+ puts "PRACTICE PROBLEMS"
153
+ puts "="*60
154
+
155
+ problems = [
156
+ "1. Sliding window maximum using deque",
157
+ "2. Implement stack using deque",
158
+ "3. Implement queue using deque",
159
+ "4. First negative in every window of size k",
160
+ "5. Maximum of all subarrays of size k",
161
+ "6. Design a data structure with O(1) operations",
162
+ "7. Palindrome checker using deque",
163
+ "8. Deque with min/max in O(1)"
164
+ ]
165
+
166
+ problems.each { |p| puts p }
167
+
168
+ puts "\nšŸ’” TIP: Deque is perfect for sliding window problems!"
169
+ puts "šŸ’” TIP: Ruby's Array class supports deque operations efficiently"
170
+ end
171
+
172
+ class DequeImplementation
173
+ def initialize
174
+ @items = []
175
+ end
176
+
177
+ def push_front(item)
178
+ @items.unshift(item)
179
+ end
180
+
181
+ def push_back(item)
182
+ @items.push(item)
183
+ end
184
+
185
+ def pop_front
186
+ return nil if empty?
187
+ @items.shift
188
+ end
189
+
190
+ def pop_back
191
+ return nil if empty?
192
+ @items.pop
193
+ end
194
+
195
+ def front
196
+ @items.first
197
+ end
198
+
199
+ def back
200
+ @items.last
201
+ end
202
+
203
+ def empty?
204
+ @items.empty?
205
+ end
206
+
207
+ def size
208
+ @items.size
209
+ end
210
+
211
+ def display
212
+ puts "Deque: [#{@items.join(', ')}]"
213
+ end
8
214
  end
9
215
  end
10
216
  end