Skip to content

Commit 9da0d66

Browse files
committed
Make (multi)map/set works with any ballanced tree implementation
1 parent 29d41e4 commit 9da0d66

5 files changed

Lines changed: 209 additions & 28 deletions

File tree

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,16 @@ mystd is a stl-like library.
3434
- [ ] hash table on open addressing
3535
- [ ] trees
3636
- [x] binary trees
37-
- [ ] bst + templated various balancing algorithms
3837
- [x] binary search tree (BST)
39-
- [x] add iterator
4038
- [x] ballanced tree (std::map)
4139
- [x] AVL
4240
- [x] red black
4341
- [x] treap
44-
- [x] std::map -> my::map
45-
- [x] std::set -> my::set
46-
- [x] std::multimap -> my::multimap
47-
- [x] std::multiset -> my::multiset
42+
- [x] map/set base on abstract tree (see `test_map_for_many_trees.cpp`)
43+
- [x] std::map -> my::map
44+
- [x] std::set -> my::set
45+
- [x] std::multimap -> my::multimap
46+
- [x] std::multiset -> my::multiset
4847
- [ ] trie
4948
- [ ] segment tree
5049
- [ ] heaps
@@ -56,3 +55,4 @@ mystd is a stl-like library.
5655
- [ ] DFS, BFS
5756
- [ ] DSU
5857
- [ ] Skip List
58+
- [x] external `iterator.hpp`

include/mystd/iterator/iterator.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55

66
namespace my {
77

8+
template <class Key, class Value>
9+
struct KeyOfPair {
10+
using ValueType = std::pair<Key, Value>;
11+
const Key& operator()(const ValueType& v) const noexcept { return v.first; }
12+
};
13+
14+
template <class Value>
15+
struct KeyOfIdentity {
16+
const Value& operator()(const Value& v) const noexcept { return v; }
17+
};
18+
819
// traversal policies
920

1021
template <typename NodePtr>
@@ -83,6 +94,13 @@ class iterator {
8394
template <bool OtherConst = IsConst, typename = std::enable_if_t<!OtherConst && IsConst>>
8495
iterator(const iterator<ValueType, NodePtr, false, Category, TraversalPolicy, ValueExtractor>& other)
8596
: node_(other.base()) {}
97+
iterator operator=(const iterator<ValueType, NodePtr, false, Category, TraversalPolicy, ValueExtractor>& other) {
98+
if (this != &other) {
99+
iterator tmp(other);
100+
swap(tmp);
101+
}
102+
return *this;
103+
}
86104

87105
NodePtr base() const { return node_; }
88106

@@ -103,6 +121,8 @@ class iterator {
103121
bool operator==(const iterator& other) const { return node_ == other.node_; }
104122
bool operator!=(const iterator& other) const { return node_ != other.node_; }
105123

124+
void swap(iterator& other) { std::swap(node_, other.node_); }
125+
106126
protected:
107127
NodePtr node_;
108128
};

include/mystd/some_trees/rb_tree.hpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,6 @@ namespace my {
1515

1616
enum class NodeColors { RED, BLACK };
1717

18-
template <class Key, class Value>
19-
struct KeyOfPair {
20-
using ValueType = std::pair<Key, Value>;
21-
const Key& operator()(const ValueType& v) const noexcept { return v.first; }
22-
};
23-
24-
template <class Value>
25-
struct KeyOfIdentity {
26-
const Value& operator()(const Value& v) const noexcept { return v; }
27-
};
28-
2918
/// @brief Red black tree has invariants:
3019
/// 1. node -- red || black
3120
/// 2. root -- black

include/mystd/some_trees/treap.hpp

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,6 @@
1111

1212
namespace my {
1313

14-
template <class Key, class Value>
15-
struct KeyOfPair {
16-
using ValueType = std::pair<Key, Value>;
17-
const Key& operator()(const ValueType& v) const noexcept { return v.first; }
18-
};
19-
20-
template <class Value>
21-
struct KeyOfIdentity {
22-
const Value& operator()(const Value& v) const noexcept { return v; }
23-
};
24-
2514
/// @brief Tree + heap
2615
/// ref: https://neerc.ifmo.ru/wiki/index.php?title=Декартово_дерево
2716
template <typename ValueType, typename KeyOfValue,
@@ -266,6 +255,8 @@ class treap {
266255

267256
void erase(const key_type& key) { root_ = erase_node(root_, key); }
268257

258+
bool contains(const key_type& key) const { return find_node(root_, key) != nullptr; }
259+
269260
iterator find(const key_type& key) {
270261
Node* found = find_node(root_, key);
271262
return iterator(found);
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <algorithm>
4+
#include <exception>
5+
#include <string>
6+
#include <utility>
7+
8+
#include "mystd/map_base.hpp"
9+
#include "mystd/some_trees/rb_tree.hpp"
10+
#include "mystd/some_trees/treap.hpp"
11+
12+
namespace my {
13+
14+
template <typename Key, typename T, typename Tree = my::rb_tree<std::pair<Key, T>, KeyOfPair<Key, T>>>
15+
using map_rbtree = map_base<Key, T, true, Tree>;
16+
17+
template <typename Key, typename T, typename Tree = my::treap<std::pair<Key, T>, KeyOfPair<Key, T>>>
18+
using map_treap = map_base<Key, T, true, Tree>;
19+
20+
} // namespace my
21+
22+
namespace my::testing {
23+
24+
TEST(MapForManyTreesTest, InsertAndSize) {
25+
// map rb tree based
26+
my::map_rbtree<int, std::string> m_rb;
27+
EXPECT_TRUE(m_rb.empty());
28+
EXPECT_EQ(m_rb.size(), 0);
29+
30+
m_rb.insert({1, "one"});
31+
m_rb.insert({2, "two"});
32+
m_rb.insert({3, "three"});
33+
EXPECT_FALSE(m_rb.empty());
34+
EXPECT_EQ(m_rb.size(), 3);
35+
36+
m_rb.insert({1, "one"});
37+
EXPECT_EQ(m_rb.size(), 3);
38+
EXPECT_EQ(m_rb[1], "one");
39+
40+
// map treap based
41+
my::map_treap<int, std::string> m_treap;
42+
EXPECT_TRUE(m_treap.empty());
43+
EXPECT_EQ(m_treap.size(), 0);
44+
45+
m_treap.insert({1, "one"});
46+
m_treap.insert({2, "two"});
47+
m_treap.insert({3, "three"});
48+
EXPECT_FALSE(m_treap.empty());
49+
EXPECT_EQ(m_treap.size(), 3);
50+
51+
m_treap.insert({1, "one"});
52+
EXPECT_EQ(m_treap.size(), 3);
53+
EXPECT_EQ(m_treap[1], "one");
54+
}
55+
56+
TEST(MapForManyTreesTest, FindAndAccess) {
57+
my::map_rbtree<int, std::string> m_rb;
58+
m_rb.insert({1, "one"});
59+
m_rb.insert({2, "two"});
60+
61+
auto itrb = m_rb.find(1);
62+
ASSERT_NE(itrb, m_rb.end());
63+
EXPECT_EQ(itrb->second, "one");
64+
65+
itrb = m_rb.find(3);
66+
EXPECT_EQ(itrb, m_rb.end());
67+
68+
my::map_treap<int, std::string> m_treap;
69+
m_treap.insert({1, "one"});
70+
m_treap.insert({2, "two"});
71+
72+
auto ittreap = m_treap.find(1);
73+
ASSERT_NE(ittreap, m_treap.end());
74+
EXPECT_EQ(ittreap->second, "one");
75+
76+
ittreap = m_treap.find(3);
77+
EXPECT_EQ(ittreap, m_treap.end());
78+
}
79+
80+
TEST(MapForManyTreesTest, Erase) {
81+
my::map_rbtree<int, std::string> m_rb;
82+
m_rb.insert({1, "one"});
83+
m_rb.insert({2, "two"});
84+
m_rb.insert({3, "three"});
85+
86+
m_rb.erase(2);
87+
EXPECT_EQ(m_rb.size(), 2);
88+
EXPECT_EQ(m_rb.find(2), m_rb.end());
89+
90+
m_rb.erase(4);
91+
EXPECT_EQ(m_rb.size(), 2);
92+
93+
my::map_treap<int, std::string> m_treap;
94+
m_treap.insert({1, "one"});
95+
m_treap.insert({2, "two"});
96+
m_treap.insert({3, "three"});
97+
98+
m_treap.erase(2);
99+
EXPECT_EQ(m_treap.size(), 2);
100+
EXPECT_EQ(m_treap.find(2), m_treap.end());
101+
102+
m_treap.erase(4);
103+
EXPECT_EQ(m_treap.size(), 2);
104+
}
105+
106+
TEST(MapForManyTreesTest, Iterator) {
107+
my::map_rbtree<int, std::string> m_rb;
108+
m_rb.insert({1, "one"});
109+
m_rb.insert({2, "two"});
110+
m_rb.insert({3, "three"});
111+
112+
std::vector<std::pair<int, std::string>> result;
113+
for (const auto& pair : m_rb) {
114+
result.push_back(pair);
115+
}
116+
std::vector<std::pair<int, std::string>> expected = {{1, "one"}, {2, "two"}, {3, "three"}};
117+
EXPECT_EQ(result, expected);
118+
119+
my::map_treap<int, std::string> m_treap;
120+
m_treap.insert({1, "one"});
121+
m_treap.insert({2, "two"});
122+
m_treap.insert({3, "three"});
123+
124+
result.clear();
125+
for (const auto& pair : m_treap) {
126+
result.push_back(pair);
127+
}
128+
EXPECT_EQ(result, expected);
129+
}
130+
131+
TEST(MapForManyTreesTest, Clear) {
132+
my::map_rbtree<int, std::string> m_rb;
133+
m_rb.insert({1, "one"});
134+
m_rb.insert({2, "two"});
135+
m_rb.clear();
136+
EXPECT_TRUE(m_rb.empty());
137+
EXPECT_EQ(m_rb.size(), 0);
138+
EXPECT_EQ(m_rb.find(1), m_rb.end());
139+
140+
my::map_treap<int, std::string> m_treap;
141+
m_treap.insert({1, "one"});
142+
m_treap.insert({2, "two"});
143+
m_treap.clear();
144+
EXPECT_TRUE(m_rb.empty());
145+
EXPECT_EQ(m_treap.size(), 0);
146+
EXPECT_EQ(m_treap.find(1), m_treap.end());
147+
}
148+
149+
TEST(MapForManyTreesTest, CopyAndAssignment) {
150+
my::map_rbtree<int, std::string> m_rb;
151+
m_rb.insert({1, "one"});
152+
m_rb.insert({2, "two"});
153+
154+
my::map_rbtree<int, std::string> m_rb_copy(m_rb);
155+
EXPECT_EQ(m_rb_copy.size(), 2);
156+
EXPECT_EQ(m_rb_copy[1], "one");
157+
EXPECT_EQ(m_rb_copy[2], "two");
158+
159+
my::map_rbtree<int, std::string> m_rb_assign;
160+
m_rb_assign = m_rb;
161+
EXPECT_EQ(m_rb_assign.size(), 2);
162+
EXPECT_EQ(m_rb_assign[1], "one");
163+
EXPECT_EQ(m_rb_assign[2], "two");
164+
165+
my::map_treap<int, std::string> m_treap;
166+
m_treap.insert({1, "one"});
167+
m_treap.insert({2, "two"});
168+
169+
my::map_treap<int, std::string> m_treap_copy(m_treap);
170+
EXPECT_EQ(m_treap_copy.size(), 2);
171+
EXPECT_EQ(m_treap_copy[1], "one");
172+
EXPECT_EQ(m_treap_copy[2], "two");
173+
174+
my::map_treap<int, std::string> m_treap_assign;
175+
m_treap_assign = m_treap;
176+
EXPECT_EQ(m_treap_assign.size(), 2);
177+
EXPECT_EQ(m_treap_assign[1], "one");
178+
EXPECT_EQ(m_treap_assign[2], "two");
179+
}
180+
181+
} // namespace my::testing

0 commit comments

Comments
 (0)