From 6e77f98494898915f8ca2c91427ccb1e7cf5ad80 Mon Sep 17 00:00:00 2001 From: Bolaji Boluwatife Date: Fri, 4 Sep 2020 01:01:50 +0100 Subject: [PATCH] Revised Linked List (#999) * Addition of Test to LinkedList I noticed an infinite loop when the program asks the user to "Enter the element to be inserted:", and the user enters a wrong input such as "rr". * Revised Tests * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update data_structures/linked_list.cpp Co-authored-by: David Leal * Update data_structures/linked_list.cpp Co-authored-by: David Leal * Update data_structures/linked_list.cpp Co-authored-by: David Leal * Update data_structures/linked_list.cpp Co-authored-by: David Leal * Update data_structures/linked_list.cpp Co-authored-by: David Leal * Update data_structures/linked_list.cpp Co-authored-by: David Leal * Update data_structures/linked_list.cpp Co-authored-by: David Leal * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update data_structures/linked_list.cpp Co-authored-by: David Leal * added documentations to functions I made a few changes although I'm not sure I covered all. * Update linked_list.cpp * function documentation Co-authored-by: David Leal * function documentation Co-authored-by: David Leal * function documentation * Update linked_list.cpp * removed global variable I decided to go with the parameter approach. Is line 79(Iter& ....) and others like it considered healthy code? * removed global variable * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * fixed clang errors * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * program rewrite * Update linked_list.cpp * Update linked_list.cpp * Removed extra space * Update linked_list.cpp * Delete vdoubly_linked_list.ico * added documentation * added documentation * added documentation * use of shared_ptr * use of shared_ptr * modified linked list * Update linked_list.cpp * added string header * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * fixed documentation * fixed link class * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * Update linked_list.cpp * fixed link class * fixed runtime error Co-authored-by: David Leal --- data_structures/linked_list.cpp | 355 ++++++++++++++++++++++---------- 1 file changed, 248 insertions(+), 107 deletions(-) diff --git a/data_structures/linked_list.cpp b/data_structures/linked_list.cpp index 8eb6e586d..72003ba0c 100644 --- a/data_structures/linked_list.cpp +++ b/data_structures/linked_list.cpp @@ -1,134 +1,275 @@ +/** + * @file + * @brief Implementation of singly linked list algorithm. + * @details + * The linked list is a data structure used for holding a sequence of + * values, which can be added, removed and displayed. + * ### 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. + * + * Values can be removed by also iterating through the list. When the node + * containing the value is found, the node pointing to the current node is made + * to point to the node that the current node is pointing to, and then returning + * the current node to heap store. + */ #include +#include +#include -struct node { - int val; - node *next; +/** + * @namespace data_structures + * @brief Data Structures algorithms + */ +namespace data_structures { + +/** + * @namespace linked_list + * @brief Functions for singly linked list algorithm + */ +namespace linked_list { + +/** + * This function checks if the string passed consists + * of only digits. + * @param s To be checked if s contains only integers + * @returns true if there are only only digits present in the string + * @returns false if any other character is found + */ +bool isDigit(const std::string& s) { + // function statements here + for (char i : s) { + if (!isdigit(i)) { + return false; + } + } + return true; +} + +/** + * A link class containing a value and pointer to another link + */ +class link { + private: + int pvalue; ///< value of the current link + std::shared_ptr psucc; ///< pointer to the next value on the list + + public: + /** + * function returns the integer value stored in the link. + * @returns the integer value stored in the link. + */ + int val() { return pvalue; } + + /** + * function returns the pointer to next link + * @returns the pointer to the next link + * */ + std::shared_ptr& succ() { return psucc; } + + /** + * Creates link with provided value and pointer to next link + * @param value is the integer stored in the link + */ + explicit link(int value = 0) : pvalue(value), psucc(nullptr) {} }; -node *start; +/** + * A list class containing a sequence of links + */ +class list { + private: + std::shared_ptr first; ///< link before the actual first element + std::shared_ptr last; ///< last link on the list + public: + /** + * List constructor. Initializes the first and last link. + */ + list() { + // Initialize the first link + first = std::make_shared(); + // Initialize the last link with the first link + last = nullptr; + } -void insert(int x) { - node *t = start; - node *n = new node; - n->val = x; - n->next = NULL; - if (start != NULL) { - while (t->next != NULL) { - t = t->next; - } - t->next = n; + bool isEmpty(); + + void push_back(int new_elem); + void push_front(int new_elem); + void erase(int old_elem); + void display(); + std::shared_ptr search(int find_elem); + void reverse(); +}; + +/** + * function checks if list is empty + * @returns true if list is empty + * @returns false if list is not empty + */ +bool list::isEmpty() { + if (last == nullptr) { + return true; } else { - start = n; + return false; } } -void remove(int x) { - if (start == NULL) { - std::cout << "\nLinked List is empty\n"; - return; - } else if (start->val == x) { - node *temp = start; - start = start->next; - delete temp; - return; - } - - node *temp = start, *parent = start; - - while (temp != NULL && temp->val != x) { - parent = temp; - temp = temp->next; - } - - if (temp == NULL) { - std::cout << std::endl << x << " not found in list\n"; - return; - } - - parent->next = temp->next; - delete temp; -} - -void search(int x) { - node *t = start; - int found = 0; - while (t != NULL) { - if (t->val == x) { - std::cout << "\nFound"; - found = 1; - break; - } - t = t->next; - } - if (found == 0) { - std::cout << "\nNot Found"; - } -} - -void show() { - node *t = start; - while (t != NULL) { - std::cout << t->val << "\t"; - t = t->next; - } -} - -void reverse() { - node *first = start; - if (first != NULL) { - node *second = first->next; - while (second != NULL) { - node *tem = second->next; - second->next = first; - first = second; - second = tem; - } - start->next = NULL; - start = first; +/** + * function adds new element to the end of the list + * @param new_elem to be added to the end of the list + */ +void list::push_back(int new_elem) { + if (isEmpty()) { + first->succ() = std::make_shared(new_elem); + last = first->succ(); } else { - std::cout << "\nEmpty list"; + last->succ() = std::make_shared(new_elem); + last = last->succ(); } } +/** + * function adds new element to the beginning of the list + * @param new_elem to be added to front of the list + */ +void list::push_front(int new_elem) { + if (isEmpty()) { + first->succ() = std::make_shared(new_elem); + last = first->succ(); + } else { + std::shared_ptr t = std::make_shared(new_elem); + t->succ() = first->succ(); + first->succ() = t; + } +} + +/** + * function erases old element from the list + * @param old_elem to be erased from the list + */ +void list::erase(int old_elem) { + if (isEmpty()) { + std::cout << "List is Empty!"; + return; + } + std::shared_ptr t = first; + std::shared_ptr to_be_removed = nullptr; + while (t != last && t->succ()->val() != old_elem) { + t = t->succ(); + } + if (t == last) { + std::cout << "Element not found\n"; + return; + } + to_be_removed = t->succ(); + t->succ() = t->succ()->succ(); + to_be_removed.reset(); + if (t->succ() == nullptr) { + last = nullptr; + } +} + +/** + * function displays all the elements in the list + * @returns 'void' + */ +void list::display() { + if (isEmpty()) { + std::cout << "List is Empty!"; + return; + } + std::shared_ptr t = first; + while (t->succ() != nullptr) { + std::cout << t->succ()->val() << "\t"; + t = t->succ(); + } +} + +/** + * function searchs for @param find_elem in the list + * @param find_elem to be searched for in the list + */ +std::shared_ptr list::search(int find_elem) { + if (isEmpty()) { + std::cout << "List is Empty!"; + return nullptr; + } + std::shared_ptr t = first; + while (t != last && t->succ()->val() != find_elem) { + t = t->succ(); + } + if (t == last) { + std::cout << "Element not found\n"; + return nullptr; + } + std::cout << "Element was found\n"; + return t->succ(); +} +} // namespace linked_list +} // namespace data_structures + +/** + * Main function: + * Allows the user add and delete values from the list. + * Also allows user to search for and display values in the list. + * @returns 0 on exit + */ int main() { - int choice, x; + data_structures::linked_list::list l; + int choice = 0; + int x = 0; + std::string s; do { std::cout << "\n1. Insert"; std::cout << "\n2. Delete"; std::cout << "\n3. Search"; std::cout << "\n4. Print"; - std::cout << "\n5. Reverse"; std::cout << "\n0. Exit"; std::cout << "\n\nEnter you choice : "; std::cin >> choice; switch (choice) { - case 1: - std::cout << "\nEnter the element to be inserted : "; - std::cin >> x; - insert(x); - break; - case 2: - std::cout << "\nEnter the element to be removed : "; - std::cin >> x; - remove(x); - break; - case 3: - std::cout << "\nEnter the element to be searched : "; - std::cin >> x; - search(x); - break; - case 4: - show(); - std::cout << "\n"; - break; - case 5: - std::cout << "The reversed list: \n"; - reverse(); - show(); - std::cout << "\n"; - break; + case 1: + std::cout << "\nEnter the element to be inserted : "; + std::cin >> s; + + if (data_structures::linked_list::isDigit(s)) { + x = std::stoi(s); + l.push_back(x); + } else { + std::cout << "Wrong Input!\n"; + } + break; + case 2: + std::cout << "\nEnter the element to be removed : "; + std::cin >> s; + if (data_structures::linked_list::isDigit(s)) { + x = std::stoi(s); + l.erase(x); + } else { + std::cout << "Wrong Input!\n"; + } + break; + case 3: + std::cout << "\nEnter the element to be searched : "; + std::cin >> s; + if (data_structures::linked_list::isDigit(s)) { + x = std::stoi(s); + std::shared_ptr found = + l.search(x); + } else { + std::cout << "Wrong Input!\n"; + } + break; + case 4: + l.display(); + std::cout << "\n"; + break; + default: + std::cout << "Invalid Input\n" << std::endl; + break; } } while (choice != 0); - return 0; }