-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathlist_pool.h
More file actions
158 lines (121 loc) · 3.26 KB
/
list_pool.h
File metadata and controls
158 lines (121 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#ifndef LIST_POOL_H
#define LIST_POOL_H
#include <vector>
#include <cstddef>
// Requirements on T: semiregular.
// Requirements on N: integral
template <typename T, typename N = std::size_t>
class list_pool {
public:
typedef T value_type;
typedef N list_type;
private:
struct node_t {
value_type value;
list_type next;
};
std::vector<node_t> pool;
node_t& node(list_type x) {
return pool[x - 1];
}
const node_t& node(list_type x) const {
return pool[x - 1];
}
list_type new_list() {
pool.push_back(node_t());
return list_type(pool.size());
}
list_type free_list;
public:
typedef typename std::vector<node_t>::size_type size_type;
list_type end() const {
return list_type(0);
}
bool is_end(list_type x) const {
return x == end();
}
bool empty() const {
return pool.empty();
}
size_type size() const {
return pool.size();
}
size_type capacity() const {
return pool.capacity();
}
void reserve(size_type n) {
pool.reserve(n);
}
list_pool() {
free_list = end();
}
list_pool(size_type n) {
free_list = end();
reserve(n);
}
T& value(list_type x) {
return node(x).value;
}
const T& value(list_type x) const {
return node(x).value;
}
list_type& next(list_type x) {
return node(x).next;
}
const list_type& next(list_type x) const {
return node(x).next;
}
list_type free(list_type x) {
list_type cdr = next(x);
next(x) = free_list;
free_list = x;
return cdr;
}
list_type free(list_type front, list_type back) {
if (is_end(front)) return end();
list_type tail = next(back);
next(back) = free_list;
free_list = front;
return tail;
}
list_type allocate(const T& val, list_type tail) {
list_type list = free_list;
if (is_end(free_list)) {
list = new_list();
} else {
free_list = next(free_list);
}
value(list) = val;
next(list) = tail;
return list;
}
// operations on queues:
// pop_front, push_front, push_back and free, etc
typedef std::pair<list_type, list_type> pair_type;
bool empty(const pair_type& p) { return is_end(p.first); }
pair_type empty_queue() { return pair_type(end(), end()); }
pair_type pop_front(const pair_type& p) {
if (empty(p)) return p;
return pair_type(next(p.first), p.second);
}
pair_type push_front(const pair_type& p, const T& value) {
list_type new_node = allocate(value, p.first);
if (empty(p)) return pair_type(new_node, new_node);
return pair_type(new_node, p.second);
}
pair_type push_back(const pair_type& p, const T& value) {
list_type new_node = allocate(value, end());
if (empty(p)) return pair_type(new_node, new_node);
next(p.second) = new_node;
return pair_type(p.first, new_node);
}
void free(const pair_type& p) { free(p.first, p.second); }
#include "list_pool_iterator.h"
};
template <typename T, typename N>
void free_list(list_pool<T, N>& pool,
typename list_pool<T, N>::list_type x)
{
while (!pool.is_end(x)) x = pool.free(x);
}
#endif