Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_indexGraph_example.cc
Go to the documentation of this file.
1
34#include <iostream>
35#include <chrono>
36#include <tpl_indexGraph.H>
37#include <tpl_graph.H>
38
39using namespace std;
40using namespace Aleph;
41using namespace std::chrono;
42
43int main()
44{
45 cout << "=== Indexed Graphs: Educational Examples ===\n\n";
46
47 // =========================================================================
48 // EXAMPLE 1: Basic Indexed Graph Operations
49 // =========================================================================
50 // CONCEPT: Index_Graph wraps a regular graph and adds search trees
51 // BENEFIT: O(log n) search instead of O(n) linear scan
52 {
53 cout << "--- Example 1: Basic Operations ---\n\n";
54
55 // STEP 1: Create graph type with integer node values
57 GT g; // The underlying graph
58
59 // STEP 2: Wrap it with Index_Graph for fast lookups
60 // Index_Graph maintains a binary search tree of nodes
61 Index_Graph<GT> idx(g);
62
63 cout << "Creating indexed graph with integer nodes...\n";
64
65 // STEP 3: Insert nodes using indexed interface
66 // This automatically adds nodes to BOTH graph AND index
67 auto n1 = idx.insert_node(100);
68 auto n2 = idx.insert_node(200);
69 auto n3 = idx.insert_node(150);
70 auto n4 = idx.insert_node(50);
71 (void)n4;
72
73 cout << "Inserted nodes: 100, 200, 150, 50\n";
74 cout << "Index maintains sorted order for O(log n) search\n\n";
75
76 // STEP 4: Fast O(log n) search by value
77 cout << "SEARCH DEMONSTRATION:\n";
78
79 auto found = idx.search_node(150);
80 if (found)
81 cout << " search_node(150): FOUND (O(log n) time!)\n";
82 else
83 cout << " search_node(150): NOT FOUND\n";
84
85 auto not_found = idx.search_node(999);
86 if (not_found)
87 cout << " search_node(999): FOUND\n";
88 else
89 cout << " search_node(999): NOT FOUND (O(log n) time!)\n";
90
91 // STEP 5: Insert arcs
92 idx.insert_arc(n1, n2, 10); // 100 -> 200, weight 10
93 idx.insert_arc(n1, n3, 5); // 100 -> 150, weight 5
94
95 cout << "\nInserted 2 arcs\n";
96
97 // STEP 6: Fast arc search
98 auto arc = idx.search_arc(n1, n2);
99 if (arc)
100 cout << "Found arc 100->200 with weight: " << arc->get_info() << "\n\n";
101
102 // KEY INSIGHT: Compare this to linear search
103 cout << "KEY INSIGHT: Without indexing, search_node() would scan ALL nodes\n";
104 cout << " With indexing: O(log n) binary search tree lookup\n";
105 cout << " For n=1000 nodes: 1000 vs ~10 comparisons!\n\n";
106 }
107
108 // =========================================================================
109 // EXAMPLE 2: Duplicate Prevention
110 // =========================================================================
111 // CONCEPT: Index automatically prevents duplicate node values
112 // BENEFIT: Data integrity without manual checks
113 {
114 cout << "--- Example 2: Automatic Duplicate Prevention ---\n\n";
115
117 GT g;
118 Index_Graph<GT> idx(g);
119
120 // STEP 1: Insert unique nodes (succeeds)
121 cout << "Inserting unique nodes...\n";
122 auto alice = idx.insert_node("Alice");
123 auto bob = idx.insert_node("Bob");
124 auto charlie = idx.insert_node("Charlie");
125 (void)alice;
126 (void)bob;
127 (void)charlie;
128
129 cout << " Inserted: Alice, Bob, Charlie\n";
130 cout << " Graph size: " << g.get_num_nodes() << " nodes\n\n";
131
132 // STEP 2: Try to insert duplicate (fails silently or returns existing)
133 cout << "Attempting to insert duplicate 'Bob'...\n";
134 auto bob2 = idx.search_node("Bob"); // Check if exists first
135 if (bob2)
136 {
137 cout << " PREVENTED: 'Bob' already exists in index\n";
138 cout << " Returned pointer to existing node\n";
139 }
140
141 cout << " Graph size still: " << g.get_num_nodes() << " nodes\n\n";
142
143 // PRACTICAL USE: Social network with unique usernames
144 cout << "REAL-WORLD APPLICATION:\n";
145 cout << " Social Network: Usernames must be unique\n";
146 cout << " Database: Primary keys must be unique\n";
147 cout << " Directory: File names in same folder must be unique\n\n";
148 }
149
150 // =========================================================================
151 // EXAMPLE 3: Performance Comparison
152 // =========================================================================
153 // DEMONSTRATION: Show the speedup from indexing
154 {
155 cout << "--- Example 3: Performance Comparison ---\n\n";
156
158
159 const int N = 1000; // Number of nodes
160 cout << "Creating graph with " << N << " nodes...\n\n";
161
162 // Create indexed graph
165
166 // Insert N nodes
167 for (int i = 0; i < N; ++i)
168 idx.insert_node(i);
169
170 // BENCHMARK: Search for nodes
171 cout << "BENCHMARK: Searching for 100 random nodes\n\n";
172
173 // Test indexed search
174 auto start = high_resolution_clock::now();
175 int found_count = 0;
176 for (int i = 0; i < 100; ++i)
177 {
178 int search_val = (i * 37) % N; // Pseudo-random
179 if (idx.search_node(search_val))
180 found_count++;
181 }
182 auto end = high_resolution_clock::now();
183 auto indexed_time = duration_cast<microseconds>(end - start).count();
184
185 cout << "Indexed Graph (O(log n) search):\n";
186 cout << " Found " << found_count << " nodes\n";
187 cout << " Time: " << indexed_time << " microseconds\n\n";
188
189 // Simulate linear search cost
190 // For 1000 nodes: log2(1000) ≈ 10 vs 500 average comparisons
191 double speedup = (N / 2.0) / log2(N);
192
193 cout << "THEORETICAL SPEEDUP:\n";
194 cout << " Linear search: O(n) = ~" << (N/2) << " comparisons average\n";
195 cout << " Indexed search: O(log n) = ~" << (int)log2(N) << " comparisons\n";
196 cout << " Speedup factor: ~" << (int)speedup << "x faster!\n\n";
197
198 cout << "CONCLUSION: For large graphs (n > 1000), indexing is ESSENTIAL\n\n";
199 }
200
201 // =========================================================================
202 // EXAMPLE 4: Dynamic Updates
203 // =========================================================================
204 // CONCEPT: Index automatically updates when graph changes
205 {
206 cout << "--- Example 4: Dynamic Graph Updates ---\n\n";
207
209 GT g;
210 Index_Graph<GT> idx(g);
211
212 // Insert initial nodes
213 cout << "Initial graph: ";
214 for (int i = 1; i <= 5; ++i)
215 {
216 idx.insert_node(i * 10);
217 cout << (i*10) << " ";
218 }
219 cout << "\n";
220
221 // Add more nodes dynamically
222 cout << "\nAdding nodes 25, 35, 45...\n";
223 idx.insert_node(25);
224 idx.insert_node(35);
225 idx.insert_node(45);
226
227 // Index automatically maintains sort order
228 cout << "All nodes still searchable in O(log n)\n";
229 cout << "Index: ";
230
231 // The index maintains sorted order internally
232 for (int val : {10, 20, 25, 30, 35, 40, 45, 50})
233 {
234 if (idx.search_node(val))
235 cout << val << " ";
236 }
237 cout << "\n\n";
238
239 cout << "KEY FEATURE: Index self-balances (uses treaps by default)\n";
240 cout << " Maintains O(log n) search even after many updates\n\n";
241 }
242
243 cout << "=== SUMMARY: When to Use Index_Graph ===\n";
244 cout << "\n1. GRAPH SIZE:\n";
245 cout << " - Small graphs (n < 100): Regular graph is fine\n";
246 cout << " - Medium graphs (100 < n < 1000): Indexing helps\n";
247 cout << " - Large graphs (n > 1000): Indexing is ESSENTIAL\n";
248 cout << "\n2. ACCESS PATTERN:\n";
249 cout << " Use indexing if you frequently:\n";
250 cout << " * Search for nodes by value\n";
251 cout << " * Check if arc exists between two nodes\n";
252 cout << " * Need to prevent duplicate nodes\n";
253 cout << "\n3. TRADE-OFFS:\n";
254 cout << " Benefits: O(log n) search vs O(n)\n";
255 cout << " Cost: Extra memory + slightly slower inserts\n";
256 cout << "\n4. REAL-WORLD EXAMPLES:\n";
257 cout << " * Social networks (find user by name)\n";
258 cout << " * Road networks (find city by name)\n";
259 cout << " * Dependency graphs (find package by name)\n";
260 cout << " * Database relations (indexed foreign keys)\n";
261 cout << "\n5. COMPLEXITY SUMMARY:\n";
262 cout << " Operation | Regular | Indexed | Speedup\n";
263 cout << " ------------------|---------|----------|--------\n";
264 cout << " Insert node | O(1) | O(log n) | Slower\n";
265 cout << " Search node | O(n) | O(log n) | n/log n\n";
266 cout << " Search arc | O(deg) | O(log m) | High\n";
267 cout << " Memory | O(n+m) | O(n+m) | Same\n";
268
269 return 0;
270}
Construye índices de nodos y arcos para su rápida búsqueda y recuperación.
GT_Node * search_node(GT_Node *p)
Busca en el índice un nodo.
GT_Arc * search_arc(GT_Node *src, GT_Node *tgt)
Busca en el índice un arco dados dos nodos.
GT_Node * insert_node(const GT_Node_Type &info)
Crea un nuevo nodo y lo inserta en grafo y en el índice.
GT_Arc * insert_arc(GT_Node *src, GT_Node *tgt, const GT_Arc_Type &info=GT_Arc_Type())
Crea un nuevo arco entre dos nodos y lo inserta en el grafo y en el índice.
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
#define N
Definition fib.C:294
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_log2_function > > log2(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4064
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
Generic graph and digraph implementations.
Graph indexing utilities for O(log n) node/arc lookup.