-
Notifications
You must be signed in to change notification settings - Fork 0
/
Circular_list.h
249 lines (220 loc) · 6.51 KB
/
Circular_list.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
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
//! Tarefa de Estruturas de Dados - Lista Circular
/*
\author Alan Vinicius Cezar Ensina - Matrícula 16206354
\since 15/04/2018
\version 1.0
\copyright @ Alan Ensina
*/
#ifndef STRUCTURES_CIRCULAR_LIST_H
#define STRUCTURES_CIRCULAR_LIST_H
#include <cstdint>
#include <stdexcept>
namespace structures {
//! Declaração da classe lista circular
template<typename T>
class CircularList {
public:
//! Construtor padrão
CircularList() {
size_ = 0;
head = new Node((T)NULL, nullptr);
head->next(head);
}
//! Destrutor de objetos
~CircularList() {
clear();
delete head;
}
//! Método que limpa a lista circular
void clear() {
while (!empty()) {
pop_front();
}
}
//! Método que insere um elemento no fim
void push_back(const T& data) {
if (empty()) {
return push_front(data);
} else {
Node* novoElemento = new Node(data, head);
if (novoElemento == nullptr) {
throw std::out_of_range("Erro: a lista está cheia!");
}
end()->next(novoElemento);
++size_;
}
}
//! Método que insere um elemento no início da lista
void push_front(const T& data) {
head->next(new Node(data, head->next()));
++size_;
}
//! Método que insere um elemento na posição desejada
void insert(const T& data, std::size_t index) {
if (index > size_) {
throw std::out_of_range("Erro: posição inválida!");
} else if (index == size_) {
return push_back(data);
} else if (index == 0) {
return push_front(data);
} else {
Node* novoElemento = new Node(data);
if (novoElemento == nullptr) {
throw std::out_of_range("Erro: a lista está cheia!");
}
auto anterior = head->next();
for (auto i = 1u; i < index; ++i) {
anterior = anterior->next();
}
novoElemento->next(anterior->next());
anterior->next(novoElemento);
++size_;
}
}
//! Método que insere um novo elemento na ordem
void insert_sorted(const T& data) {
if (empty()) {
return push_front(data);
}
Node* atual = head->next();
auto i = 0u;
while (i < size_ && atual->data() < data) {
atual = atual->next();
++i;
}
return insert(data, i);
}
//! Método que verifica um elemento no índice dado por parâmetro
T& at(std::size_t index) {
if (empty()) {
throw std::out_of_range("Erro: a lista está vazia!");
} else if (index >= size_) {
throw std::out_of_range("Erro: posição inválida!");
} else {
auto aux = head->next();
for (auto i = 0u; i < index; ++i) {
aux = aux->next();
}
return aux->data();
}
}
//! Método que verifica um elemento const no índice dado por parâmetro
const T& at(std::size_t index) const {
auto aux = head->next();
for (auto i = 0u; i < index; ++i) {
aux = aux->next();
}
return aux->data();
}
//! Método que retira um elemento da posição dada por parâmetro
T pop(std::size_t index) {
if (index >= size()) {
throw std::out_of_range("Erro: posição inválida!");
}
if (index == 0) {
return pop_front();
}
auto aux = head->next();
for (auto i = 1u; i < index; ++i) {
aux = aux->next();
}
auto del = aux->next();
auto data = del->data();
aux->next(del->next());
--size_;
delete del;
return data;
}
//! Método que remove um elemento no fim da lista
T pop_back() {
if (size() == 1) {
return pop_front();
}
return pop(size() - 1);
}
//! Método que remove um elemento no início da lista
T pop_front() {
if (empty()) {
throw std::out_of_range("Erro: a lista está vazia!");
}
T dado = head->next()->data();
auto deleta = head->next();
head->next(deleta->next());
delete deleta;
--size_;
return dado;
}
//! Método que remove um elemento específico da lista
void remove(const T& data) {
pop(find(data));
}
//! Método que informa se a listá está vazia.
bool empty() const {
return size_ == 0;
}
//! Método que informa se a listá contém determinado elemento.
bool contains(const T& data) const {
if (find(data) == size()) {
return false;
}
return true;
}
//! Método que retorna a posição de um elemento na lista
std::size_t find(const T& data) const {
if (empty()) {
throw std::out_of_range("Erro lista vazia!");
}
auto aux = head->next();
for (auto i = 0u; i < size(); ++i) {
if (aux->data() == data) {
return i;
}
aux = aux->next();
}
return size_;
}
//! Método que informa o tamanho da lista.
std::size_t size() const {
return size_;
}
private:
class Node { // Elemento
public:
explicit Node(const T& data):
data_{data}
{}
Node(const T& data, Node* next):
data_{data},
next_{next}
{}
T& data() { // getter: dado
return data_;
}
const T& data() const { // getter const: dado
return data_;
}
Node* next() { // getter: próximo
return next_;
}
const Node* next() const { // getter const: próximo
return next_;
}
void next(Node* node) { // setter: próximo
next_ = node;
}
private:
T data_;
Node* next_{nullptr};
};
Node* end() { // último nodo da lista
auto it = head->next();
for (auto i = 1u; i < size(); ++i) {
it = it->next();
}
return it;
}
Node* head;
std::size_t size_;
};
} // namespace structures
#endif