chore(CPlusPlus): add linked list implementation (#463)

pull/465/head
Adarsh Kishore 2021-09-14 19:15:07 +05:30 committed by GitHub
parent 61d7d0495e
commit 0661f09ae8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 134 additions and 24 deletions

View File

@ -1,19 +1,23 @@
#include <iostream> #include <iostream>
#include <exception>
template <typename T> using dType = int;
class Node {
public:
T data;
Node *next;
Node(T data)
: data(data) , next(nullptr) {};
Node(){}
};
template <typename T> template <typename T>
class SinglyLinkedList { class SinglyLinkedList {
private: private:
template <typename N>
class Node {
public:
T data;
Node *next;
Node(T data)
: data(data) , next(nullptr) {};
Node(){}
};
Node<T>* head; Node<T>* head;
Node<T>* tail; Node<T>* tail;
@ -21,6 +25,19 @@ class SinglyLinkedList {
SinglyLinkedList() SinglyLinkedList()
: head(nullptr),tail(nullptr){} : head(nullptr),tail(nullptr){}
~SinglyLinkedList(){
Node<T> *itr = this->head;
// iterate through list until itr reach to nullptr and print data
while(itr != nullptr) {
// creating temporary pointer to delete memory
Node<T> *temp_ptr = itr;
itr = itr->next;
delete temp_ptr;
}
// std::cout << "Destructor called\n";
}
void insertAtHead(T data) { void insertAtHead(T data) {
Node<T> *temp = new Node<T>(data); Node<T> *temp = new Node<T>(data);
@ -36,7 +53,7 @@ class SinglyLinkedList {
// change head point to new node // change head point to new node
this->head = temp; this->head = temp;
} }
void insertAtEnd(T data){ void insertAtEnd(T data){
Node<T> *newNode = new Node<T>(data); Node<T> *newNode = new Node<T>(data);
@ -57,10 +74,8 @@ class SinglyLinkedList {
T removeAtHead() { T removeAtHead() {
// if list is empty we can't remove node // if list is empty we can't remove node
if(this->head == nullptr) { if(this->head == nullptr)
std::cout<<"List is Empty"<<std::endl; throw std::runtime_error("List is Empty.");
exit(1);
}
// save data of node where head is pointed // save data of node where head is pointed
T data = this->head->data; T data = this->head->data;
@ -73,9 +88,59 @@ class SinglyLinkedList {
return data; return data;
} }
T removeAtEnd() {
// if list is empty we can't remove node
if (this->head == nullptr)
throw std::runtime_error("List is Empty.");
// if list is singleton it just becomes nullptr
if(this->head->next == nullptr) {
T data = this->tail->data;
Node<T>* temp_ptr = this->tail;
this->head = nullptr;
this->tail = nullptr;
delete temp_ptr;
return data;
}
// save data of node where tail is pointed
T data = this->tail->data;
// now iterate to one before last pointer
Node<T>* currNode = this->head;
Node<T>* nextNode = currNode->next;
while (nextNode && nextNode->next)
{
currNode = nextNode;
nextNode = nextNode->next;
}
// save temp pointer to free the memory
Node<T>* temp_ptr = this->tail;
currNode->next = nullptr;
this->tail = currNode;
delete temp_ptr;
return data;
}
T front() {
if(this->head == nullptr)
throw std::runtime_error("Empty List.");
return this->head->data;
}
T back() {
if(this->head == nullptr)
throw std::runtime_error("Empty List.");
return this->tail->data;
}
void printList() const { void printList() const {
if(this->head == nullptr) { if(this->head == nullptr) {
std::cout<<"List is Empty"<<std::endl; std::cout<<"List is Empty."<<std::endl;
} else { } else {
Node<T> *itr = this->head; Node<T> *itr = this->head;
// iterate through list until itr reach to nullptr and print data // iterate through list until itr reach to nullptr and print data
@ -88,13 +153,58 @@ class SinglyLinkedList {
} }
}; };
int main() { template <typename T>
SinglyLinkedList<int> l; void insert_element(SinglyLinkedList<T>& list, bool front) {
l.insertAtHead(1); T val {};
l.insertAtHead(2); std::cout << "Enter value to be inserted: ";
l.insertAtHead(3); std::cin >> val;
l.insertAtEnd(5);
l.removeAtHead(); if (front) list.insertAtHead(val);
l.printList(); else list.insertAtEnd(val);
return 0; }
void menu() {
SinglyLinkedList<dType> list {};
while (true) {
std::cout << "\nWhat would you like to do?\n";
std::cout << "1. Push back an element\n";
std::cout << "2. Push front an element\n";
std::cout << "3. Display the linked list\n";
std::cout << "4. Get front\n";
std::cout << "5. Get back\n";
std::cout << "6. Pop front\n";
std::cout << "7. Pop back\n";
std::cout << "8. Quit\n";
std::cout << "Enter corresponding number to your choice: ";
int ch {};
std::cin >> ch;
try {
switch (ch) {
case 1: insert_element(list, false);
break;
case 2: insert_element(list, true);
break;
case 3: list.printList();
break;
case 4: std::cout << list.front() << "\n";
break;
case 5: std::cout << list.back() << "\n";
break;
case 6: list.removeAtHead();
break;
case 7: list.removeAtEnd();
break;
case 8: return;
default: std::cout << "That's an invalid option. Please try again.\n";
}
}
catch (const std::runtime_error& re) {
std::cerr << re.what() << "\n";
}
}
}
int main() {
menu();
} }