Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
quadtree_test.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
39#include <gtest/gtest.h>
40#include <quadtree.H>
41#include <random>
42#include <algorithm>
43#include <unordered_set>
44#include <sstream>
45
46// ============================================================================
47// Basic Functionality Tests
48// ============================================================================
49
51{
52 QuadTree tree(0, 100, 0, 100, 4);
53
54 EXPECT_NE(tree.get_root(), nullptr);
56}
57
59{
60 EXPECT_THROW((QuadTree(0, 0, 0, 100, 1)), std::domain_error);
61 EXPECT_THROW((QuadTree(100, 0, 0, 100, 1)), std::domain_error);
62 EXPECT_THROW((QuadTree(0, 100, 7, 7, 1)), std::domain_error);
63 EXPECT_THROW((QuadTree(0, 100, 100, 0, 1)), std::domain_error);
64 EXPECT_THROW((QuadTree(0, 100, 0, 100, 0)), std::domain_error);
65
66 QuadTree tree(0, 100, 0, 100, 4);
67 EXPECT_THROW(tree.set_max_num_points_per_node(0), std::domain_error);
69}
70
72{
73 QuadNode node(0, 10, 0, 10);
74 EXPECT_THROW(node.set_region(5, 5, 0, 10), std::domain_error);
75 EXPECT_EQ(node.get_min_x(), 0);
76 EXPECT_EQ(node.get_max_x(), 10);
77 EXPECT_EQ(node.get_min_y(), 0);
78 EXPECT_EQ(node.get_max_y(), 10);
79}
80
82{
83 QuadTree tree(0, 100, 0, 100, 4);
84
85 Point * inserted = tree.insert(Point(50, 50));
86
87 ASSERT_NE(inserted, nullptr);
88 EXPECT_EQ(inserted->get_x(), 50);
89 EXPECT_EQ(inserted->get_y(), 50);
90}
91
93{
94 QuadTree tree(0, 100, 0, 100, 4);
95
96 Point * result1 = tree.insert(Point(-10, 50));
97 Point * result2 = tree.insert(Point(50, 150));
98 Point * result3 = tree.insert(Point(150, 50));
99 Point * result4 = tree.insert(Point(50, -10));
100
101 EXPECT_EQ(result1, nullptr);
102 EXPECT_EQ(result2, nullptr);
103 EXPECT_EQ(result3, nullptr);
104 EXPECT_EQ(result4, nullptr);
105}
106
108{
109 QuadTree tree(0, 100, 0, 100, 4);
110
111 tree.insert(Point(25, 25));
112 tree.insert(Point(75, 75));
113
114 EXPECT_TRUE(tree.contains(Point(25, 25)));
115 EXPECT_TRUE(tree.contains(Point(75, 75)));
116 EXPECT_TRUE(tree.contains(Point(50, 50))); // In bounds but not inserted
117 EXPECT_FALSE(tree.contains(Point(-10, 50))); // Out of bounds
118 EXPECT_FALSE(tree.contains(Point(150, 50))); // Out of bounds
119}
120
122{
123 QuadTree tree(0, 100, 0, 100, 4);
124
125 tree.insert(Point(30, 40));
126 tree.insert(Point(70, 60));
127
128 Point * found1 = tree.search(Point(30, 40));
129 Point * found2 = tree.search(Point(70, 60));
130
131 ASSERT_NE(found1, nullptr);
132 ASSERT_NE(found2, nullptr);
133 EXPECT_EQ(found1->get_x(), 30);
134 EXPECT_EQ(found1->get_y(), 40);
135 EXPECT_EQ(found2->get_x(), 70);
136 EXPECT_EQ(found2->get_y(), 60);
137}
138
140{
141 QuadTree tree(0, 100, 0, 100, 4);
142
143 tree.insert(Point(30, 40));
144
145 Point * found = tree.search(Point(50, 50));
146
147 EXPECT_EQ(found, nullptr);
148}
149
151{
152 QuadTree tree(0, 100, 0, 100, 4);
153
154 tree.insert(Point(25, 25));
155
156 QuadNode * node = tree.search_container_node(Point(25, 25));
157
158 ASSERT_NE(node, nullptr);
159 EXPECT_TRUE(node->is_leaf());
160 EXPECT_NE(node->search_point(Point(25, 25)), nullptr);
161}
162
164{
165 QuadTree tree(0, 100, 0, 100, 4);
166
167 tree.insert(Point(50, 50));
168 EXPECT_NE(tree.search(Point(50, 50)), nullptr);
169
170 tree.remove(Point(50, 50));
171 EXPECT_EQ(tree.search(Point(50, 50)), nullptr);
172}
173
175{
176 QuadTree tree(0, 100, 0, 100, 4);
177
178 tree.insert(Point(50, 50));
179
180 // Should not crash or cause errors
181 tree.remove(Point(30, 30));
182
183 EXPECT_NE(tree.search(Point(50, 50)), nullptr);
184}
185
187{
188 QuadTree tree(0, 100, 0, 100, 1);
189 tree.insert(Point(10, 10));
190 tree.insert(Point(90, 90));
191
192 EXPECT_NO_THROW(tree.remove(Point(-1, 50)));
193 EXPECT_NO_THROW(tree.remove(Point(50, 100)));
194 EXPECT_NE(tree.search(Point(10, 10)), nullptr);
195 EXPECT_NE(tree.search(Point(90, 90)), nullptr);
196}
197
199{
200 QuadTree tree(0, 100, 0, 100, 4);
201
202 tree.insert(Point(25, 25));
203 tree.insert(Point(75, 75));
204 tree.insert(Point(50, 50));
205
206 tree.empty();
207
208 EXPECT_EQ(tree.search(Point(25, 25)), nullptr);
209 EXPECT_EQ(tree.search(Point(75, 75)), nullptr);
210 EXPECT_EQ(tree.search(Point(50, 50)), nullptr);
211}
212
214{
215 // Test 1: clear on newly constructed tree (no-op)
216 QuadTree tree(0, 100, 0, 100, 4);
217 tree.clear();
218 EXPECT_EQ(tree.search(Point(50, 50)), nullptr);
219
220 // Test 2: re-insertion after clear
221 tree.insert(Point(25, 25));
222 tree.clear();
223 EXPECT_EQ(tree.search(Point(25, 25)), nullptr);
224
225 tree.insert(Point(25, 25));
226 EXPECT_NE(tree.search(Point(25, 25)), nullptr);
227}
228
230{
231 QuadTree tree(0, 100, 0, 100, 4);
232 tree.insert(Point(25, 25));
233 tree.insert(Point(75, 75));
234
235 tree.clear();
236
237 EXPECT_EQ(tree.search(Point(25, 25)), nullptr);
238 EXPECT_EQ(tree.search(Point(75, 75)), nullptr);
239}
240
241// ============================================================================
242// Subdivision and Merging Tests
243// ============================================================================
244
246{
247 QuadTree tree(0, 100, 0, 100, 2); // Max 2 points per node
248
249 tree.insert(Point(25, 25));
250 tree.insert(Point(30, 30));
251
252 // Root should still be a leaf
253 EXPECT_TRUE(tree.get_root()->is_leaf());
254
255 // Third point should trigger split
256 tree.insert(Point(35, 35));
257
258 // Root should now be internal (Gray)
259 EXPECT_FALSE(tree.get_root()->is_leaf());
260 EXPECT_EQ(COLOR(tree.get_root()), QuadNode::Color::Gray);
261}
262
264{
265 QuadTree tree(0, 100, 0, 100, 2);
266
267 // Insert many points in one quadrant to force deep splits
268 for (int i = 1; i <= 10; ++i)
269 {
270 tree.insert(Point(10 + i, 10 + i));
271 }
272
273 // Verify root is internal
274 EXPECT_FALSE(tree.get_root()->is_leaf());
275
276 // Verify tree has multiple levels
277 QuadNode * nw = NW_CHILD(tree.get_root());
278 ASSERT_NE(nw, nullptr);
279
280 // At least one child should be further subdivided
281 bool has_deep_child = false;
282 if (not nw->is_leaf() || (NE_CHILD(tree.get_root()) != nullptr and not NE_CHILD(tree.get_root())->is_leaf()))
283 has_deep_child = true;
284
286}
287
289{
290 QuadTree tree(0, 100, 0, 100, 1);
291
292 // Insert one point in each quadrant
293 tree.insert(Point(25, 25)); // SW
294 tree.insert(Point(75, 25)); // SE
295 tree.insert(Point(25, 75)); // NW
296 tree.insert(Point(75, 75)); // NE
297
298 QuadNode * root = tree.get_root();
299 EXPECT_FALSE(root->is_leaf());
300
301 // All four children should exist and be leaves
302 ASSERT_NE(NW_CHILD(root), nullptr);
303 ASSERT_NE(NE_CHILD(root), nullptr);
304 ASSERT_NE(SW_CHILD(root), nullptr);
305 ASSERT_NE(SE_CHILD(root), nullptr);
306
311}
312
314{
315 QuadTree tree(0, 100, 0, 100, 2);
316
317 // Insert 3 points in DIFFERENT quadrants to trigger split
318 // Points must be in different quadrants to avoid nested splits
319 tree.insert(Point(25, 25)); // SW quadrant
320 tree.insert(Point(75, 25)); // SE quadrant
321 tree.insert(Point(25, 75)); // NW quadrant
322
323 EXPECT_FALSE(tree.get_root()->is_leaf());
324
325 // Remove one point to go below threshold
326 tree.remove(Point(25, 75));
327
328 // Root should merge back to leaf (only 2 points left, threshold is 2)
329 EXPECT_TRUE(tree.get_root()->is_leaf());
330}
331
333{
334 QuadTree tree(0, 100, 0, 100, 2);
335
336 // Insert many points
337 std::vector<Point> points = {
338 Point(10, 10), Point(15, 15), Point(20, 20),
339 Point(80, 80), Point(85, 85), Point(90, 90)
340 };
341
342 for (const auto & p : points)
343 tree.insert(p);
344
345 // Tree should be subdivided
346 EXPECT_FALSE(tree.get_root()->is_leaf());
347
348 // Remove points one by one
349 for (const auto & p : points)
350 {
351 tree.remove(p);
352 }
353
354 // After all removals, root should be a leaf again
355 EXPECT_TRUE(tree.get_root()->is_leaf());
356 EXPECT_EQ(COLOR(tree.get_root()), QuadNode::Color::White);
357}
358
360{
361 QuadTree tree(0, 1024, 0, 1024, 2);
362 const Point p1(1, 1);
363 const Point p2(2, 2);
364 const Point p3(3, 3);
365 const Point far(900, 900);
366
367 tree.insert(p1);
368 tree.insert(p2);
369 tree.insert(p3);
370 ASSERT_FALSE(tree.get_root()->is_leaf());
371
372 tree.remove(p3);
373 ASSERT_TRUE(tree.get_root()->is_leaf());
374
375 tree.insert(far);
376 ASSERT_FALSE(tree.get_root()->is_leaf());
378
379 EXPECT_TRUE(tree.get_root()->is_leaf());
380 EXPECT_NE(tree.search(p1), nullptr);
381 EXPECT_NE(tree.search(p2), nullptr);
382}
383
384// ============================================================================
385// Copy Constructor and Assignment Tests
386// ============================================================================
387
389{
390 QuadTree tree1(0, 100, 0, 100, 3);
391
392 tree1.insert(Point(25, 25));
393 tree1.insert(Point(75, 75));
394 tree1.insert(Point(50, 50));
395
397
398 // Verify all points are in the copy
399 EXPECT_NE(tree2.search(Point(25, 25)), nullptr);
400 EXPECT_NE(tree2.search(Point(75, 75)), nullptr);
401 EXPECT_NE(tree2.search(Point(50, 50)), nullptr);
402
403 // Verify they are independent
404 tree1.insert(Point(10, 10));
405 EXPECT_EQ(tree2.search(Point(10, 10)), nullptr);
406}
407
409{
410 QuadTree tree1(0, 100, 0, 100, 3);
411 tree1.insert(Point(25, 25));
412 tree1.insert(Point(75, 75));
413
414 QuadTree tree2(0, 200, 0, 200, 5);
415 tree2.insert(Point(150, 150));
416
417 tree2 = tree1;
418
419 // tree2 should now have tree1's data
420 EXPECT_NE(tree2.search(Point(25, 25)), nullptr);
421 EXPECT_NE(tree2.search(Point(75, 75)), nullptr);
422 EXPECT_EQ(tree2.search(Point(150, 150)), nullptr);
423
424 // Configuration should also be copied
425 EXPECT_EQ(tree2.get_max_num_points_per_node(), 3);
426}
427
429{
430 QuadTree tree(0, 100, 0, 100, 3);
431 tree.insert(Point(50, 50));
432
433 tree = tree;
434
435 // Should still work
436 EXPECT_NE(tree.search(Point(50, 50)), nullptr);
437}
438
439// ============================================================================
440// Stress Tests
441// ============================================================================
442
444{
445 QuadTree tree(0, 1000, 0, 1000, 4);
446
447 std::mt19937 gen(12345);
448 std::uniform_real_distribution<> dis(0, 1000);
449
450 const size_t num_points = 10000;
451 std::vector<Point> points;
452
453 for (size_t i = 0; i < num_points; ++i)
454 {
455 Point p(dis(gen), dis(gen));
456 points.push_back(p);
457 Point * inserted = tree.insert(p);
458 ASSERT_NE(inserted, nullptr);
459 }
460
461 // Verify all points can be found
462 for (const auto & p : points)
463 {
464 EXPECT_NE(tree.search(p), nullptr);
465 }
466}
467
469{
470 QuadTree tree(0, 100, 0, 100, 4);
471
472 std::mt19937 gen(54321);
473 std::uniform_real_distribution<> dis(0, 100);
474
475 const size_t cycles = 100;
476 const size_t points_per_cycle = 50;
477
478 for (size_t cycle = 0; cycle < cycles; ++cycle)
479 {
480 std::vector<Point> points;
481
482 // Insert points
483 for (size_t i = 0; i < points_per_cycle; ++i)
484 {
485 Point p(dis(gen), dis(gen));
486 points.push_back(p);
487 tree.insert(p);
488 }
489
490 // Remove half of them
491 for (size_t i = 0; i < points_per_cycle / 2; ++i)
492 {
493 tree.remove(points[i]);
494 }
495 }
496
497 // Tree should still be functional
498 Point * test = tree.insert(Point(50, 50));
499 EXPECT_NE(test, nullptr);
500}
501
503{
504 QuadTree tree(0, 100, 0, 100, 2);
505
506 // Insert many points in a small region
507 for (int x = 40; x <= 60; ++x)
508 {
509 for (int y = 40; y <= 60; ++y)
510 {
511 tree.insert(Point(x, y));
512 }
513 }
514
515 // Verify all can be found
516 for (int x = 40; x <= 60; ++x)
517 {
518 for (int y = 40; y <= 60; ++y)
519 {
520 EXPECT_NE(tree.search(Point(x, y)), nullptr);
521 }
522 }
523}
524
525// ============================================================================
526// Edge Cases
527// ============================================================================
528
530{
531 QuadTree tree(0, 100, 0, 100, 4);
532
533 // Test exact boundary points
534 Point * p1 = tree.insert(Point(0, 0));
535 Point * p2 = tree.insert(Point(0, 100)); // Upper bound, should fail
536 Point * p3 = tree.insert(Point(100, 0)); // Upper bound, should fail
537 Point * p4 = tree.insert(Point(100, 100)); // Upper bounds, should fail
538
539 EXPECT_NE(p1, nullptr);
540 EXPECT_EQ(p2, nullptr); // Upper bounds are exclusive
541 EXPECT_EQ(p3, nullptr);
542 EXPECT_EQ(p4, nullptr);
543}
544
546{
547 QuadTree tree(0, 100, 0, 100, 1);
548
549 // Insert point exactly at midpoint
550 tree.insert(Point(50, 50));
551
552 // Insert more to trigger split
553 tree.insert(Point(25, 25));
554
555 // Midpoint should be in one of the quadrants
556 EXPECT_NE(tree.search(Point(50, 50)), nullptr);
557}
558
560{
561 QuadTree tree(0, 100, 0, 100, 1);
562
563 tree.insert(Point(25, 25));
564 tree.insert(Point(30, 30));
565
566 // Should trigger immediate split
567 EXPECT_FALSE(tree.get_root()->is_leaf());
568}
569
571{
572 QuadTree tree(0, 100, 0, 100, 1);
573 const Point duplicate(25, 25);
574
575 for (size_t i = 0; i < 100; ++i)
576 ASSERT_NE(tree.insert(duplicate), nullptr);
577
578 EXPECT_TRUE(tree.get_root()->is_leaf());
579 EXPECT_EQ(tree.get_root()->get_num_points(), 100u);
580
581 for (size_t i = 0; i < 100; ++i)
582 tree.remove(duplicate);
583
584 EXPECT_EQ(tree.search(duplicate), nullptr);
585 EXPECT_EQ(COLOR(tree.get_root()), QuadNode::Color::White);
586}
587
589{
590 QuadTree tree(0, 1, 0, 1, 2);
591
592 tree.insert(Point(0.1, 0.1));
593 tree.insert(Point(0.9, 0.9));
594
595 EXPECT_NE(tree.search(Point(0.1, 0.1)), nullptr);
596 EXPECT_NE(tree.search(Point(0.9, 0.9)), nullptr);
597}
598
600{
601 QuadTree tree(-1e9, 1e9, -1e9, 1e9, 4);
602
603 tree.insert(Point(0, 0));
604 tree.insert(Point(1e8, 1e8));
605 tree.insert(Point(-5e8, -5e8));
606
607 EXPECT_NE(tree.search(Point(0, 0)), nullptr);
608 EXPECT_NE(tree.search(Point(1e8, 1e8)), nullptr);
609 EXPECT_NE(tree.search(Point(-5e8, -5e8)), nullptr);
610}
611
612// ============================================================================
613// Traversal Tests
614// ============================================================================
615
617{
618 QuadTree tree(0, 100, 0, 100, 2);
619
620 for (int i = 0; i < 10; ++i)
621 {
622 tree.insert(Point(10 * i, 10 * i));
623 }
624
625 size_t node_count = 0;
626 tree.for_each([&node_count](QuadNode * node) {
627 ++node_count;
628 EXPECT_NE(node, nullptr);
629 });
630
631 EXPECT_GT(node_count, 0);
632}
633
635{
636 QuadTree tree(0, 100, 0, 100, 2);
637
638 tree.insert(Point(10, 10));
639 tree.insert(Point(20, 20));
640 tree.insert(Point(80, 80));
641 tree.insert(Point(90, 90));
642
643 size_t leaf_count = 0;
644 tree.for_each([&leaf_count](QuadNode * node) {
645 if (node->is_leaf())
646 ++leaf_count;
647 });
648
650}
651
652// ============================================================================
653// Fuzz Tests
654// ============================================================================
655
657{
658 QuadTree tree(0, 1000, 0, 1000, 4);
659
660 std::mt19937 gen(99999);
661 // Use integer coordinates to avoid mpq_class precision issues with double conversion
662 std::uniform_int_distribution<int> coord_dis(0, 999);
663 std::uniform_int_distribution<> op_dis(0, 2);
664
665 // Store points directly to avoid string conversion precision issues
666 std::vector<Point> inserted_points;
667
668 for (int i = 0; i < 1000; ++i)
669 {
670 int op = op_dis(gen);
671
672 if (op == 0 || op == 1) // Insert
673 {
675 Point * result = tree.insert(p);
676 if (result != nullptr)
677 inserted_points.push_back(p);
678 }
679 else if (op == 2 && not inserted_points.empty()) // Remove
680 {
681 // Pick a random inserted point
682 size_t idx = gen() % inserted_points.size();
684
685 tree.remove(to_remove);
686 inserted_points.erase(inserted_points.begin() + idx);
687 }
688 }
689
690 // Verify consistency
691 for (const auto & p : inserted_points)
692 EXPECT_NE(tree.search(p), nullptr)
693 << "Point (" << p.get_x() << ", " << p.get_y() << ") should be in tree";
694}
695
696// ============================================================================
697// Main
698// ============================================================================
699
700int main(int argc, char **argv)
701{
702 ::testing::InitGoogleTest(&argc, argv);
703 return RUN_ALL_TESTS();
704}
int main()
Represents a point with rectangular coordinates in a 2D plane.
Definition point.H:221
const Geom_Number & get_x() const noexcept
Gets the x-coordinate value.
Definition point.H:448
const Geom_Number & get_y() const noexcept
Gets the y-coordinate value.
Definition point.H:457
Node for QuadTree spatial data structure.
Definition quadnode.H:94
const Geom_Number & get_min_y() const noexcept
Get minimum Y coordinate of this region.
Definition quadnode.H:490
const Geom_Number & get_max_y() const noexcept
Get maximum Y coordinate of this region.
Definition quadnode.H:493
const Geom_Number & get_min_x() const noexcept
Get minimum X coordinate of this region.
Definition quadnode.H:484
void set_region(const Geom_Number &_min_x, const Geom_Number &_max_x, const Geom_Number &_min_y, const Geom_Number &_max_y)
Set the region boundaries for this node.
Definition quadnode.H:345
Point * search_point(const Point &p) noexcept
Search for a point in this node.
Definition quadnode.H:514
bool is_leaf() const noexcept
Check if this node is a leaf (has no children).
Definition quadnode.H:381
size_t get_num_points() noexcept
Get total number of points in this subtree.
Definition quadnode.H:478
const Geom_Number & get_max_x() const noexcept
Get maximum X coordinate of this region.
Definition quadnode.H:487
QuadTree - Hierarchical spatial index for 2D points.
Definition quadtree.H:126
void empty(Node *&r) noexcept
Recursively delete all nodes.
Definition quadtree.H:300
void clear()
Alias for empty().
Definition quadtree.H:602
void for_each(Op &op)
Apply an operation to each node in the tree.
Definition quadtree.H:612
void remove(const Point &p)
Remove a point from the tree.
Definition quadtree.H:565
Point * search(const Point &p) noexcept
Search for a point in the tree.
Definition quadtree.H:524
Node * search_container_node(const Point &p) noexcept
Find the leaf node containing a point.
Definition quadtree.H:542
void set_max_num_points_per_node(const size_t &_max_num_points_per_node)
Set the maximum points per leaf node.
Definition quadtree.H:469
bool contains(const Point &p) const noexcept
Check if a point is within the tree's region.
Definition quadtree.H:487
Point * insert(Node *&r, const Point &p)
Recursive insert helper.
Definition quadtree.H:281
size_t get_max_num_points_per_node() const noexcept
Get the maximum points per leaf node.
Definition quadtree.H:477
Node * get_root() noexcept
Get the root node.
Definition quadtree.H:451
#define TEST(name)
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
Definition gmpfrxx.h:4071
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
static mpfr_t y
Definition mpfr_mul_d.c:3
and
Check uniqueness with explicit hash + equality functors.
static bool is_leaf(BinNode< std::string > *p) noexcept
Definition Huffman.H:104
#define COLOR(p)
Definition quadnode.H:58
#define SE_CHILD(p)
Definition quadnode.H:57
#define NE_CHILD(p)
Definition quadnode.H:55
#define NW_CHILD(p)
Definition quadnode.H:54
#define SW_CHILD(p)
Definition quadnode.H:56
QuadTree spatial data structure for efficient 2D point indexing.
void test()
Definition test-comb.C:40