-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathdoubly_linked_list_v3.h
132 lines (115 loc) · 3.24 KB
/
doubly_linked_list_v3.h
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
#pragma once
#include <iostream>
// doubly-linked list node
template<class T>
class Link {
public:
T value;
explicit Link(const T& v, Link* p = nullptr, Link* s = nullptr)
:value(v), prev(p), succ(s) {}
Link* insert(Link* n);
Link* add(Link* n);
Link* add_ordered(Link* n);
Link* erase();
Link* find(const T& v);
const Link* find(const T& v) const;
Link* advance(int n);
const Link* advance(int n) const;
Link* next() const { return succ; }
Link* previous() const { return prev; }
private:
Link* prev;
Link* succ;
};
// insert n before this object; return n
template<class T>
Link<T>* Link<T>::insert(Link* n) {
if (n == nullptr) return this; // nothing to insert
n->succ = this; // this object comes after n
if (prev) prev->succ = n; // n comes after what used to be p's predecessor
n->prev = prev; // this object's predecessor becomes n's predecessor
prev = n; // n becomes this object's predecessor
return n;
}
// insert n after this object; return n
template<class T>
Link<T>* Link<T>::add(Link* n) {
if (n == nullptr) return this;
n->succ = succ;
n->prev = this;
if (succ) succ->prev = n;
succ = n;
return n;
}
// insert n in correct lexicographical position; return n
template<class T>
Link<T>* Link<T>::add_ordered(Link* n) {
if (n == nullptr) return this;
if (n->value < value)
return insert(n);
Link* p = this;
while (p->next() && (p->next()->value < n->value || p->next()->value == n->value))
p = p->next();
return p->add(n);
}
// remove this object from list; return this object's successor
template<class T>
Link<T>* Link<T>::erase() {
if (succ) succ->prev = prev;
if (prev) prev->succ = succ;
return succ;
}
// find v in list; return nullptr for "not found"
template<class T>
Link<T>* Link<T>::find(const T& v) {
return const_cast<Link*>(static_cast<const Link*>(this)->find(v));
}
// find v in const list; return nullptr for "not found"
template<class T>
const Link<T>* Link<T>::find(const T& v) const {
const Link* p = this;
while (p) {
if (p->value == v) return p;
p = p->succ;
}
return nullptr;
}
// move n positions in list; return nullptr for "not found"
// positive n moves forward, negative backward
template<class T>
Link<T>* Link<T>::advance(int n) {
return const_cast<Link*>(static_cast<const Link*>(this)->advance(n));
}
// move n positions in const list; return nullptr for "not found"
// positive n moves forward, negative backward
template<class T>
const Link<T>* Link<T>::advance(int n) const {
const Link* p = this;
if (n > 0) {
while (n--) {
if (p->succ == nullptr) return nullptr;
p = p->succ;
}
}
else if (n < 0) {
while (n++) {
if (p->prev == nullptr) return nullptr;
p = p->prev;
}
}
return p;
}
template<class T>
std::ostream& operator<<(std::ostream& os, Link<T>* p) {
for (; p; p = p->next())
os << p->value << std::endl;
return os;
}
template<class T>
void destroy(Link<T>* p) {
while (p) {
Link<T>* next = p->next();
delete p;
p = next;
}
}