It is debatable if Linked lists are needed in C++, especially because STL can do a very good job for the same functionality for which Linked Lists are required. Nevertheless sometimes it maybe convenient to know linked lists.
#include <iostream>
#include <string>
#include <istream>
#include <limits>
using namespace std;
class Node
{
public:
Node() : next(NULL) {}; Node(const string& s1) : info(s1), next(NULL) {};
string info;
Node* next;
};
Node* getNewNode()
{ istream& in(cin);
in.ignore( numeric_limits<std::streamsize>::max(), '\n' ); cout<<"\tEnter a string: ";
istreambuf_iterator<char> eos; istreambuf_iterator<char> iit (cin.rdbuf()); string s2;
while (iit!=eos && *iit!='\n') s2+=*iit++; Node* newNode = new Node(s2);
return newNode;
}
int main()
{
Node* head = NULL;
bool contFlag = true;
char c;
while(contFlag)
{
cout<<"\n\n";
cout<<"0. Quit"<<endl;
cout<<"1. Traverse and Print"<<endl;
cout<<"2. Insert node at the start"<<endl;
cout<<"3. Insert node at the end"<<endl;
cout<<"4. Insert after specified number of nodes"<<endl;
cout<<"5. Remove node from the start"<<endl;
cout<<"6. Remove node from the end"<<endl;
cout<<"7. Remove node from a specified number"<<endl;
cout<<"\nEnter your choice: ";
cin>>c;
switch(c)
{
case '0':
contFlag = false;
break;
case '1':
{
Node* tempNode = head;
int count = 0;
while(tempNode)
{
cout<<"\tItem "<<count<<" = "<<tempNode->info<<endl;
tempNode = tempNode->next;
count++;
}
}
break;
case '2':
{
Node* newNode = getNewNode();
newNode->next = head;
head = newNode;
}
break;
case '3':
{
Node* newNode = getNewNode();
Node* endNode = head;
if(endNode)
{
while(endNode->next)
endNode = endNode->next;
endNode->next = newNode;
}
else {
head = newNode;
}
}
break;
case '4':
{
Node* tempNode = head;
if(tempNode)
{
unsigned num;
cout<<"\tInsert after how many nodes? : ";
cin>>num;
Node* newNode = getNewNode();
unsigned count = 1; while(tempNode->next && (count < num))
{
tempNode = tempNode->next;
count++;
}
newNode->next = tempNode->next;
tempNode->next = newNode;
}
else
{
cout<<"\tNo nodes present yet"<<endl;
}
}
break;
case '5':
{
Node* firstNode = head;
if(firstNode)
{
head = firstNode->next;
delete firstNode;
}
}
break;
case '6':
{
Node* endNode = head;
if(endNode) {
Node* endEndNode = endNode->next;
if(endEndNode) {
while(endEndNode->next)
{
endNode = endEndNode;
endEndNode = endEndNode->next;
}
endNode->next = NULL;
delete endEndNode;
}
else {
head = NULL;
delete endNode;
}
}
}
break;
case '7':
{
Node* tempNode = head;
if(tempNode)
{
unsigned num;
cout<<"\tRemove after how many nodes? : ";
cin>>num;
unsigned count = 1; while(tempNode->next && (count < num))
{
tempNode = tempNode->next;
count++;
}
if(count == num && tempNode->next && tempNode->next->next)
{
Node* nodeToRemove = tempNode->next;
tempNode->next = nodeToRemove->next;
delete nodeToRemove;
}
}
else
{
cout<<"\tNo nodes present yet"<<endl;
}
}
break;
default:
cout<<"Incorrect selection."<<endl;
}
}
return 0;
}
The output is as follows:
You can try more combinations and if you have ideas for improvements please add in the comments section.
Few things to note:
1. This program is for reference and I have not accounted for memory leaks after pressing '0'.
2. For simplicity, getNewNode() is shown as a seperate function. In a real program, it may be better as a method of class Node
3. General Linked Lists use Struct's but in C++, Structs and Classes are
nearly the same so its better to use Class.
4. In C++ there is rarely a need to use Linked Lists. Its better to use the STL which already have vectors, stacks, lists, etc.
5. There should be check for memory allocation and try catch blocks that have been ignored for simplicity