-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathsingle_list.hpp
232 lines (204 loc) · 4.57 KB
/
single_list.hpp
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/***************************************************************************
* @file single_list.hpp
* @author Alan.W
* @date 30 May 2014
* @remark Chapter 10, Introduction to Algorithms
* @note code style : STL
***************************************************************************/
//!
//! ex10.2-1
//! Can you implement the dynamic-set operation INSERT on a singly linked list
//! in O(1) time? How about DELETE ?
//!
// As shown below, INSERT on a singly linked list in O(1) is able to
// implment, but DELETE in O(1) is not.The reason is that prev which is not provided
// needs O(n) time to find.
//!
//! ex10.2-5
//! Implement the dictionary operations INSERT, DELETE , and SEARCH using singly
//! linked, circular lists. What are the running times of your procedures?
//!
// As shown in code below.
//!
//! ex10.2-7
//! Give a theta (n)-time nonrecursive procedure that reverses a singly linked list of n
//! elements. The procedure should use no more than constant storage beyond that
//! needed for the list itself.
//!
/* reverse
* 1 def current = begin
* 2 nil-> next = nil
* 3 while(current != nil)
* 4 insert(current->key)
* 5 current = current ->next
*/
#ifndef SINGLE_LIST_H
#define SINGLE_LIST_H
#include <list.hpp>
namespace ch10 {
namespace list {
/**
* @brief singly linked circular list
*/
template<typename T>
class single_list_ring
{
public:
using ValueType = T;
using Node = node<ValueType>;
using sPointer = std::shared_ptr<Node>;
using SizeType = std::size_t;
/**
* @brief default ctor
*/
single_list_ring():
count(0), nil(std::make_shared<Node>(12345))
{
nil->next = nil;
}
/**
* @brief search
*
* @complexity O(n)
*/
sPointer search(const ValueType& val) const
{
sPointer ptr = nil->next;
while(ptr != nil && ptr->key != val)
ptr = ptr->next;
return ptr;
}
/**
* @brief insert
*
* @complexity O(1)
*
*
* example: insert(3)
* before inserting: [nil][7][8][9]
* ^
* begin
* after inserting: [nil][3][7][8][9]
* ^
* begin
*
*
* as ex10.2-1 required.
*/
void insert(const ValueType& val)
{
sPointer inserted = std::make_shared<Node>(val);
inserted->next = nil->next;
nil->next = inserted;
++count;
}
/**
* @brief remove
*
* @param target shared pointer
*
* @complexity O(n)
*
* check ex10.2-1 for detail.
*/
void remove(sPointer target)
{
assert(target != nil && !empty());
prev(target)->next = target->next;
--count;
}
/**
* @brief reverse
*
* @complexity O(n)
*/
void reverse()
{
sPointer current = begin();
nil->next = nil;
while(current != nil)
{
insert(current->key);
current = current->next;
}
}
/**
* @brief size
*
* @complexity O(1)
*/
SizeType size() const
{
return count;
}
/**
* @brief empty
*/
bool empty() const
{
return begin() == end();
}
/**
* @brief begin
*/
const sPointer& begin() const
{
return nil->next;
}
/**
* @brief end
*/
const sPointer& end() const
{
return nil;
}
private:
/**
* @brief size counter
*/
SizeType count;
/**
* @brief nil
*
* used as a dummy sentinel on the list
*/
sPointer nil;
/**
* @brief search and return the predecessor of target
*/
sPointer prev(sPointer target) const
{
sPointer ptr = nil;
while(ptr->next != target)
ptr = ptr->next;
return ptr;
}
};
/**
* @brief operator <<
*/
template<typename T>
std::ostream& operator <<(std::ostream& os, const single_list_ring<T>& l)
{
auto ptr = l.begin();
while (ptr != l.end())
{
os << ptr->key << std::endl;
ptr = ptr->next;
}
return os;
}
}//namespace list
}//namespace ch10
#endif // SINGLE_LIST_H
//! test code for ex10.2-7
//#include <iostream>
//#include "single_list.hpp"
//int main()
//{
// ch10::list::single_list_ring<int> l;
// for(int i = 0; i != 10; ++i)
// l.insert(i);
// l.reverse();
// std::cout << l << std::endl;
//}