forked from TheAlgorithms/C-Plus-Plus
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add reverse linked list algorithim (TheAlgorithms#1596)
* add: reverse linked list algorithim * updating DIRECTORY.md * clang-format and clang-tidy fixes for 5cac47c * Update data_structures/reverse_a_linked_list.cpp Co-authored-by: David Leal <[email protected]> * Update data_structures/reverse_a_linked_list.cpp Co-authored-by: David Leal <[email protected]> * Update the description in data_structures/reverse_a_linked_list.cpp Co-authored-by: David Leal <[email protected]> * clang-format and clang-tidy fixes for 19b4a93 * Updating data_structures/reverse_a_linked_list.cpp Co-authored-by: David Leal <[email protected]> * add:test for the reversing algorithim * fix: synatx changes * docs :added an external link for explanation of the algorithim * fix: suggested changes * fix: chamges in the code * docs : changes required in the docs * docs :fix indentation * fix : ouptut statement changes * fix: clang-tidy warnings * formatting filenames f769503 * updating DIRECTORY.md * clang-format and clang-tidy fixes for f769503 * fix : display function removed * updating DIRECTORY.md * clang-format and clang-tidy fixes for 38547be * fix: changed the data types * clang-format and clang-tidy fixes for 3b2e68c * docs : documentation fixes Co-authored-by: David Leal <[email protected]> * docs : documentation changes Co-authored-by: David Leal <[email protected]> * clang-format and clang-tidy fixes for 57953be * docs: fix changes Co-authored-by: David Leal <[email protected]> * clang-format and clang-tidy fixes for db8e74a * fix : display changes Co-authored-by: ERR ! <[email protected]> * fix : added try block * fix: try-catch block * fix :merge conflict * docs:documentation changes * added more efficient test cases * clang-format and clang-tidy fixes for 83ee6e4 * Update data_structures/reverse_a_linked_list.cpp Co-authored-by: David Leal <[email protected]> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal <[email protected]> Co-authored-by: Abhinn Mishra <[email protected]> Co-authored-by: ERR ! <[email protected]>
- Loading branch information
1 parent
5245b3e
commit f7a5aec
Showing
2 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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; | ||
} |