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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +323 -0
  4. data/USAGE.md +359 -0
  5. data/bin/dsa_visualizer +5 -0
  6. data/lib/dsa_visualizer/algorithms/dynamic_programming.rb +23 -0
  7. data/lib/dsa_visualizer/algorithms/graph_algorithms.rb +23 -0
  8. data/lib/dsa_visualizer/algorithms/greedy.rb +11 -0
  9. data/lib/dsa_visualizer/algorithms/searching.rb +78 -0
  10. data/lib/dsa_visualizer/algorithms/sorting.rb +77 -0
  11. data/lib/dsa_visualizer/algorithms/string_algorithms.rb +11 -0
  12. data/lib/dsa_visualizer/cli.rb +281 -0
  13. data/lib/dsa_visualizer/comparator.rb +57 -0
  14. data/lib/dsa_visualizer/data_structures/array.rb +109 -0
  15. data/lib/dsa_visualizer/data_structures/binary_tree.rb +104 -0
  16. data/lib/dsa_visualizer/data_structures/bst.rb +11 -0
  17. data/lib/dsa_visualizer/data_structures/deque.rb +11 -0
  18. data/lib/dsa_visualizer/data_structures/doubly_linked_list.rb +11 -0
  19. data/lib/dsa_visualizer/data_structures/graph.rb +11 -0
  20. data/lib/dsa_visualizer/data_structures/hash_table.rb +61 -0
  21. data/lib/dsa_visualizer/data_structures/heap.rb +17 -0
  22. data/lib/dsa_visualizer/data_structures/linked_list.rb +197 -0
  23. data/lib/dsa_visualizer/data_structures/priority_queue.rb +11 -0
  24. data/lib/dsa_visualizer/data_structures/queue.rb +110 -0
  25. data/lib/dsa_visualizer/data_structures/stack.rb +207 -0
  26. data/lib/dsa_visualizer/data_structures/string.rb +11 -0
  27. data/lib/dsa_visualizer/data_structures/trie.rb +11 -0
  28. data/lib/dsa_visualizer/data_structures/union_find.rb +11 -0
  29. data/lib/dsa_visualizer/fundamentals/complexity.rb +264 -0
  30. data/lib/dsa_visualizer/fundamentals/memory.rb +285 -0
  31. data/lib/dsa_visualizer/fundamentals/pointers.rb +311 -0
  32. data/lib/dsa_visualizer/fundamentals/recursion.rb +63 -0
  33. data/lib/dsa_visualizer/memory_tracker.rb +49 -0
  34. data/lib/dsa_visualizer/notes_manager.rb +85 -0
  35. data/lib/dsa_visualizer/version.rb +3 -0
  36. data/lib/dsa_visualizer/visualizer.rb +58 -0
  37. data/lib/dsa_visualizer.rb +114 -0
  38. metadata +157 -0
@@ -0,0 +1,285 @@
1
+ module DSAVisualizer
2
+ module Fundamentals
3
+ class Memory
4
+ def self.learn
5
+ Visualizer.print_header("MEMORY MANAGEMENT - How Data Lives in Computer Memory")
6
+
7
+ # Introduction
8
+ puts "\nšŸ“– UNDERSTANDING COMPUTER MEMORY".colorize(:cyan).bold
9
+ puts "─" * 80
10
+ puts "Memory is organized in a hierarchy:"
11
+ puts " Registers (fastest, smallest) → Cache → RAM → Disk (slowest, largest)"
12
+ puts "\nWe primarily work with RAM (Random Access Memory)"
13
+
14
+ # Memory Layout
15
+ Visualizer.print_section("1. Memory Layout of a Program")
16
+ puts "\nā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” High Address"
17
+ puts "│ Command Line Args │"
18
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
19
+ puts "│ Stack │ ← Grows downward"
20
+ puts "│ (Local variables) │ Function calls"
21
+ puts "│ (Function calls) │ Automatic cleanup"
22
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
23
+ puts "│ ↓ │"
24
+ puts "│ │"
25
+ puts "│ ↑ │"
26
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
27
+ puts "│ Heap │ ← Grows upward"
28
+ puts "│ (Dynamic memory) │ Manual/GC managed"
29
+ puts "│ (Objects) │ Flexible size"
30
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
31
+ puts "│ BSS (Uninitialized)│"
32
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
33
+ puts "│ Data (Initialized)│"
34
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
35
+ puts "│ Text (Code) │"
36
+ puts "ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ Low Address"
37
+
38
+ # Stack vs Heap
39
+ Visualizer.print_section("2. Stack vs Heap Memory")
40
+
41
+ puts "\nšŸ”µ STACK MEMORY:".colorize(:blue).bold
42
+ puts " • Fast allocation/deallocation (just move stack pointer)"
43
+ puts " • Limited size (typically 1-8 MB)"
44
+ puts " • Automatic cleanup (LIFO - Last In First Out)"
45
+ puts " • Stores: local variables, function parameters, return addresses"
46
+ puts " • Contiguous memory"
47
+
48
+ puts "\n🟢 HEAP MEMORY:".colorize(:green).bold
49
+ puts " • Slower allocation (must find free block)"
50
+ puts " • Large size (limited by system RAM)"
51
+ puts " • Manual management (C++) or Garbage Collection (Ruby)"
52
+ puts " • Stores: dynamically allocated objects, large data structures"
53
+ puts " • Fragmented memory possible"
54
+
55
+ # Ruby vs C++ Memory Management
56
+ Visualizer.print_section("3. Ruby vs C++ Memory Management")
57
+
58
+ ruby_code = <<~RUBY
59
+ # Ruby - Automatic Memory Management
60
+ def create_array
61
+ arr = [1, 2, 3, 4, 5] # Heap allocated
62
+ # Ruby's GC will clean up automatically
63
+ arr
64
+ end
65
+
66
+ result = create_array
67
+ # 'arr' in function is gone (stack)
68
+ # but array object still exists (heap)
69
+ # GC tracks references
70
+
71
+ # When no references exist:
72
+ result = nil # Array becomes eligible for GC
73
+ RUBY
74
+
75
+ cpp_code = <<~CPP
76
+ // C++ - Manual Memory Management
77
+ int* createArray() {
78
+ int* arr = new int[5]{1,2,3,4,5}; // Heap
79
+ // Must manually delete!
80
+ return arr;
81
+ }
82
+
83
+ int* result = createArray();
84
+ // Use the array...
85
+
86
+ delete[] result; // MUST free memory!
87
+ result = nullptr; // Good practice
88
+
89
+ // Forgetting delete[] = memory leak!
90
+ CPP
91
+
92
+ Visualizer.print_comparison(ruby_code, cpp_code,
93
+ "Ruby uses Garbage Collection (automatic). C++ requires manual memory management with new/delete.")
94
+
95
+ # Stack Example
96
+ Visualizer.print_section("4. Stack Memory Example")
97
+
98
+ ruby_code = <<~RUBY
99
+ def factorial(n)
100
+ return 1 if n <= 1
101
+ n * factorial(n - 1)
102
+ end
103
+
104
+ factorial(4)
105
+
106
+ # Call Stack:
107
+ # factorial(4) → calls factorial(3)
108
+ # factorial(3) → calls factorial(2)
109
+ # factorial(2) → calls factorial(1)
110
+ # factorial(1) → returns 1
111
+ # Then unwinds: 2*1, 3*2, 4*6 = 24
112
+ RUBY
113
+
114
+ cpp_code = <<~CPP
115
+ int factorial(int n) {
116
+ if(n <= 1) return 1;
117
+ return n * factorial(n - 1);
118
+ }
119
+
120
+ factorial(4);
121
+
122
+ // Stack frames:
123
+ // [factorial(4)] ← top
124
+ // [factorial(3)]
125
+ // [factorial(2)]
126
+ // [factorial(1)] ← base
127
+ // Each frame stores: n, return address
128
+ CPP
129
+
130
+ puts "\nStack Frame Visualization:"
131
+ puts "ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”"
132
+ puts "│ factorial(4) │ ← Current"
133
+ puts "│ n=4, ret_addr │"
134
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
135
+ puts "│ factorial(3) │"
136
+ puts "│ n=3, ret_addr │"
137
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
138
+ puts "│ factorial(2) │"
139
+ puts "│ n=2, ret_addr │"
140
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
141
+ puts "│ factorial(1) │"
142
+ puts "│ n=1, ret_addr │"
143
+ puts "ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜"
144
+
145
+ Visualizer.print_comparison(ruby_code, cpp_code,
146
+ "Both use call stack for recursion. Deep recursion can cause stack overflow!")
147
+
148
+ # Heap Example
149
+ Visualizer.print_section("5. Heap Memory Example")
150
+
151
+ ruby_code = <<~RUBY
152
+ class Node
153
+ attr_accessor :data, :next
154
+ def initialize(data)
155
+ @data = data
156
+ @next = nil
157
+ end
158
+ end
159
+
160
+ # Creating linked list
161
+ head = Node.new(10) # Heap allocated
162
+ head.next = Node.new(20) # Heap allocated
163
+ head.next.next = Node.new(30)
164
+
165
+ # All Node objects on heap
166
+ # GC tracks references
167
+ # When head = nil, all become eligible for GC
168
+ RUBY
169
+
170
+ cpp_code = <<~CPP
171
+ struct Node {
172
+ int data;
173
+ Node* next;
174
+ };
175
+
176
+ // Creating linked list
177
+ Node* head = new Node{10, nullptr};
178
+ head->next = new Node{20, nullptr};
179
+ head->next->next = new Node{30, nullptr};
180
+
181
+ // Must manually free each node!
182
+ Node* temp;
183
+ while(head) {
184
+ temp = head;
185
+ head = head->next;
186
+ delete temp; // Free each node
187
+ }
188
+ CPP
189
+
190
+ Visualizer.print_comparison(ruby_code, cpp_code,
191
+ "Heap allows dynamic sizing. Ruby's GC vs C++'s manual delete. Memory leaks happen when you forget to free!")
192
+
193
+ # Memory Leaks
194
+ Visualizer.print_section("6. Memory Leaks")
195
+
196
+ puts "\nāŒ Common Memory Leak in C++:"
197
+ puts "```cpp"
198
+ puts "void leak() {"
199
+ puts " int* arr = new int[1000];"
200
+ puts " // Forgot to delete[]!"
201
+ puts " // Memory is lost forever (until program ends)"
202
+ puts "}"
203
+ puts "```"
204
+
205
+ puts "\nāœ… Proper Memory Management:"
206
+ puts "```cpp"
207
+ puts "void noLeak() {"
208
+ puts " int* arr = new int[1000];"
209
+ puts " // Use the array..."
210
+ puts " delete[] arr; // Clean up!"
211
+ puts "}"
212
+ puts "```"
213
+
214
+ puts "\nāœ… Modern C++ (RAII - Resource Acquisition Is Initialization):"
215
+ puts "```cpp"
216
+ puts "void modern() {"
217
+ puts " std::vector<int> arr(1000); // Automatic cleanup!"
218
+ puts " std::unique_ptr<int[]> ptr(new int[1000]);"
219
+ puts " // Automatically deleted when out of scope"
220
+ puts "}"
221
+ puts "```"
222
+
223
+ # Cache Locality
224
+ Visualizer.print_section("7. Cache Locality & Performance")
225
+
226
+ puts "\nCPU Cache is much faster than RAM:"
227
+ puts " L1 Cache: ~1 ns"
228
+ puts " L2 Cache: ~4 ns"
229
+ puts " L3 Cache: ~10 ns"
230
+ puts " RAM: ~100 ns"
231
+
232
+ puts "\nšŸš€ Good Cache Locality (Array):"
233
+ puts " [1][2][3][4][5] ← Contiguous memory"
234
+ puts " CPU loads chunk into cache"
235
+ puts " Accessing next element is fast (already in cache)"
236
+
237
+ puts "\n🐌 Poor Cache Locality (Linked List):"
238
+ puts " [1]→...→[2]→...→[3]→...→[4] ← Scattered memory"
239
+ puts " Each access might miss cache"
240
+ puts " Must fetch from RAM (100Ɨ slower!)"
241
+
242
+ # Important Notes
243
+ notes = [
244
+ "Stack: Fast, automatic, limited size, LIFO structure",
245
+ "Heap: Flexible, larger, requires management (manual or GC)",
246
+ "Ruby uses Garbage Collection - automatic but has overhead",
247
+ "C++ requires manual memory management - fast but error-prone",
248
+ "Modern C++ uses RAII and smart pointers for safety",
249
+ "Stack overflow happens with deep recursion or large local arrays",
250
+ "Memory leaks occur when heap memory isn't freed",
251
+ "Cache locality matters - contiguous memory is faster",
252
+ "Pointer size: 8 bytes on 64-bit systems, 4 bytes on 32-bit"
253
+ ]
254
+ NotesManager.print_notes("Memory Management", notes)
255
+
256
+ # Key Points
257
+ key_points = [
258
+ "Stack is for local variables, Heap is for dynamic allocation",
259
+ "Ruby's GC trades performance for safety and convenience",
260
+ "C++ gives control but requires discipline (use smart pointers!)",
261
+ "Arrays have better cache locality than linked lists",
262
+ "Deep recursion uses stack memory - can cause overflow",
263
+ "Always free what you allocate in C++ (or use RAII)",
264
+ "Memory alignment affects performance (CPU reads in chunks)"
265
+ ]
266
+ NotesManager.print_key_points(key_points)
267
+
268
+ # Common Mistakes
269
+ mistakes = [
270
+ "Forgetting to delete[] in C++ (memory leak)",
271
+ "Deleting same memory twice (double free - crash!)",
272
+ "Using memory after freeing it (dangling pointer)",
273
+ "Creating too deep recursion (stack overflow)",
274
+ "Allocating huge arrays on stack (use heap instead)",
275
+ "Not considering cache locality in performance-critical code"
276
+ ]
277
+ NotesManager.print_common_mistakes(mistakes)
278
+
279
+ puts "\nšŸ’” PRO TIP:".colorize(:yellow).bold
280
+ puts "In C++, prefer std::vector over raw arrays, and std::unique_ptr/shared_ptr"
281
+ puts "over raw pointers. They provide automatic memory management!"
282
+ end
283
+ end
284
+ end
285
+ end
@@ -0,0 +1,311 @@
1
+ module DSAVisualizer
2
+ module Fundamentals
3
+ class Pointers
4
+ def self.learn
5
+ Visualizer.print_header("POINTERS & REFERENCES - The Foundation of Data Structures")
6
+
7
+ puts "\nšŸ“– WHAT ARE POINTERS?".colorize(:cyan).bold
8
+ puts "─" * 80
9
+ puts "A pointer is a variable that stores a memory address."
10
+ puts "It 'points to' another variable's location in memory."
11
+
12
+ # Basic Concept
13
+ Visualizer.print_section("1. Pointer Basics")
14
+
15
+ puts "\nMemory Visualization:"
16
+ puts "ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”"
17
+ puts "│ Address │ Name │ Value │"
18
+ puts "ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤"
19
+ puts "│ 0x1000 │ x │ 42 │ ← Regular variable"
20
+ puts "│ 0x1004 │ ptr │ 0x1000 │ ← Pointer (stores address of x)"
21
+ puts "ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜"
22
+
23
+ # Ruby vs C++
24
+ Visualizer.print_section("2. Ruby References vs C++ Pointers")
25
+
26
+ ruby_code = <<~RUBY
27
+ # Ruby - No explicit pointers
28
+ # Everything is an object reference
29
+
30
+ x = 42
31
+ y = x # y references same object
32
+
33
+ puts x.object_id # Memory address
34
+ puts y.object_id # Same address!
35
+
36
+ # For immutable objects (numbers, symbols):
37
+ x = 43 # Creates NEW object
38
+ # y still references old object (42)
39
+
40
+ # For mutable objects (arrays, hashes):
41
+ arr1 = [1, 2, 3]
42
+ arr2 = arr1 # Both reference same array
43
+ arr2 << 4 # Modifies shared array
44
+ puts arr1 # [1, 2, 3, 4]
45
+ RUBY
46
+
47
+ cpp_code = <<~CPP
48
+ // C++ - Explicit pointers
49
+
50
+ int x = 42;
51
+ int* ptr = &x; // ptr stores address of x
52
+
53
+ cout << x; // 42 (value)
54
+ cout << &x; // 0x1000 (address)
55
+ cout << ptr; // 0x1000 (address stored in ptr)
56
+ cout << *ptr; // 42 (dereference - get value)
57
+
58
+ *ptr = 43; // Modify x through pointer
59
+ cout << x; // 43 (x changed!)
60
+
61
+ // Pointer arithmetic
62
+ int arr[] = {1, 2, 3};
63
+ int* p = arr; // Points to first element
64
+ p++; // Now points to second element
65
+ cout << *p; // 2
66
+ CPP
67
+
68
+ Visualizer.print_comparison(ruby_code, cpp_code,
69
+ "Ruby uses implicit references (managed by GC). C++ uses explicit pointers (manual control).")
70
+
71
+ # Pointer Operations
72
+ Visualizer.print_section("3. C++ Pointer Operations")
73
+
74
+ puts "\nšŸ”¹ Declaration:"
75
+ puts " int* ptr; // Pointer to int"
76
+ puts " int *ptr; // Same thing (style choice)"
77
+ puts " int* p1, p2; // p1 is pointer, p2 is int! (confusing)"
78
+ puts " int *p1, *p2; // Both are pointers"
79
+
80
+ puts "\nšŸ”¹ Address-of operator (&):"
81
+ puts " int x = 10;"
82
+ puts " int* ptr = &x; // Get address of x"
83
+
84
+ puts "\nšŸ”¹ Dereference operator (*):"
85
+ puts " int value = *ptr; // Get value at address"
86
+ puts " *ptr = 20; // Set value at address"
87
+
88
+ puts "\nšŸ”¹ Null pointer:"
89
+ puts " int* ptr = nullptr; // C++11 (preferred)"
90
+ puts " int* ptr = NULL; // Old style"
91
+ puts " int* ptr = 0; // Also works"
92
+
93
+ # Pointer Arithmetic
94
+ Visualizer.print_section("4. Pointer Arithmetic")
95
+
96
+ puts "\nArray in memory:"
97
+ puts "ā”Œā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”"
98
+ puts "│ 10 │ 20 │ 30 │ 40 │ 50 │"
99
+ puts "ā””ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”˜"
100
+ puts "0x100 0x104 0x108 0x10C 0x110 (each int = 4 bytes)"
101
+
102
+ cpp_code = <<~CPP
103
+ int arr[] = {10, 20, 30, 40, 50};
104
+ int* ptr = arr; // Points to arr[0]
105
+
106
+ cout << *ptr; // 10
107
+ cout << *(ptr+1); // 20 (moves 4 bytes, not 1!)
108
+ cout << *(ptr+2); // 30
109
+
110
+ ptr++; // Now points to arr[1]
111
+ cout << *ptr; // 20
112
+
113
+ // Array indexing is pointer arithmetic!
114
+ arr[2] == *(arr + 2) // TRUE!
115
+ CPP
116
+
117
+ puts "\n#{cpp_code}"
118
+ puts "\nšŸ’” Key Insight: ptr+1 doesn't add 1 byte, it adds sizeof(int) bytes!"
119
+ puts " The compiler knows the type and adjusts automatically."
120
+
121
+ # Pointers and Arrays
122
+ Visualizer.print_section("5. Pointers and Arrays")
123
+
124
+ cpp_code = <<~CPP
125
+ int arr[5] = {1, 2, 3, 4, 5};
126
+ int* ptr = arr; // Array name is pointer to first element
127
+
128
+ // These are equivalent:
129
+ arr[0] == *arr == *(arr + 0)
130
+ arr[1] == *(arr+1) == ptr[1]
131
+ arr[2] == *(ptr+2) == ptr[2]
132
+
133
+ // Passing array to function:
134
+ void process(int* arr, int size) {
135
+ // arr is just a pointer!
136
+ // Size information is lost
137
+ }
138
+ CPP
139
+
140
+ puts "\n#{cpp_code}"
141
+
142
+ # Pointers in Data Structures
143
+ Visualizer.print_section("6. Pointers in Data Structures")
144
+
145
+ puts "\nšŸ”— Linked List Node:"
146
+ cpp_code = <<~CPP
147
+ struct Node {
148
+ int data;
149
+ Node* next; // Pointer to next node
150
+ };
151
+
152
+ Node* head = new Node{10, nullptr};
153
+ head->next = new Node{20, nullptr};
154
+ head->next->next = new Node{30, nullptr};
155
+
156
+ // Traversal:
157
+ Node* current = head;
158
+ while(current != nullptr) {
159
+ cout << current->data;
160
+ current = current->next; // Move to next node
161
+ }
162
+ CPP
163
+ puts cpp_code
164
+
165
+ puts "\n🌳 Binary Tree Node:"
166
+ cpp_code = <<~CPP
167
+ struct TreeNode {
168
+ int data;
169
+ TreeNode* left; // Pointer to left child
170
+ TreeNode* right; // Pointer to right child
171
+ };
172
+
173
+ TreeNode* root = new TreeNode{50, nullptr, nullptr};
174
+ root->left = new TreeNode{30, nullptr, nullptr};
175
+ root->right = new TreeNode{70, nullptr, nullptr};
176
+ CPP
177
+ puts cpp_code
178
+
179
+ # Ruby Equivalent
180
+ Visualizer.print_section("7. Ruby's Object References")
181
+
182
+ ruby_code = <<~RUBY
183
+ # Ruby doesn't have pointers, but references work similarly
184
+
185
+ class Node
186
+ attr_accessor :data, :next
187
+ def initialize(data)
188
+ @data = data
189
+ @next = nil # Reference to next node
190
+ end
191
+ end
192
+
193
+ head = Node.new(10)
194
+ head.next = Node.new(20)
195
+ head.next.next = Node.new(30)
196
+
197
+ # Traversal:
198
+ current = head
199
+ while current
200
+ puts current.data
201
+ current = current.next # Follow reference
202
+ end
203
+
204
+ # Key difference: No manual memory management!
205
+ # GC handles cleanup automatically
206
+ RUBY
207
+
208
+ puts ruby_code
209
+
210
+ # Common Pointer Errors
211
+ Visualizer.print_section("8. Common Pointer Errors (C++)")
212
+
213
+ puts "\nāŒ 1. Dangling Pointer:"
214
+ puts "```cpp"
215
+ puts "int* ptr = new int(42);"
216
+ puts "delete ptr;"
217
+ puts "cout << *ptr; // ERROR! Memory freed, pointer still points there"
218
+ puts "ptr = nullptr; // Good practice after delete"
219
+ puts "```"
220
+
221
+ puts "\nāŒ 2. Memory Leak:"
222
+ puts "```cpp"
223
+ puts "int* ptr = new int(42);"
224
+ puts "ptr = new int(100); // Lost reference to first allocation!"
225
+ puts "// First allocation leaked - can't free it now"
226
+ puts "```"
227
+
228
+ puts "\nāŒ 3. Null Pointer Dereference:"
229
+ puts "```cpp"
230
+ puts "int* ptr = nullptr;"
231
+ puts "cout << *ptr; // CRASH! Can't dereference null"
232
+ puts "// Always check: if(ptr != nullptr) { *ptr = 10; }"
233
+ puts "```"
234
+
235
+ puts "\nāŒ 4. Wild Pointer:"
236
+ puts "```cpp"
237
+ puts "int* ptr; // Uninitialized! Contains garbage"
238
+ puts "*ptr = 42; // CRASH! Writing to random memory"
239
+ puts "// Always initialize: int* ptr = nullptr;"
240
+ puts "```"
241
+
242
+ # Smart Pointers
243
+ Visualizer.print_section("9. Modern C++ Smart Pointers")
244
+
245
+ puts "\nāœ… Smart pointers provide automatic memory management:"
246
+
247
+ cpp_code = <<~CPP
248
+ #include <memory>
249
+
250
+ // unique_ptr - Single ownership
251
+ std::unique_ptr<int> ptr1(new int(42));
252
+ // or better:
253
+ auto ptr1 = std::make_unique<int>(42);
254
+ // Automatically deleted when out of scope!
255
+
256
+ // shared_ptr - Shared ownership (reference counting)
257
+ std::shared_ptr<int> ptr2 = std::make_shared<int>(42);
258
+ std::shared_ptr<int> ptr3 = ptr2; // Both own it
259
+ // Deleted when last shared_ptr goes out of scope
260
+
261
+ // weak_ptr - Non-owning reference (breaks cycles)
262
+ std::weak_ptr<int> ptr4 = ptr2;
263
+ // Doesn't prevent deletion
264
+ CPP
265
+
266
+ puts cpp_code
267
+
268
+ # Notes
269
+ notes = [
270
+ "Pointer stores memory address, not the value itself",
271
+ "& (address-of) gets address, * (dereference) gets value",
272
+ "Ruby uses implicit references, C++ uses explicit pointers",
273
+ "Array name is pointer to first element in C++",
274
+ "Pointer arithmetic: ptr+1 moves by sizeof(type) bytes",
275
+ "Always initialize pointers (nullptr in C++)",
276
+ "Check for nullptr before dereferencing",
277
+ "Use smart pointers in modern C++ (unique_ptr, shared_ptr)",
278
+ "Ruby's GC eliminates pointer management complexity"
279
+ ]
280
+ NotesManager.print_notes("Pointers & References", notes)
281
+
282
+ # Key Points
283
+ key_points = [
284
+ "Pointers enable dynamic data structures (linked lists, trees, graphs)",
285
+ "Ruby abstracts pointers as object references with automatic GC",
286
+ "C++ pointers give control but require careful management",
287
+ "Null pointer dereference is a common crash cause",
288
+ "Memory leaks happen when you lose pointer to allocated memory",
289
+ "Smart pointers (C++11+) provide safety with RAII",
290
+ "Understanding pointers is crucial for DSA implementation"
291
+ ]
292
+ NotesManager.print_key_points(key_points)
293
+
294
+ # Common Mistakes
295
+ mistakes = [
296
+ "Dereferencing null or uninitialized pointer (crash!)",
297
+ "Using pointer after freeing memory (dangling pointer)",
298
+ "Forgetting to free allocated memory (memory leak)",
299
+ "Confusing pointer and value (missing * or &)",
300
+ "Array out of bounds with pointer arithmetic",
301
+ "Double-freeing same memory (crash!)"
302
+ ]
303
+ NotesManager.print_common_mistakes(mistakes)
304
+
305
+ puts "\nšŸ’” PRO TIP:".colorize(:yellow).bold
306
+ puts "In C++, prefer references (&) for function parameters when you don't need"
307
+ puts "pointer arithmetic or reassignment. Use smart pointers for ownership."
308
+ end
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,63 @@
1
+ module DSAVisualizer
2
+ module Fundamentals
3
+ class Recursion
4
+ def self.learn
5
+ Visualizer.print_header("RECURSION - Function Calling Itself")
6
+
7
+ puts "\nšŸ“– WHAT IS RECURSION?".colorize(:cyan).bold
8
+ puts "─" * 80
9
+ puts "Recursion is when a function calls itself to solve a problem"
10
+ puts "by breaking it down into smaller subproblems."
11
+
12
+ Visualizer.print_section("1. Basic Recursion Example")
13
+
14
+ ruby_code = <<~RUBY
15
+ def factorial(n)
16
+ return 1 if n <= 1 # Base case
17
+ n * factorial(n - 1) # Recursive case
18
+ end
19
+
20
+ factorial(5)
21
+ # 5 * factorial(4)
22
+ # 5 * 4 * factorial(3)
23
+ # 5 * 4 * 3 * factorial(2)
24
+ # 5 * 4 * 3 * 2 * factorial(1)
25
+ # 5 * 4 * 3 * 2 * 1 = 120
26
+ RUBY
27
+
28
+ cpp_code = <<~CPP
29
+ int factorial(int n) {
30
+ if(n <= 1) return 1; // Base case
31
+ return n * factorial(n - 1); // Recursive
32
+ }
33
+
34
+ factorial(5);
35
+ // Call stack grows then unwinds
36
+ // Space: O(n) due to call stack
37
+ CPP
38
+
39
+ Visualizer.print_comparison(ruby_code, cpp_code,
40
+ "Both use call stack. Each recursive call adds a stack frame. Must have base case to stop!")
41
+
42
+ notes = [
43
+ "Every recursion needs a base case (stopping condition)",
44
+ "Recursive case must progress toward base case",
45
+ "Space complexity: O(n) for call stack depth n",
46
+ "Can cause stack overflow if too deep",
47
+ "Some recursions can be optimized with tail call optimization",
48
+ "Iterative solutions often more efficient (no stack overhead)"
49
+ ]
50
+ NotesManager.print_notes("Recursion", notes)
51
+
52
+ key_points = [
53
+ "Recursion = function calling itself",
54
+ "Base case prevents infinite recursion",
55
+ "Call stack stores each recursive call",
56
+ "Useful for tree/graph traversal, divide-and-conquer",
57
+ "Trade-off: elegant code vs stack space"
58
+ ]
59
+ NotesManager.print_key_points(key_points)
60
+ end
61
+ end
62
+ end
63
+ end