-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCircular_linked_list.cpp
More file actions
443 lines (380 loc) · 11.2 KB
/
Circular_linked_list.cpp
File metadata and controls
443 lines (380 loc) · 11.2 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
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
//Divyansh 1903112
#include <iostream>
#include <algorithm>
using namespace std;
template <typename Object>
/*
|Circular_list is a circular linked list which consists of nodes and prev and next pointers.
|This is a class template for a circular linked list
|Iterators : iterators and cons_iterators can be created as for any other STL like vectors etc.
|Getting special node's iterators :begin() and end() returns first and last insertd element respectively.
|Inserting: Insertion can be done by insert function after the passed iterator.
|Inserting/removing elements at special location: push_front push_back pop_front.
pop_back can be used to insert/remove element at first/last inserted location as sugested by name.
|Erase: erase() function can be called to delete a particular node or a range of node as acoording
to the passed iterator. clear() erases the whole list
Size: size() functions return size of CLL
MOST OPERATONS USING ++ -- OPERATORS OR EQUALITY OPEAROTRS CAN BE USED AS WITH ANY OTHER STL, LISTS CAN BE ALSO ASSIGNED TO OTHER LISTS
VIEW SPECIFIC FUNCTIONS AND CLASSES TO KNOW IT'S WORKINGS AND ABOUT FUNCTIONS AND OPERATORS SUPPORTED
*/
/*
For IIT GOA CS 220 Assignment for Lab 4
FULLFILLING ASSIGNMENT REQUIREMENTS
add:
insert(iterator, const Object & x) adds at a specific location as decteted by first argument
push_front(Object) adds before first inserted element
push_back(Object) adds after the last inserted element
remove:
erase(iterator itr) removes the node coresponding to passed iterator
erase(iterator from, iterator to) removes all nodes between the passed iterators
erase(Object &) it removes all nodes with that data equal to passed parameter
pop_front() removes the oldest inserted element or the element inserted before oldest inserted element
pop_back() removes the latest inserted element or the elemnts inserted after that
clear() deletes the whole list
isEmpty:
empty() functions returns bool value coresponding to is list empty or not
size() returns the current size of the list
*/
class Circular_list{
private:
struct Node{
Object data;
Node *prev;
Node *next;
Node(const Object & d = Object{ }, Node* p = nullptr, Node *n = nullptr):data{d},prev{p},next{n} {}
Node (Object &&d, Node *p = nullptr, Node *n = nullptr):data{move(d)},prev{p},next{n} {}
};
public:
class const_iterator{
public:
const_iterator():current{nullptr}{}
const Object & operator* () const{
return retrieve();
}
const_iterator & operator++(){
current = current->next;
return *this;
}
const_iterator operator++(int){
const_iterator old = *this;
++(*this);
return old;
}
const_iterator & operator--(){
current = current->prev;
return *this;
}
const_iterator operator--(int){
const_iterator old = *this;
--(*this);
return old;
}
bool operator== (const const_iterator & rhs)const{
return current == rhs.current;
}
bool operator != (const const_iterator & rhs)const{
return !(*this==rhs);
}
protected:
Node *current;
Object & retrieve() const{
return current->data;
}
const_iterator(Node* p): current{p}
{}
friend class Circular_list<Object>;
};
class iterator : public const_iterator{
public:
iterator(){
;
}
Object & operator*(){
return const_iterator::retrieve();
}
const Object & operator* () const{
return const_iterator::operator*();
}
iterator & operator++(){
this->current = this->current->next;
return *this;
}
iterator operator++(int){
iterator old = *this;
++(*this);
return old;
}
iterator & operator--(){
this->current = this->current->prev;
return *this;
}
iterator operator--(int){
iterator old = *this;
--(*this);
return old;
}
protected:
iterator (Node *p): const_iterator{p}{}
friend class Circular_list<Object>;
};
public:
Circular_list(){
init();
}
Circular_list(const Circular_list & rhs){
init();
for(auto & x : rhs)
push_back(x);
}
~Circular_list(){
clear();
delete head;
delete tail;
}
Circular_list & operator= (const Circular_list & rhs ){
auto b = rhs.begin();
auto c = rhs.begin();
int counter = 0;
do{
this->push_back(*(b++));
}
while(b!=c);
return *this;
}
Circular_list(Circular_list && rhs):theSize{rhs.size()},head{rhs.head},tail{rhs.tail}{
rhs.theSize = 0;
rhs.head = nullptr;
rhs.tail = nullptr;
}
Circular_list & operator= (Circular_list && rhs){
swap( theSize, rhs.theSize );
swap( head, rhs.head );
swap( tail, rhs.tail );
return *this;
}
iterator begin(){
return {head->next};
}
const_iterator begin() const{
return{head->next};
}
iterator end(){
return {tail};
}
const_iterator end() const{
return {tail};
}
int size() const{
return theSize;
}
bool empty(){
return size() == 0;
}
void clear(){
while(!empty())
pop_front();
}
Object & front(){
return *begin();
}
const Object & front() const{
return *begin();
}
Object & back(){
return *--end();
}
const Object & back() const{
return *--end();
}
void push_front(const Object & x){
insert(begin(),x);
circularise();
}
void push_front(const Object && x){
insert(begin(),std::move(x));
circularise();
}
void push_back(const Object &x){
insert(end(),x);
circularise();
}
void push_back(const Object &&x){
insert(end(),std::move(x));
circularise();
}
int print(){
cout << "[circular list] ";
iterator b = begin();
if(empty())return 0;
cout << "..." ;
do{
cout << *(b++) <<" ";
}
while(b!=begin());
cout << "..." << endl;
return size();
}
void pop_front(){
erase(begin());
circularise();
}
void pop_back(){
erase(--end());
circularise();
}
iterator insert(iterator itr, const Object & x)
{
Node *p = itr.current;
theSize++;
p->prev = p->prev->next = new Node{x,p->prev,p};
circularise();
return p->prev;
}
iterator insert(iterator itr, const Object && x)
{
Node *p = itr.current;
theSize++;
p->prev = p->prev->next = new Node{move(x),p->prev,p};
circularise();
return p->prev;
}
iterator erase(iterator itr)
{
Node *p = itr.current;
iterator retVal {p->next};
p -> prev->next = p->next;
p -> next->prev = p->prev;
delete p;
theSize--;
circularise();
return retVal;
}
iterator find(const Object & x){
iterator a = begin();
int count = 0;
int flag = 0;
while(*a!=x){
++a;
++count;
if(count > size()){
flag = 1;
break;
}
}
if(flag ==1){
return tail;
}
return a;
}
void erase(const Object & x){
while(true){
iterator a = find(x);
if(a == tail) break;
erase(a);
}
}
iterator erase(iterator from, iterator to)
{
for(iterator itr = from; itr != to;)
itr = erase (itr);
circularise();
return to;
}
private:
int theSize;
Node * head;
Node * tail;
void circularise(){
//deleting the content of this function will convert the list into linear non circular linked list
if(size()>=1){
tail->prev->next = head->next;
head->prev = tail->prev;
}
}
void init(){
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
circularise();
}
};
int main(){
//creating a linked list for ints;
Circular_list<int> cl1;
//pushing elemnts just beside the oldest element and newest elemet
//all the below insertion takes O(1) time
cl1.push_front(5);
cl1.push_front(10);
cl1.push_front(3);
cl1.push_back(3);
cl1.push_front(5);
cl1.push_front(6);
cl1.push_back(3);
cl1.push_front(7);
cl1.push_back(2);
cl1.push_back(1);
//printing the list
cout << "cl1 is " << endl;
cl1.print();
//iterating the list using iterators
//though circular linked lists have no significance of begin but for
// the sake of chosing a starting point a node is selected as begin
Circular_list<int>::iterator a = cl1.begin();
int num = cl1.back();
//using *(dereference operator) with iterators
cout << "the begin node has value = " << *a << endl;
//using increment/decrement operator with iterators to move forward(clockwise)
a++;
cout << "element just beside the begin node in clockwise direction has value = " << *a << endl;
//finding one of the occurance of an element in linked list
Circular_list<int>::iterator f = cl1.find(3);
cout << "the node found has value ="<<*f << " and the next node(clockwise) has value = " <<*(++f) <<endl;
//returning to previous f
--f;
//making another list by assigning it already created list
Circular_list<int> cl2;
cl2 = cl1;
cout << "cl2 is ";
int k = cl2.print();
//inserting an element at a particular location
auto f1 = cl2.find(6);
cl2.insert(f1,-1); //will insert -1 before(counter clockwise) first 6(at its location);
cl2.print();
auto in = cl2.begin();
for(int i=0; i<5; i++){
in++;
}
cl2.insert(in,-2);
cl2.print();
//erasing a node
auto e = cl2.begin();
for(int i=0; i<3; i++){
e++;
}
cl2.erase(e); //will erase the node pointed by e (here 3 forward of begin)
cl2.print();
//erasing a integer
cl2.erase(3); //will delete all occurances of 3
cl2.print();
//getting size
cout << "now size of cl2 is " << cl2.size() << endl;
//is a list empty;
Circular_list <int> cl3;
cout << "empty() for cl2 returns " <<cl2.empty() << " and for cl3 returns "<<cl3.empty()<<endl;
//deleting the whole list
cl2.clear();
cout << "now size of cl2 is "<<cl2.size() <<endl;
//creating list of other data types
Circular_list <char> cl4;
cl4.push_back('D');
cl4.push_back('i');
cl4.push_back('v');
cl4.push_back('y');
cl4.push_back('a');
cl4.push_back('n');
cl4.push_back('s');
cl4.push_back('h');
cl4.print();
}