-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathreverse_a_linked_list.cpp
More file actions
208 lines (195 loc) · 5.43 KB
/
reverse_a_linked_list.cpp
File metadata and controls
208 lines (195 loc) · 5.43 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
/**
* @file
* @brief Implementation of [Reversing
* a single linked list](https://simple.wikipedia.org/wiki/Linked_list)
* @details
* The linked list is a data structure used for holding a sequence of
* values, which can be added, displayed, reversed, or removed.
* ### Algorithm
* Values can be added by iterating to the end of a list (by following
* the pointers) starting from the first link. Whichever link points to null
* is considered the last link and is pointed to the new value.
*
* Linked List can be reversed by using 3 pointers: current, previous, and
* next_node; we keep iterating until the last node. Meanwhile, before changing
* to the next of current, we store it in the next_node pointer, now we store
* the prev pointer in the current of next, this is where the actual reversal
* happens. And then we move the prev and current pointers one step forward.
* Then the head node is made to point to the last node (prev pointer) after
* completion of an iteration.
* [A graphic explanation and view of what's happening behind the
*scenes](https://drive.google.com/file/d/1pM5COF0wx-wermnNy_svtyZquaCUP2xS/view?usp=sharing)
*/
#include <cassert> /// for assert
#include <iostream> /// for I/O operations
#include <memory> /// for dynamic memory
#include <new> /// for managing dynamic storage
/**
* @namespace data_structures
* @brief Data Structures algorithms
*/
namespace data_structures {
/**
* @namespace linked_list
* @brief Functions for singly linked list algorithm
*/
namespace linked_list {
/**
* A Node class containing a value and pointer to another link
*/
class Node {
public:
int32_t val; /// value of the current link
Node *next; /// pointer to the next value on the list
};
/**
* A list class containing a sequence of links
*/
class list {
private:
Node *head; // link before the actual first element
public:
/**
* List constructor. Initializes the first link.
*/
list() {
head = nullptr; // Initialize the first link
}
bool isEmpty();
void insert(int32_t new_elem);
void reverseList();
void display();
int32_t top();
int32_t last();
int32_t traverse(int32_t index);
};
/**
* @brief Utility function that checks if the list is empty
* @returns true if the list is empty
* @returns false if the list is not empty
*/
bool list::isEmpty() { return head == nullptr; }
/**
* @brief Utility function that adds a new element at the end of the list
* @param new_elem element be added at the end of the list
*/
void list::insert(int32_t n) {
try {
Node *new_node = new Node();
Node *temp = nullptr;
new_node->val = n;
new_node->next = nullptr;
if (isEmpty()) {
head = new_node;
} else {
temp = head;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new_node;
}
} catch (std::bad_alloc &exception) {
std::cerr << "bad_alloc detected: " << exception.what() << "\n";
}
}
/**
* @brief Utility function for reversing a list
* @brief Using the current, previous, and next pointer.
* @returns void
*/
void list::reverseList() {
Node *curr = head;
Node *prev = nullptr, *next_node = nullptr;
while (curr != nullptr) {
next_node = curr->next;
curr->next = prev;
prev = curr;
curr = next_node;
}
head = prev;
}
/**
* @brief Utility function to find the top element of the list
* @returns the top element of the list
*/
int32_t list::top() {
try {
if (!isEmpty()) {
return head->val;
}
} catch (const std::exception &e) {
std::cerr << "List is empty" << e.what() << '\n';
}
}
/**
* @brief Utility function to find the last element of the list
* @returns the last element of the list
*/
int32_t list::last() {
try {
if (!isEmpty()) {
Node *t = head;
while (t->next != nullptr) {
t = t->next;
}
return t->val;
}
} catch (const std::exception &e) {
std::cerr << "List is empty" << e.what() << '\n';
}
}
/**
* @brief Utility function to find the i th element of the list
* @returns the i th element of the list
*/
int32_t list::traverse(int index) {
Node *current = head;
int count = 0;
while (current != nullptr) {
if (count == index) {
return (current->val);
}
count++;
current = current->next;
}
/* if we get to this line,the caller was asking for a non-existent element
so we assert fail */
assert(0);
}
} // namespace linked_list
} // namespace data_structures
/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
data_structures::linked_list::list L;
// 1st test
L.insert(11);
L.insert(12);
L.insert(15);
L.insert(10);
L.insert(-12);
L.insert(-20);
L.insert(18);
assert(L.top() == 11);
assert(L.last() == 18);
L.reverseList();
// Reversal Testing
assert(L.top() == 18);
assert(L.traverse(1) == -20);
assert(L.traverse(2) == -12);
assert(L.traverse(3) == 10);
assert(L.traverse(4) == 15);
assert(L.traverse(5) == 12);
assert(L.last() == 11);
std::cout << "All tests have successfully passed!" << std::endl;
}
/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
test(); // run self-test implementations
return 0;
}