chore(CPlusPlus): add linked list implementation (#463)
parent
61d7d0495e
commit
0661f09ae8
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue