|
| 1 | +/** |
| 2 | + * @file |
| 3 | + * @brief Implementation of singly linked list algorithm. |
| 4 | + * @details |
| 5 | + * The linked list is a data structure used for holding a sequence of |
| 6 | + * values, which can be added, removed and displayed. |
| 7 | + * ### Algorithm |
| 8 | + * Values can be added by iterating to the end of a list(by following |
| 9 | + * the pointers) starting from the first link. Whichever link points to null |
| 10 | + * is considered the last link and is pointed to the new value. |
| 11 | + * |
| 12 | + * Values can be removed by also iterating through the list. When the node |
| 13 | + * containing the value is found, the node pointing to the current node is made |
| 14 | + * to point to the node that the current node is pointing to, and then returning |
| 15 | + * the current node to heap store. |
| 16 | + */ |
1 | 17 | #include <iostream>
|
| 18 | +#include <memory> |
| 19 | +#include <string> |
2 | 20 |
|
3 |
| -struct node { |
4 |
| - int val; |
5 |
| - node *next; |
6 |
| -}; |
| 21 | +/** |
| 22 | + * @namespace data_structures |
| 23 | + * @brief Data Structures algorithms |
| 24 | + */ |
| 25 | +namespace data_structures { |
7 | 26 |
|
8 |
| -node *start; |
| 27 | +/** |
| 28 | + * @namespace linked_list |
| 29 | + * @brief Functions for singly linked list algorithm |
| 30 | + */ |
| 31 | +namespace linked_list { |
9 | 32 |
|
10 |
| -void insert(int x) { |
11 |
| - node *t = start; |
12 |
| - node *n = new node; |
13 |
| - n->val = x; |
14 |
| - n->next = NULL; |
15 |
| - if (start != NULL) { |
16 |
| - while (t->next != NULL) { |
17 |
| - t = t->next; |
| 33 | +/** |
| 34 | + * This function checks if the string passed consists |
| 35 | + * of only digits. |
| 36 | + * @param s To be checked if s contains only integers |
| 37 | + * @returns true if there are only only digits present in the string |
| 38 | + * @returns false if any other character is found |
| 39 | + */ |
| 40 | +bool isDigit(const std::string& s) { |
| 41 | + // function statements here |
| 42 | + for (char i : s) { |
| 43 | + if (!isdigit(i)) { |
| 44 | + return false; |
18 | 45 | }
|
19 |
| - t->next = n; |
20 |
| - } else { |
21 |
| - start = n; |
22 | 46 | }
|
| 47 | + return true; |
23 | 48 | }
|
24 | 49 |
|
25 |
| -void remove(int x) { |
26 |
| - if (start == NULL) { |
27 |
| - std::cout << "\nLinked List is empty\n"; |
28 |
| - return; |
29 |
| - } else if (start->val == x) { |
30 |
| - node *temp = start; |
31 |
| - start = start->next; |
32 |
| - delete temp; |
33 |
| - return; |
| 50 | +/** |
| 51 | + * A link class containing a value and pointer to another link |
| 52 | + */ |
| 53 | +class link { |
| 54 | + private: |
| 55 | + int pvalue; ///< value of the current link |
| 56 | + std::shared_ptr<link> psucc; ///< pointer to the next value on the list |
| 57 | + |
| 58 | + public: |
| 59 | + /** |
| 60 | + * function returns the integer value stored in the link. |
| 61 | + * @returns the integer value stored in the link. |
| 62 | + */ |
| 63 | + int val() { return pvalue; } |
| 64 | + |
| 65 | + /** |
| 66 | + * function returns the pointer to next link |
| 67 | + * @returns the pointer to the next link |
| 68 | + * */ |
| 69 | + std::shared_ptr<link>& succ() { return psucc; } |
| 70 | + |
| 71 | + /** |
| 72 | + * Creates link with provided value and pointer to next link |
| 73 | + * @param value is the integer stored in the link |
| 74 | + */ |
| 75 | + explicit link(int value = 0) : pvalue(value), psucc(nullptr) {} |
| 76 | +}; |
| 77 | + |
| 78 | +/** |
| 79 | + * A list class containing a sequence of links |
| 80 | + */ |
| 81 | +class list { |
| 82 | + private: |
| 83 | + std::shared_ptr<link> first; ///< link before the actual first element |
| 84 | + std::shared_ptr<link> last; ///< last link on the list |
| 85 | + public: |
| 86 | + /** |
| 87 | + * List constructor. Initializes the first and last link. |
| 88 | + */ |
| 89 | + list() { |
| 90 | + // Initialize the first link |
| 91 | + first = std::make_shared<link>(); |
| 92 | + // Initialize the last link with the first link |
| 93 | + last = nullptr; |
34 | 94 | }
|
35 | 95 |
|
36 |
| - node *temp = start, *parent = start; |
| 96 | + bool isEmpty(); |
| 97 | + |
| 98 | + void push_back(int new_elem); |
| 99 | + void push_front(int new_elem); |
| 100 | + void erase(int old_elem); |
| 101 | + void display(); |
| 102 | + std::shared_ptr<link> search(int find_elem); |
| 103 | + void reverse(); |
| 104 | +}; |
37 | 105 |
|
38 |
| - while (temp != NULL && temp->val != x) { |
39 |
| - parent = temp; |
40 |
| - temp = temp->next; |
| 106 | +/** |
| 107 | + * function checks if list is empty |
| 108 | + * @returns true if list is empty |
| 109 | + * @returns false if list is not empty |
| 110 | + */ |
| 111 | +bool list::isEmpty() { |
| 112 | + if (last == nullptr) { |
| 113 | + return true; |
| 114 | + } else { |
| 115 | + return false; |
41 | 116 | }
|
| 117 | +} |
42 | 118 |
|
43 |
| - if (temp == NULL) { |
44 |
| - std::cout << std::endl << x << " not found in list\n"; |
45 |
| - return; |
| 119 | +/** |
| 120 | + * function adds new element to the end of the list |
| 121 | + * @param new_elem to be added to the end of the list |
| 122 | + */ |
| 123 | +void list::push_back(int new_elem) { |
| 124 | + if (isEmpty()) { |
| 125 | + first->succ() = std::make_shared<link>(new_elem); |
| 126 | + last = first->succ(); |
| 127 | + } else { |
| 128 | + last->succ() = std::make_shared<link>(new_elem); |
| 129 | + last = last->succ(); |
46 | 130 | }
|
| 131 | +} |
47 | 132 |
|
48 |
| - parent->next = temp->next; |
49 |
| - delete temp; |
| 133 | +/** |
| 134 | + * function adds new element to the beginning of the list |
| 135 | + * @param new_elem to be added to front of the list |
| 136 | + */ |
| 137 | +void list::push_front(int new_elem) { |
| 138 | + if (isEmpty()) { |
| 139 | + first->succ() = std::make_shared<link>(new_elem); |
| 140 | + last = first->succ(); |
| 141 | + } else { |
| 142 | + std::shared_ptr<link> t = std::make_shared<link>(new_elem); |
| 143 | + t->succ() = first->succ(); |
| 144 | + first->succ() = t; |
| 145 | + } |
50 | 146 | }
|
51 | 147 |
|
52 |
| -void search(int x) { |
53 |
| - node *t = start; |
54 |
| - int found = 0; |
55 |
| - while (t != NULL) { |
56 |
| - if (t->val == x) { |
57 |
| - std::cout << "\nFound"; |
58 |
| - found = 1; |
59 |
| - break; |
60 |
| - } |
61 |
| - t = t->next; |
| 148 | +/** |
| 149 | + * function erases old element from the list |
| 150 | + * @param old_elem to be erased from the list |
| 151 | + */ |
| 152 | +void list::erase(int old_elem) { |
| 153 | + if (isEmpty()) { |
| 154 | + std::cout << "List is Empty!"; |
| 155 | + return; |
62 | 156 | }
|
63 |
| - if (found == 0) { |
64 |
| - std::cout << "\nNot Found"; |
| 157 | + std::shared_ptr<link> t = first; |
| 158 | + std::shared_ptr<link> to_be_removed = nullptr; |
| 159 | + while (t != last && t->succ()->val() != old_elem) { |
| 160 | + t = t->succ(); |
| 161 | + } |
| 162 | + if (t == last) { |
| 163 | + std::cout << "Element not found\n"; |
| 164 | + return; |
| 165 | + } |
| 166 | + to_be_removed = t->succ(); |
| 167 | + t->succ() = t->succ()->succ(); |
| 168 | + to_be_removed.reset(); |
| 169 | + if (t->succ() == nullptr) { |
| 170 | + last = nullptr; |
65 | 171 | }
|
66 | 172 | }
|
67 | 173 |
|
68 |
| -void show() { |
69 |
| - node *t = start; |
70 |
| - while (t != NULL) { |
71 |
| - std::cout << t->val << "\t"; |
72 |
| - t = t->next; |
| 174 | +/** |
| 175 | + * function displays all the elements in the list |
| 176 | + * @returns 'void' |
| 177 | + */ |
| 178 | +void list::display() { |
| 179 | + if (isEmpty()) { |
| 180 | + std::cout << "List is Empty!"; |
| 181 | + return; |
| 182 | + } |
| 183 | + std::shared_ptr<link> t = first; |
| 184 | + while (t->succ() != nullptr) { |
| 185 | + std::cout << t->succ()->val() << "\t"; |
| 186 | + t = t->succ(); |
73 | 187 | }
|
74 | 188 | }
|
75 | 189 |
|
76 |
| -void reverse() { |
77 |
| - node *first = start; |
78 |
| - if (first != NULL) { |
79 |
| - node *second = first->next; |
80 |
| - while (second != NULL) { |
81 |
| - node *tem = second->next; |
82 |
| - second->next = first; |
83 |
| - first = second; |
84 |
| - second = tem; |
85 |
| - } |
86 |
| - start->next = NULL; |
87 |
| - start = first; |
88 |
| - } else { |
89 |
| - std::cout << "\nEmpty list"; |
| 190 | +/** |
| 191 | + * function searchs for @param find_elem in the list |
| 192 | + * @param find_elem to be searched for in the list |
| 193 | + */ |
| 194 | +std::shared_ptr<link> list::search(int find_elem) { |
| 195 | + if (isEmpty()) { |
| 196 | + std::cout << "List is Empty!"; |
| 197 | + return nullptr; |
| 198 | + } |
| 199 | + std::shared_ptr<link> t = first; |
| 200 | + while (t != last && t->succ()->val() != find_elem) { |
| 201 | + t = t->succ(); |
90 | 202 | }
|
| 203 | + if (t == last) { |
| 204 | + std::cout << "Element not found\n"; |
| 205 | + return nullptr; |
| 206 | + } |
| 207 | + std::cout << "Element was found\n"; |
| 208 | + return t->succ(); |
91 | 209 | }
|
| 210 | +} // namespace linked_list |
| 211 | +} // namespace data_structures |
92 | 212 |
|
| 213 | +/** |
| 214 | + * Main function: |
| 215 | + * Allows the user add and delete values from the list. |
| 216 | + * Also allows user to search for and display values in the list. |
| 217 | + * @returns 0 on exit |
| 218 | + */ |
93 | 219 | int main() {
|
94 |
| - int choice, x; |
| 220 | + data_structures::linked_list::list l; |
| 221 | + int choice = 0; |
| 222 | + int x = 0; |
| 223 | + std::string s; |
95 | 224 | do {
|
96 | 225 | std::cout << "\n1. Insert";
|
97 | 226 | std::cout << "\n2. Delete";
|
98 | 227 | std::cout << "\n3. Search";
|
99 | 228 | std::cout << "\n4. Print";
|
100 |
| - std::cout << "\n5. Reverse"; |
101 | 229 | std::cout << "\n0. Exit";
|
102 | 230 | std::cout << "\n\nEnter you choice : ";
|
103 | 231 | std::cin >> choice;
|
104 | 232 | switch (choice) {
|
105 |
| - case 1: |
106 |
| - std::cout << "\nEnter the element to be inserted : "; |
107 |
| - std::cin >> x; |
108 |
| - insert(x); |
109 |
| - break; |
110 |
| - case 2: |
111 |
| - std::cout << "\nEnter the element to be removed : "; |
112 |
| - std::cin >> x; |
113 |
| - remove(x); |
114 |
| - break; |
115 |
| - case 3: |
116 |
| - std::cout << "\nEnter the element to be searched : "; |
117 |
| - std::cin >> x; |
118 |
| - search(x); |
119 |
| - break; |
120 |
| - case 4: |
121 |
| - show(); |
122 |
| - std::cout << "\n"; |
123 |
| - break; |
124 |
| - case 5: |
125 |
| - std::cout << "The reversed list: \n"; |
126 |
| - reverse(); |
127 |
| - show(); |
128 |
| - std::cout << "\n"; |
129 |
| - break; |
| 233 | + case 1: |
| 234 | + std::cout << "\nEnter the element to be inserted : "; |
| 235 | + std::cin >> s; |
| 236 | + |
| 237 | + if (data_structures::linked_list::isDigit(s)) { |
| 238 | + x = std::stoi(s); |
| 239 | + l.push_back(x); |
| 240 | + } else { |
| 241 | + std::cout << "Wrong Input!\n"; |
| 242 | + } |
| 243 | + break; |
| 244 | + case 2: |
| 245 | + std::cout << "\nEnter the element to be removed : "; |
| 246 | + std::cin >> s; |
| 247 | + if (data_structures::linked_list::isDigit(s)) { |
| 248 | + x = std::stoi(s); |
| 249 | + l.erase(x); |
| 250 | + } else { |
| 251 | + std::cout << "Wrong Input!\n"; |
| 252 | + } |
| 253 | + break; |
| 254 | + case 3: |
| 255 | + std::cout << "\nEnter the element to be searched : "; |
| 256 | + std::cin >> s; |
| 257 | + if (data_structures::linked_list::isDigit(s)) { |
| 258 | + x = std::stoi(s); |
| 259 | + std::shared_ptr<data_structures::linked_list::link> found = |
| 260 | + l.search(x); |
| 261 | + } else { |
| 262 | + std::cout << "Wrong Input!\n"; |
| 263 | + } |
| 264 | + break; |
| 265 | + case 4: |
| 266 | + l.display(); |
| 267 | + std::cout << "\n"; |
| 268 | + break; |
| 269 | + default: |
| 270 | + std::cout << "Invalid Input\n" << std::endl; |
| 271 | + break; |
130 | 272 | }
|
131 | 273 | } while (choice != 0);
|
132 |
| - |
133 | 274 | return 0;
|
134 | 275 | }
|
0 commit comments