TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
reverse_a_linked_list.cpp
Go to the documentation of this file.
1
25#include <cassert>
26#include <iostream>
27#include <new>
28
33namespace data_structures {
38namespace linked_list {
42class Node {
43 public:
44 int32_t val;
46};
47
53Node* copy_all_nodes(const Node* const node) {
54 if (node) {
55 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
56 Node* res = new Node();
57 res->val = node->val;
58 res->next = copy_all_nodes(node->next);
59 return res;
60 }
61 return nullptr;
62}
63
67// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
68class list {
69 private:
70 Node* head = nullptr; // link before the actual first element
71 void delete_all_nodes();
72 void copy_all_nodes_from_list(const list& other);
73
74 public:
75 bool isEmpty() const;
76 void insert(int32_t new_elem);
77 void reverseList();
78 void display() const;
79 int32_t top() const;
80 int32_t last() const;
81 int32_t traverse(int32_t index) const;
82 ~list();
83 list() = default;
84 list(const list& other);
85 list& operator=(const list& other);
86};
87
93bool list::isEmpty() const { return head == nullptr; }
94
99void list::insert(int32_t n) {
100 try {
101 // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
102 Node* new_node = new Node();
103 Node* temp = nullptr;
104 new_node->val = n;
105 new_node->next = nullptr;
106 if (isEmpty()) {
107 head = new_node;
108 } else {
109 temp = head;
110 while (temp->next != nullptr) {
111 temp = temp->next;
112 }
113 temp->next = new_node;
114 }
115 } catch (std::bad_alloc& exception) {
116 std::cerr << "bad_alloc detected: " << exception.what() << "\n";
117 }
118}
119
126 Node* curr = head;
127 Node* prev = nullptr;
128 Node* next_node = nullptr;
129 while (curr != nullptr) {
130 next_node = curr->next;
131 curr->next = prev;
132 prev = curr;
133 curr = next_node;
134 }
135 head = prev;
136}
137
142int32_t list::top() const {
143 if (!isEmpty()) {
144 return head->val;
145 } else {
146 throw std::logic_error("List is empty");
147 }
148}
153int32_t list::last() const {
154 if (!isEmpty()) {
155 Node* t = head;
156 while (t->next != nullptr) {
157 t = t->next;
158 }
159 return t->val;
160 } else {
161 throw std::logic_error("List is empty");
162 }
163}
168int32_t list::traverse(int32_t index) const {
169 Node* current = head;
170
171 int count = 0;
172 while (current != nullptr) {
173 if (count == index) {
174 return (current->val);
175 }
176 count++;
177 current = current->next;
178 }
179
180 /* if we get to this line,the caller was asking for a non-existent element
181 so we assert fail */
182 exit(1);
183}
184
189 while (head != nullptr) {
190 const auto tmp_node = head->next;
191 delete head;
192 head = tmp_node;
193 }
194}
195
196list::~list() { delete_all_nodes(); }
197
198void list::copy_all_nodes_from_list(const list& other) {
199 assert(isEmpty());
200 head = copy_all_nodes(other.head);
201}
202
206list::list(const list& other) { copy_all_nodes_from_list(other); }
207
211list& list::operator=(const list& other) {
212 if (this == &other) {
213 return *this;
214 }
216
217 copy_all_nodes_from_list(other);
218 return *this;
219}
220
221} // namespace linked_list
222} // namespace data_structures
223
228static void test() {
230 // 1st test
231 L.insert(11);
232 L.insert(12);
233 L.insert(15);
234 L.insert(10);
235 L.insert(-12);
236 L.insert(-20);
237 L.insert(18);
238 assert(L.top() == 11);
239 assert(L.last() == 18);
240 L.reverseList();
241 // Reversal Testing
242 assert(L.top() == 18);
243 assert(L.traverse(1) == -20);
244 assert(L.traverse(2) == -12);
245 assert(L.traverse(3) == 10);
246 assert(L.traverse(4) == 15);
247 assert(L.traverse(5) == 12);
248 assert(L.last() == 11);
249 std::cout << "All tests have successfully passed!" << std::endl;
250}
251
252void test_copy_constructor() {
254 L.insert(10);
255 L.insert(20);
256 L.insert(30);
258 otherList.insert(40);
259
260 L.insert(400);
261
262 assert(L.top() == 10);
263 assert(otherList.top() == 10);
264 assert(L.traverse(1) == 20);
265 assert(otherList.traverse(1) == 20);
266
267 assert(L.traverse(2) == 30);
268 assert(otherList.traverse(2) == 30);
269
270 assert(L.last() == 400);
271 assert(otherList.last() == 40);
272}
273
274void test_assignment_operator() {
277 L.insert(10);
278 L.insert(20);
279 L.insert(30);
280 otherList = L;
281
282 otherList.insert(40);
283 L.insert(400);
284
285 assert(L.top() == 10);
286 assert(otherList.top() == 10);
287 assert(L.traverse(1) == 20);
288 assert(otherList.traverse(1) == 20);
289
290 assert(L.traverse(2) == 30);
291 assert(otherList.traverse(2) == 30);
292
293 assert(L.last() == 400);
294 assert(otherList.last() == 40);
295}
296
301int main() {
302 test(); // run self-test implementations
303 test_copy_constructor();
304 test_assignment_operator();
305 return 0;
306}
Node * next
value of the current link
int32_t traverse(int32_t index) const
Utility function to find the i th element of the list.
int32_t top() const
Utility function to find the top element of the list.
void insert(int32_t new_elem)
Utility function that adds a new element at the end of the list.
void reverseList()
Utility function for reversing a list.
void delete_all_nodes()
calls delete operator on every node in the represented list
list & operator=(const list &other)
assignment operator creating a deep copy of every node of the input
std::shared_ptr< link > last
last link on the list
for IO operations
Functions for singly linked list algorithm.
Node * copy_all_nodes(const Node *const node)
creates a deep copy of a list starting at the input node
static void test()
Self-test implementations.
int main()
Main function.