Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Pointers Chapter Practice Section: Wadsfsaaawaaadsss

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 30

wadsfsaaawaaadsss

aaaaaLinked list is one of the most important data structures. We often face
situations, where the data is dynamic in nature and number of data can’t be
predicted or the number of data keeps changing during program execution. Linked
lists are very useful in this type of situations.

The implementation of a linked list in C++ is done using pointers. You can go
through the pointers chapter if you don’t have a strong grip over it. You can also
practice a good number of questions from practice section.

A linked list is made up of many nodes which are connected in nature. Every node
is mainly divided into two parts, one part holds the data and the other part is
connected to a different node. It is similar to the picture given below.

Here, each node contains a data member (the upper part of the picture) and link to
another node(lower part of the picture).

Notice that the last node doesn’t point to any other node and just stores NULL.

In C++, we achieve this functionality by using structures and pointers. Each


structure represents a node having some data and also a pointer to another structure
of the same kind. This pointer holds the address of the next node and creates the
link between two nodes. So, the structure is something like:

struct node
{
int data;
struct node *next;
};
The first data member of the structure (named node) is an integer to hold an integer
and the second data member is the pointer to a node (same structure). This means
that the second data member holds the address of the next node and in this way,
every node is connected as represented in the picture above.

The picture representing the above structure is given below.

And the picture representing the linked list is:

So, if we have access to the first node then we can access any node of the linked
list. For example, if ‘a’ is a node then a->next is the node next to the ‘a’ (the
pointer storing the address of the next node is named ‘next’).

One thing you should notice here is that we can easily access the next node but
there is no way of accessing the previous node and this is the limitation of singly
linked list.

Coding up a linked list

You are now clear with the concepts of a linked list. Let’s code it up. The first part
is to create a node (structure).

#include <iostream>

using namespace std;


struct node
{
int data;
node *next;
};

Now, we will create a class ‘linked_list’ which will contain all the functions and
data members required for a linked list. This class will use the structure ‘node’ for
the creation of the linked list.

The second and the most important part of a linked list is to always keep the track
of the first node because access to the first node means access to the entire list. So,
let’s call our first node as ‘ head’.

#include <iostream>

using namespace std;

struct node
{
int data;
node *next;
};

class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}
};

int main()
{
linked_list a;
return 0;
}

We have made two nodes – head and tail. We will store the first node in ‘head’ and
the last node in ‘tail’. The constructor of the linked list is making both ‘head ’ and ‘
tail’ NULL because we have not yet added any element to our linked list and thus
both are NULL.

Now, let’s create a function of adding a node to our linked list.

#include <iostream>

using namespace std;

struct node
{
int data;
node *next;
};

class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}
void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;

if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}
};

int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
return 0;
}

If you are not familiar with the ‘malloc’ function, then just read the dynamic
memory allocation chapter.

node *tmp=new node – We are allocating the space required for a node by
the new operator. Now, ‘tmp’ points to a node (or space allocated for the node).
tmp->data = n – We are giving a value to the ‘data’ of ‘tmp’ as passed to the
function.

tmp->next=NULL – We have given the value to ‘data’ in the previous line and a
value of the pointer ‘next’ (NULL) in this line and thus making our node ‘tmp’
complete.

The next part after the creation of a node is to join the nodes and create the linked
list. We will first check if the ‘head’ is NULL or not. If the ‘head’ is NULL, it
means that there is no linked list yet and our current node(tmp) will be the ‘head’.

if(head == NULL)
{
head = tmp;
tail = tmp;
}

If ‘head’ is NULL, our current node (tmp) is the first node of the linked list and this
it will be ‘head’ and ‘tail’ both (as it is also the last element right now).

If ‘head’ is not NULL, it means that we have a linked list and we just have to add
the node at the end of the linked list.

else
{
tail->next = tmp;
tail = tail->next;
}

The new node (tmp) will go after the ‘tail’ and then we are changing the tail
because the new node is the new ‘tail’.
Traversing

In this post, we will traverse through each node in the linked list with a loop and
also with recursion.

Traversal means “visiting” or examining each node of the list. We start from the
beginning and visit one node at a time until the end of the list (until the ‘next’ is
NULL). As discussed in the previous post, we need the first element (head) to
reach to any element of the list. So, we will do the traversal using the ‘head’ and
print its element and then proceed to the next element of the list.

Thus, the steps for the traversal of the linked list are:

1. Check if the element is not NULL.

2. If it is not, then print its ‘data’.

3. Change the element to the element stored in the ‘next’.

And the code representing the above steps is:

while(p != NULL)
{
printf("%d\n",p->data);
p = p->next;
}

Here, we are first checking if the node ‘p’ is not NULL then we are printing the
‘data’ stored in it. And then changing the p to the element stored in the ‘next’.

The overall code for linked traversal is:

#include <iostream>

using namespace std;

struct node
{
int data;
node *next;
};

class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}

void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;

if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}

void display()
{
node *tmp;
tmp = head;
while (tmp != NULL)
{
cout << tmp->data << endl;
tmp = tmp->next;
}
}
};

int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
a.display();
return 0;
}

Traversal using recursion

We can also traverse the linked list using recursion. The same logic is also used in
traversing using recursion with just a difference that we will use recursion instead
of the while loop. Let’s see it in action.

#include <iostream>

using namespace std;

struct node
{
int data;
node *next;
};

class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}

void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;

if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}
node* gethead()
{
return head;
}

void display(node *head)


{
if(head == NULL)
{
cout << "NULL" << endl;
}
else
{
cout << head->data << endl;
display(head->next);
}
}
};

int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
a.display(a.gethead());
return 0;
}

Here, we have declared a new function ‘gethead’ which is returning the head of the
linked list and then we are passing this head to the ‘display’ function.
In this code, we have first checked if the node is NULL or not. If it is NULL, then
we just printed “NULL” and when it is not then we printed the value of the ‘data’
and called the function ‘display’ again with the node next to it (‘head->next’).

Concatenating

Concatenating or joining two linked lists is not at all a difficult task. We just need
to follow some very simple steps and the steps to join two lists (say ‘a’ and ‘b’) are
as follows:

1. Traverse over the linked list ‘a’ until the element next to the node is not
NULL.

2. If the element next to the current element is NULL (a->next == NULL) then
change the element next to it to ‘b’ (a->next = b).

That’s it. Let’s code up these steps.

void concatenate(struct node *a,struct node *b)


{
if (a->next == NULL)
a->next = b;
else
concatenate(a->next,b);
}

Here, we are traversing over the article using recursion as explained in the article
“Linked list traversal using while loop and recursion”. We are firstly checking if
the next node (a->next) is NULL or not. If it is NULL, then we are just changing
its value from NULL to ‘b’ (a->next = b) and if it is not then we are calling the
‘concatenate’ function again with the next element to traverse over the list.

So, the whole code is:

#include <iostream>

using namespace std;


struct node
{
int data;
node *next;
};

class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}

void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;

if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}

node* gethead()
{
return head;
}

static void display(node *head)


{
if(head == NULL)
{
cout << "NULL" << endl;
}
else
{
cout << head->data << endl;
display(head->next);
}
}

static void concatenate(node *a,node *b)


{
if( a != NULL && b!= NULL )
{
if (a->next == NULL)
a->next = b;
else
concatenate(a->next,b);
}
else
{
cout << "Either a or b is NULL\n";
}
}
};

int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
linked_list b;
b.add_node(3);
b.add_node(4);
linked_list::concatenate(a.gethead(),b.gethead());
linked_list::display(a.gethead());
return 0;
}

The simpler way


We can use the above method even when we don't have the record of the 'tail'.
When we keep the record of the 'tail', we can simply do a->tail->next = b-
>head
Insertion

There are three different possibilities for inserting a node into a linked list. These
three possibilities are:

1. Insertion at the beginning of the list.

2. Insertion at the end of the list

3. Inserting a new node anywhere in between the list

In the first case, we make a new node and points its next to the head of the existing
list and then change the head to the newly added node. It is similar to picture given
below.

So, the steps to be followed are as follows:

1. Make a new node

2. Point the ‘next’ of the new node to the ‘head’ of the linked list.

3. Mark new node as ‘head’.

Thus, the code representing the above steps is:


void front(int n)
{
node *tmp = new node;
tmp -> data = n;
tmp -> next = head;
head = tmp;
}

The code is very simple to understand. We just made a new node first – node
*tmp = new node;

tmp->next=head – In this line, we have followed the second step which is to point
the ‘next’ of the new node to the head of the linked list.

And in the last line, we are making the new node ‘head’ as per the third step
– head = tmp;

The second case is the simplest one. We just add a new node at the end of the
existing list. It is shown in the picture given below:

So, the steps to add the end if a linked list are:

1. Make a new node


2. Point the last node of the linked list to the new node

We have already dealt with this in the first post with the ‘add_node’ function. I am
just mentioning the ‘add_node’ function here again.
void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;

if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}

You can read the explanation of the above code in the first post of linked list.

The third and the last case is a little bit complicated. To insert a node in between a
linked list, we need to first break the existing link and then create two new links. It
will be clear from the picture given below.
The steps for inserting a node after node ‘a’ (as shown in the picture) are:

1. Make a new node

2. Point the ‘next’ of the new node to the node ‘b’ (the node after which we
have to insert the new node). Till now, two nodes are pointing the same
node ‘b’, the node ‘a’ and the new node.

3. Point the ‘next’ of ‘a’ to the new node.

The code for the above steps is:


void after(node *a, int value)
{
node* p = new node;
p->data = value;
/*
if initial linked list is
_______ _______ _______
| 1 |____\ | 3 |____\ | 5 |____\ NULL
|_______| / |_______| / |_______| /
and new node's value is 10
then the next line will do something like
_______ _______ _______
| 1 |____\ | 3 |____\ | 5 |____\ NULL
|_______| / |_______| / |_______| /
/ \
|
|
___|___
| 10 |
|_______|
*/
p->next = a->next;
a->next = p;
/*
now the linked list will look like:
_______ _______ _______ _______
| 1 |____\| 10 |____\ | 3 |____\ | 5 |____\ NULL
|_______| /|_______| / |_______| / |_______| /
*/
}

node* p = new node; – We are creating a new node.


p->next = a->next – We are making the ‘next’ of the new node to point to the
node after which insertion is to be made. See the comments for better
understanding.

a->next = p – We are pointing the ‘next’ of ‘a’ to the new node.

The entire code is:

#include <iostream>

using namespace std;

struct node
{
int data;
node *next;
};

class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}

void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;
if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}

node* gethead()
{
return head;
}

static void display(node *head)


{
if(head == NULL)
{
cout << "NULL" << endl;
}
else
{
cout << head->data << endl;
display(head->next);
}
}

static void concatenate(node *a,node *b)


{
if( a != NULL && b!= NULL )
{
if (a->next == NULL)
a->next = b;
else
concatenate(a->next,b);
}
else
{
cout << "Either a or b is NULL\n";
}
}

void front(int n)
{
node *tmp = new node;
tmp -> data = n;
tmp -> next = head;
head = tmp;
}

void after(node *a, int value)


{
node* p = new node;
p->data = value;
p->next = a->next;
a->next = p;
}
};

int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
a.front(3);
linked_list::display(a.gethead());
return 0;
}
Deletion
We delete any node of a linked list by connecting the predecessor node of the node
to be deleted by the successor node of the same node. For example, if we have a
linked list a → b → c, then to delete the node ‘b’, we will connect ‘a’ to ‘c’ i.e., a
→ c. But this will make the node ‘b’ inaccessible and this type of inaccessible
nodes are called garbage and we need to clean this garbage. We do this cleaning by
the use of ‘delete’ operator. If you are not familiar with the ‘delete’ operator then
you can visit the ‘Dynamic memory’ chapter of the C++ course. So, the steps to be
followed for deletion of the node ‘B’ from the linked list A → B → C are as
follows:

1. Create a temporary pointer to the node ‘B’.

2. Connect node ‘A’ to ‘C’.

3. Delete the node ‘B’.

The code representing the above steps is:

void del (node *before_del)


{
node* temp;
temp = before_del->next;
before_del->next = temp->next;
delete temp;
}
Here, ‘before_node’ is the predecessor of the node to be deleted.
temp = before_del->next – We are making a temporary pointer to the node to
be deleted.
before_del->next = temp->next – Connecting the predecessor of the node to
be deleted with the successor of the node to be deleted.
delete temp – Making the ‘temp’ free.

And the overall code is:

#include <iostream>

using namespace std;

struct node
{
int data;
node *next;
};

class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}

void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;
if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}

node* gethead()
{
return head;
}

static void display(node *head)


{
if(head == NULL)
{
cout << "NULL" << endl;
}
else
{
cout << head->data << endl;
display(head->next);
}
}

static void concatenate(node *a,node *b)


{
if( a != NULL && b!= NULL )
{
if (a->next == NULL)
a->next = b;
else
concatenate(a->next,b);
}
else
{
cout << "Either a or b is NULL\n";
}
}

void front(int n)
{
node *tmp = new node;
tmp -> data = n;
tmp -> next = head;
head = tmp;
}

void after(node *a, int value)


{
node* p = new node;
p->data = value;
p->next = a->next;
a->next = p;
}

void del (node *before_del)


{
node* temp;
temp = before_del->next;
before_del->next = temp->next;
delete temp;
}
};

int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
a.front(3);
a.add_node(5);
a.add_node(15);
a.after(a.gethead()->next->next->next, 10);
a.del(a.gethead()->next);
linked_list::display(a.gethead());
return 0;
}

You might also like