Problem Question
To implement front back split on a Linked List.
Explanation of Problem
In this program we would be implementing a Linked List. Make sure you have a strong understanding of pointers to understand Linked Lists. A linked list is a basic data structure that is used in dynamic memory allocation applications. It comprises of 'nodes' which are linked together to form a sequence of nodes called Linked List. The linkage is done using memory addresses of adjacent nodes (next node in singly linked list, and both next & previous node in doubly linked list).In this program we use a struct to implement the node of our linked list. We will implement addition function to get some data in linked list before we can perform desired operations on it. Adding a new node to the list means, creating a new node structure, allocating memory to it and linking it to the list.
Consider we have a linked list. In this problem we want to split it into two lists. If the list has even number of nodes, then we split the list into two lists of equal length. If the list has odd number of nodes, then we split the list into two lists, the first one with one node more than the second one.
Code
#include<iostream>
/**@Title: LinkedList v1.9.cpp*
*@Programming Paradigm: Procedural*
*@Language: C++*
*@Compiler: GNU GCC*
*@IDE: Code::Blocks 13.12*
*@Author: Rogue Coder*
*@URL: http://letsplaycoding.blogspot.com/*
*@Date: 27-01-2015*
*/
struct node
{
  int data;
  node* next;
};
void addAtLast(node** rootNode);
void frontBackSplit(node** rootNodeFront, node** rootNodeBack);
void displayList(node* rootNode);
int main()
{
  int choice;
  node *startList = NULL, *backList = NULL;
  std::cout << "Welcome to LinkedList v1.9" << std::endl << "Made by Rogue Coder" << std::endl;
  do
  {
    std::cout << std::endl << "1 : Add a Node to the list" <<
         std::endl << "2 : Perform Front Back Split" <<
         std::endl << "3 : Display List" <<
         std::endl << "4 : Exit" <<
         std::endl << "Enter your choice : ";
    std::cin>>choice;
    switch(choice)
    {
    case 1:
        addAtLast(&startList);
        break;
    case 2:
        frontBackSplit(&startList, &backList);
        break;
    case 3:
        std::cout<<"List 1: ";
        displayList(startList);
        std::cout<<"List 2: ";
        displayList(backList);
        break;
    case 4:
      std::cout<<std::endl<<"Thank you for using LinkedList v1.9"<<std::endl<<"Made by Rogue Coder"
           <<std::endl<<"Press any key to exit"<<std::endl;
      break;
    default:
      std::cout<<"\a\aWrong Choice\a\a"<<std::endl;
      break;
    }
  }
  while(choice != 4);
  std::cin.get();
  return 0;
}
void addAtLast(node** rootNode)
{
   node* newNode = new node;
   std::cout<<std::endl<<"Enter data : ";
   std::cin>>newNode -> data;
   if(*rootNode == NULL)
   {
      *rootNode = newNode;
   }
   else
   {
       node* currentNode = *rootNode;
       while(currentNode->next != NULL)
       {
           currentNode = currentNode->next;
       }
       currentNode -> next = newNode;
   }
   newNode -> next = NULL;
}
void frontBackSplit(node** rootNodeFront, node** rootNodeBack)
{
    if (*rootNodeFront == NULL)
    {
        std::cout << "List Empty!";
        return;
    }
    int length = 0;
    node* currentNode = *rootNodeFront;
    while (currentNode)
    {
        length++;
        currentNode = currentNode -> next;
    }
    currentNode = *rootNodeFront;
    for(int newLength = 1; newLength < ((length / 2) + (length % 2)); newLength++)
    {
        currentNode = currentNode -> next;
    }
    *rootNodeBack = currentNode -> next;
    currentNode -> next = NULL;
    return;
}
void displayList(node* rootNode)
{
  node *currentNode = rootNode;
  if(currentNode == NULL)
  {
    std::cout<<std::endl<<"\aList Empty\a"<<std::endl;
  }
  else
  {
    std::cout<<std::endl;
    while(currentNode != NULL)
    {
      std::cout<<currentNode->data<<"->";
      currentNode=currentNode->next;
    }
    std::cout<<"End of List"<<std::endl;
  }
}
Explanation of Code
#include <iostream> -> The compiler calls the Preprocessor to include the IOSTREAM(Standard Input / Output Streams Library) header file into the program, thus letting the use of the Standard Input / Output Streams functions like std::cin and std::cout. As per C++11 specification, including <iostream> automatically includes also <ios>, <streambuf>, <istream>, <ostream> and <iosfwd>.
int main() -> The entry point of the program where the execution starts. This function has to be named main. As per the ANSI specification, the return type has to be int. Since the return type is specified as int in my program, I have to use a return statement at the end of my code. So I use return 0 since zero returned from a function, by convention, implies a correct execution of the program. The return values are used to debug the program.
std::cin (extern istream cin) -> Standard Input Stream, and object of class istream. It is generally used with the extraction operator (>>), though we can use member functions like get (cin.get()), read (cin.read()), etc. for the input. The use of extraction operator is much more popular due to the fact that it aids in getting formatted input.
std::cout (extern ostream cout) -> Standard Output Stream, and object of class ostream. It is generally used with the insertion operator (<<), though we can use member functions like write (cout.write()) for the output. The use of insertions operator is much more popular due to the fact that it aids in giving formatted output.
using namespace std; -> In modern IDEs, we have to explicitly write std::cout instead of cout to use the ostream cout object. Namespace std helps in easing off the pain of writing std:: again and again. Though make sure you are not trapped! The classes defined in std should not be redefined by you. So in case you want to define a class 'distance', you can't do so if you have used std namespace. Though you can define 'Distance' (capital D).
std::endl (ostream& endl (ostream& os)) -> This is a function which is used to insert a newline character and flush the stream. Because this function is a manipulator, it is designed to be used alone with no arguments in conjunction with the insertion (<<) operations on output streams.
{
  int data;
  node* next;
}; ->
node* startList; -> The global pointer ‘startList’ which we are going to use to point to the first node/root node/ start node of the linked list, we are going to implement in this program.
int choice; -> This variable 'choice' will be used for the user’s choice in the menu driven program.
{
   node* newNode = new node;
   std::cout<<std::endl<<"Enter data : ";
   std::cin>>newNode -> data;
   if(*rootNode == NULL)
   {
      *rootNode = newNode;
   }
   else
   {
       node* currentNode = *rootNode;
       while(currentNode->next != NULL)
       {
           currentNode = currentNode->next;
       }
       currentNode -> next = newNode;
   }
   newNode -> next = NULL;
} ->
{
    if (*rootNodeFront == NULL)
    {
        std::cout << "List Empty!";
        return;
    }
    int length = 0;
    node* currentNode = *rootNodeFront;
    while (currentNode)
    {
        length++;
        currentNode = currentNode -> next;
    }
    currentNode = *rootNodeFront;
    for(int newLength = 1; newLength < ((length / 2) + (length % 2)); newLength++)
    {
        currentNode = currentNode -> next;
    }
    *rootNodeBack = currentNode -> next;
    currentNode -> next = NULL;
    return;
} ->
We first check if the first list is empty. We do that by checking if the value at this reference pointer(the value is also a pointer, notice 2 asterisks, denoting pointer to pointer), points to start of first node.
If the list is not empty we go ahead with the split operation. We first get the length of the list by traversing through the list. We traverse the list starting the first node until we reach the last node, incrementing the variable storing length at every point.
Once we have the length, we need to split the list. But we need to find the point at which we want to split it. As explained, we need to split into two equal halves if the length is even, else first list would contain one extra node. We achieve this with the condition newLength < ((length / 2) + (length % 2)). If the length of original list was 4, we need to lists of length 2 each. If the length was 5, we need lists of length 3 and 2. If we have length of first list with us, we simply assign the node at this position as last(make it's next NULL), and the original next of this node becomes the first node of second list.
That's exactly waht we do in the statments *rootNodeBack = currentNode -> next; and currentNode -> next = NULL;.
We thus have 2 lists from the orginal list.
void displayList(node* rootNode)
{
  node *currentNode = rootNode;
  if(currentNode == NULL)
  {
    std::cout<<std::endl<<"\aList Empty\a"<<std::endl;
  }
  else
  {
    std::cout<<std::endl;
    while(currentNode != NULL)
    {
      std::cout<<currentNode->data<<"->";
      currentNode=currentNode->next;
    }
    std::cout<<"End of List"<<std::endl;
  }
} ->
do{..}while() -> The program loop which encapsulates the whole program. Until the user chooses to exit the program, the control loops within this.
exit(0); -> This function is used to exit the program with an error code as it's argument. '0' implies normal exit. Other values are used for debugging purposes.
std::cin.get() -> This statement is used to pause our program, until user presses a key. This function is not necessary in your program, I use it to see my outputs at a paused screen. If you use cmd to run your programs, you might not need this. If you use linux/unix you might not need this. Moreover, removing this line of code from this program, doesn't affect the functionality of the program.
No comments:
Post a Comment
Need help?