]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/ext/pb_ds/example/tree_intervals.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / ext / pb_ds / example / tree_intervals.cc
CommitLineData
4569a895
AT
1// -*- C++ -*-
2
8d9254fc 3// Copyright (C) 2005-2020 Free Software Foundation, Inc.
4569a895
AT
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the terms
7// of the GNU General Public License as published by the Free Software
748086b7 8// Foundation; either version 3, or (at your option) any later
4569a895
AT
9// version.
10
11// This library is distributed in the hope that it will be useful, but
12// WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
748086b7
JJ
17// along with this library; see the file COPYING3. If not see
18// <http://www.gnu.org/licenses/>.
4569a895 19
4569a895
AT
20
21// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
22
23// Permission to use, copy, modify, sell, and distribute this software
24// is hereby granted without fee, provided that the above copyright
25// notice appears in all copies, and that both that copyright notice
26// and this permission notice appear in supporting documentation. None
27// of the above authors, nor IBM Haifa Research Laboratories, make any
28// representation about the suitability of this software for any
29// purpose. It is provided "as is" without express or implied
30// warranty.
31
32/**
33 * @file tree_intervals_example.cpp
34 * An example showing how to augment a trees to support operations involving
35 * line intervals.
36 */
37
38/**
39 * In some cases tree structure can be used for various purposes other
40 * than storing entries by key order. This example shows how a
41 * tree-based container can be used for geometric-line intersection
42 * determination. That is, the key of the container is a pair of
43 * numbers representing a line interval. The container object can be
44 * used to query whether a line interval intersects any line interval
45 * it currently stores.
46 *
47 * This type of problem arises not only in geometric applications, but
48 * also sometimes in distributed filesystems. Assume that "leases" are
49 * taken for parts of files or LUNs. When a new lease is requested, it
50 * is necessary to check that it does not conflict with a lease
51 * already taken. In this case a file or LUN can be envisioned as a
52 * line segment; leases requested and granted for contiguous parts of
53 * the file or LUN can be represented as line intervals as well.
54 */
55
56#include <cassert>
57#include <cstdlib>
58#include <ext/pb_ds/assoc_container.hpp>
59
60using namespace std;
5e11f978 61using namespace __gnu_pbds;
4569a895
AT
62
63// Following are definitions of line intervals and functors operating
64// on them. As the purpose of this example is node invariants, and not
65// computational-geometry algorithms per-se, some simplifications are
66// made (e.g., intervals are defined by unsigned integers, and not by
67// a parameterized type, data members are public, etc.).
68
69// An interval of unsigned integers.
70typedef pair< unsigned int, unsigned int> interval;
71
72// Functor updating maximal endpoints of entries. Algorithm taken from
73// "Introduction to Algorithms" by Cormen, Leiserson, and Rivest.
a345e45d
BK
74template<class Node_CItr,
75 class Node_Itr,
4569a895 76 class Cmp_Fn,
a345e45d 77 typename _Alloc>
4569a895
AT
78struct intervals_node_update
79{
80public:
81 // The metadata that each node stores is the largest endpoint of an
82 // interval in its subtree. In this case, this is an unsigned int.
83 typedef unsigned int metadata_type;
84
85 // Checks whether a set of intervals contains at least one interval
86 // overlapping some interval. Algorithm taken from "Introduction to
87 // Algorithms" by Cormen, Leiserson, and Rivest.
88 bool
89 overlaps(const interval& r_interval)
90 {
a345e45d
BK
91 Node_CItr nd_it = node_begin();
92 Node_CItr end_it = node_end();
4569a895
AT
93
94 while (nd_it != end_it)
95 {
96 // Check whether r_interval overlaps the current interval.
97 if (r_interval.second >= (*nd_it)->first&&
98 r_interval.first <= (*nd_it)->second)
99 return true;
100
101 // Get the const node iterator of the node's left child.
a345e45d 102 Node_CItr l_nd_it = nd_it.get_l_child();
4569a895
AT
103
104 // Calculate the maximal endpoint of the left child. If the
105 // node has no left child, then this is the node's maximal
106 // endpoint.
107 const unsigned int l_max_endpoint =(l_nd_it == end_it)?
108 0 : l_nd_it.get_metadata();
109
110 // Now use the endpoint to determine which child to choose.
111 if (l_max_endpoint >= r_interval.first)
112 nd_it = l_nd_it;
113 else
114 nd_it = nd_it.get_r_child();
115 }
116
117 return false;
118 }
119
120protected:
121 // Update predicate: nd_it is a node iterator to the node currently
122 // updated; end_nd_it is a const node iterator to a just-after leaf
123 // node.
124 inline void
a345e45d 125 operator()(Node_Itr nd_it, Node_CItr end_nd_it)
4569a895
AT
126 {
127 // The left maximal endpoint is 0 if there is no left child.
128 const unsigned int l_max_endpoint =(nd_it.get_l_child() == end_nd_it)?
129 0 : nd_it.get_l_child().get_metadata();
130
131 // The right maximal endpoint is 0 if there is no right child.
132 const unsigned int r_max_endpoint =(nd_it.get_r_child() == end_nd_it)?
133 0 : nd_it.get_r_child().get_metadata();
134
135 // The maximal endpoint is the endpoint of the node's interval,
136 // and the maximal endpoints of its children.
137 const_cast<unsigned int&>(nd_it.get_metadata()) =
138 max((*nd_it)->second, max<unsigned int>(l_max_endpoint, r_max_endpoint));
139 }
140
a345e45d 141 virtual Node_CItr
4569a895
AT
142 node_begin() const = 0;
143
a345e45d 144 virtual Node_CItr
4569a895
AT
145 node_end() const = 0;
146
147 virtual
148 ~intervals_node_update()
149 { }
150};
151
152// The following function performs some operation sequence on a
153// generic associative container supporting order statistics. It
154// inserts some intervals, and checks for overlap.
155template<class Cntnr>
156void
157some_op_sequence(Cntnr r_c)
158{
159 // Insert some entries.
160 r_c.insert(make_pair(0, 100));
161 r_c.insert(make_pair(150, 160));
162 r_c.insert(make_pair(300, 1000));
163 r_c.insert(make_pair(10000, 100000));
164 r_c.insert(make_pair(200, 100200));
165
166 // Test overlaps.
167
168 // Overlaps 150 - 160
169 assert(r_c.overlaps(make_pair(145, 165)) == true);
170 // Overlaps 150 - 160
171 assert(r_c.overlaps(make_pair(145, 155)) == true);
172 assert(r_c.overlaps(make_pair(165, 175)) == false);
173 assert(r_c.overlaps(make_pair(100201, 100203)) == false);
174
175 // Erase an interval
176 r_c.erase(make_pair(150, 160));
177
178 // Test overlaps again.
179 assert(r_c.overlaps(make_pair(145, 165)) == false);
180 assert(r_c.overlaps(make_pair(165, 175)) == false);
181 assert(r_c.overlaps(make_pair(0, 300000)) == true);
182}
183
184int main()
185{
186 // Test a red-black tree.
187 some_op_sequence(tree<
188 interval,
a345e45d 189 null_type,
4569a895
AT
190 less<interval>,
191 rb_tree_tag,
192 intervals_node_update>());
193
194 // Test an ordered-vector tree.
195 some_op_sequence(tree<
196 interval,
a345e45d 197 null_type,
4569a895
AT
198 less<interval>,
199 ov_tree_tag,
200 intervals_node_update>());
201
202 // Test a splay tree.
203 some_op_sequence(tree<
204 interval,
a345e45d 205 null_type,
4569a895
AT
206 less<interval>,
207 splay_tree_tag,
208 intervals_node_update>());
209
210 return 0;
211}
212