Sei sulla pagina 1di 23

SK

UNIT-5

Unit 5 Linked Lists The main drawback of sequential representation is that fixed amount of storage remains allocated even when it is not used. Linear Linked list Each item in the list is called a node and contains two fields Information field - The information field holds the actual elements in the list Next address field- The next address field contains the address of the next node in the list The entire linked list is accessed from an external pointer called the List. It contains the address of the first element in the list. The next address field of the last node contains a special value known as null, which is not a valid address. Null indicates the end of the list. The list with no nodes on it is called the empty list or the null list. When the list is empty the external pointer first will contain the value null. Notations for use in algorithms (not in C programs) Node(p) refers to the node pointed to by that node. Info(p) refers to the information of that node. Next(p)-refers to the next address portion of that node.

Inserting nodes and removing nodes from the list. A list is a dynamic data structure. The number of nodes in the list can vary dynamically as the elements are inserted and removed from the list The first step to insert an element into the list is to get an empty node into which we can store the element to be inserted. Once an empty node is got we can fill the information part of it with integer and it can be connected to the list. Algorithm to add a node to the front of the list is shown below. P=getnode info(p)=item next(p)=first first=p;

// (p->info=item) // (p->next=first)

Algorithm to remove a node from the front of a list is shown below. The deleted node is available for reuse. p=first; first=next(p);

// first=p->next
1

SK

UNIT-5

x=info(p); freenode(p);

//x= p->info

Getnode operation The getnode operation removes a node from a pool of free nodes called as the available list and makes it available for use. The get node operation will return the first node from the available list. When the available list is empty and the getnode operation is called then the overflow occurs. Assuming that avail is an external pointer that has the address of the first node in the available list the getnode operation is implemented as follows. getnode() { If (avail=null) { Printf(overflow); Return(null); } P=avail; avail=next(avail) return p; } The getnode operation can be invoked as p=getnode and p will have the address of the free node Free node operation a node that is no longer used is returned to the pool by the free node operation. The node is added to the front of the available list. This node will be returned by the next get node operation The function free is used to free a node Freenode(p) { Next(p)=avail avail=p; } Available list: It is the finite pool of empty nodes existing initially. The available list is a linked list that behaves like a stack. The getnode operation removes the first node from the list and the freenode operation adds a node to the front of the list. In C we can represent a node as follows
2

SK

UNIT-5

Struct node { int info; struct node *next; }

Linked implementation of stacks.


The operation of adding an element to the front of a linked list is similar to that of pushing an element into the stack. A stack can be accessed only through the top element and a list can only be accessed through a pointer to its first element. The process of removing the first element from linked list is similar to popping from the stack. #include<stdio.h> #include<conio.h> struct node { int info; struct node *link; }; typedef struct node NODE; NODE* insert_front(int item,NODE * first) { NODE *temp,*cur; temp=(NODE *)malloc(sizeof(struct node)); if(temp==NULL) { printf("stack overflow\n"); return first; } temp->info=item; temp->link=first; count++; first=temp; return(first); }

NODE* del_front(NODE *first) { NODE *temp; if(first==NULL) { printf("Stack underflow\n"); return first; }
3

SK

UNIT-5

temp=first; printf("the deleted item is %d\n",temp->info); first=first->link; count--; return(first); }

void display(NODE *first) { NODE *temp; if(first==NULL) { printf("Stack empty\n"); return; } printf("Contents of stack are\n"); temp=first; while(temp!=NULL) { printf("%d\t",temp->info); temp=temp->link; } } void main() { int item,ch; NODE *first,*temp; first=NULL; clrscr(); for(;;) { printf("\nEnter the choice\n1:push\n2:pop\n3:display\n4:exit\n"); scanf("%d",&ch); switch(ch) { case 1:printf("Enter the item\n"); scanf("%d",&item); first=insert_front(item,first); break; case 2:first=del_front(first); break; case 3:display(first); break; default:exit(0);
4

SK

UNIT-5

} } }

Linked Implementation of queues


To implement a queue using a linked list we use two pointers the front and the rear. The front pointer will have the address of the first node and the rear pointer will have the address of the last node. A new node is always attached to the rear of the list and the node at the front will be deleted first. #include<stdio.h> #include<conio.h>

struct node { int info; struct node *link; }; typedef struct node *NODE; NODE insert_rear(int item,NODE rear) { NODE temp; temp=(NODE)malloc(sizeof(struct node)); if(temp==NULL) { printf("queue overflow\n"); return(first) } temp=getnode(); temp->info=item; temp->link=NULL; count++; if (rear==NULL) return temp; else { rear->link=temp; rear=temp; return rear; } } NODE del_front(NODE front) { NODE cur; if(front==NULL)
5

SK

UNIT-5

{ printf("Queue underflow\n"); return front; } cur=front; printf("item deleted=%d\n",cur->info); count--; front=front->link; free(cur); return front; }

void display(NODE front) { NODE temp; if(front==NULL) { printf("Queue is empty\n"); return; } printf("Contents of queue are\n"); temp=front; while(temp!=NULL) { printf("%d\t",temp->info); temp=temp->link; } } void main() { int item,ch; NODE front,rear; front=NULL; rear=NULL; clrscr(); for(;;) { printf("\nEnter the choice\n1:insert rear\n2:delete front\n3:display\n4:exit\n"); scanf("%d",&ch); switch(ch) { case 1:printf("Enter the item\n"); scanf("%d",&item); rear=insert_rear(item,rear); if(count==1) front=rear; break;
6

SK

UNIT-5

case 2:front=del_front(front); if (count==0) rear=NULL; break; case 3:display(front); break; default:exit(0); } } }

Linked list as a data structure Advantage of an array over list. An array implementation allows access to the nth item in a group using a single operation, whereas a list implementation requires n operation. In a linked list an item is accessed by traversing the list from the beginning. Advantage of a list over an array. In an array if we have to insert an element in the middle then we have to move the elements down to make room for the new element. Similarly if we have to delete an element from the middle we have to move the remaining elements up to fill up the gap. Whereas in a linked list insertion and deletion of elements in the middle can be done without affecting the position of other elements.

insafter(p,x) :The operation of inserting an item x into a list after a node pointed to by p q=getnode(); info(q)=x; next(q)=next(p); next(p)=q;

delafter(p,x): Denote the operation of deleting the node following the node pointed by p and assigning its contents to the variable x. q=next(p); x=info(q); next(p)=nex(q); freenode(q); Write a C routine(function) to insert an element X at the end of a list pointed by plist
7

SK

UNIT-5

Insert_end(struct node *plist , int x) { Struct node *new, *temp; new=(struct node *)malloc(sizeof (structnode)) new->info=x; new->link=NULL; if(plist==NULL) plist=new; temp= plist; while(temp->link!=NULL) temp=temp->link; temp->link=new; }

Write a function to delete the nodes whose information part contains 4 Delete_four(struct node *first) { Struct node *temp, *prev, *cur; If (first==NULL) { printf(list is empty); return(first); } If (first->info=4) temp=first First=first->link Free(temp); prev=NULL; temp=first; while (temp!=NULL) { If (temp->info==4) { cur=temp; prev->link=temp->link; temp=temp->link; } prev=temp; temp=temp->link; } } Write a C routine to delete the last node in the list.
8

SK

UNIT-5

Delete_last(struct node *first) { Struct node *temp,*prev; If (first==NULL) { Printf(list is empty); Return(first) } If(fist->link==NULL) { Temp=first; First=NULL; Free(temp); Return(first); } Prev=NULL; Temp=first; While(temp->link!=NULL) { Prev=temp; temp=temp->link; } Prev->link=NULL; Free(temp); return(first); }

Write a C routine to reverse a linked list Struct node* reverse(struct node *first) { Struct node *prev,*cur,*next; cur=first; prev=NULL; while(cur!=NULL) { next= cur->link cur->link=prev; prev=cur; cur=next; } return(prev); } Write a C routine to concatenate two list
9

SK

UNIT-5

Concat(Struct node * list1,stuct node *list2) { struct node* temp; if(list1==NULL) return(list2) if(list2==NULL) return(list1); temp=list1 while(temp->link!=NULL) temp=temp->link; temp->link=list2 return(list1) }

Write a C routine to delete a node at a specified position Struct node* delete_pos(struct node *first, int pos) { Struct node *temp *prev; int count=1; if(first==NULL) { Printf(list is empty); Return; } If(pos==1) { First=first->link return(first); } temp=first; prev=NULL; while(temp!=NULL && count!=pos) { Prev=temp; Temp=temp->link; Count++; } If (temp=NULL) Printf(invalid position); else { Prev->link=temp->link
10

SK

UNIT-5

free(temp); } } Write a function to delete the nodes whose information part is specified Struct node *Delete_four(struct node *first, int item) { Struct node *temp, *prev, *cur; If (first==NULL) { printf(list is empty); return(first); } If(first->info==item) { Temp=first First=first->link free(temp); return(first); }

prev=NULL; temp=first; while (temp!=NULL) { If (temp->info==item) { cur=temp; prev->link=temp->link; temp=temp->link; return(first); } prev=temp; temp=temp->link; } } Write a C routine to insert a node at a specified position Node * insert_pos(int item,node* first) { int count; node * temp,*cur,*prev; temp=(node*)malloc(sizeof(node)); if (temp==NULL) {
11

SK

UNIT-5

printf(allocation failed); return(first); } temp->info=item; temp->link=NULL; if(first==NULL&&pos==1) return temp; if(first==NULL) { printf("Invalid position\n"); return first; } if(pos==1) { temp->link=first; return temp; } prev=NULL; cur=first; count=1; while(cur!=NULL&&count!=pos) { prev=cur; cur=cur->link; count++; } if(count==pos) { prev->link=temp; temp->link=cur; return first; } printf("Invalid position\n"); return first; }

List implementation of priority queues


To implement a priority queue, when we are inserting elements into the queue we store it in ascending order so that the first element deleted is always the smallest element. For a descending priority queue the elements are stored in descending order so that the first element deleted is always the largest element.
12

SK

UNIT-5

To maintain an ordered list, for every insertion we have to compare all the elements. It is not possible to traverse a linked list from the last node. So we dont need the rear pointer here. Ordered list(struct node *first, int item) { Struct node *temp,*prev,*new; new=(struct node*)malloc(sizeof(struct node)); new->info=item; new->link=NULL; if(first==NULL) return(new); If (item<first->info) { New->link=first first=new return(first); } temp=first prev=NULL; (temp!=NULL && item>temp->info) { prev=temp; temp=temp->link; } prev->link=new new->link=temp return(first); } Write a C routine to concatenate two ordered list Struct node* concat(struct node *list1 ,struct node * list2) { Struct node *temp1,*temp2,*cur; prev1=NULL if(list1==NULL) return(list2) if(list2==NULL) return(list1); if(list1->info>list2->info) { temp=list2; list2=list2->link; temp->link=list1 list1=temp;
13

SK

UNIT-5

} temp1=list1; temp2=list2; while(temp1!=NULL & temp2!=NULL) { If(temp1->info>temp2->info) { cur=temp2; temp2=temp2->link; prev->link=cur; cur->link=temp1 } Else { prev=temp; temp=temp->link; } while(temp2!=NULL) { Prev->link=temp2 } Return(list1) } Header Nodes Sometimes an extra node is placed in the front of a list called the header node. This node does not represent an item in the list . The info part of the header node is often not used or sometimes it may contain some global information like the number of nodes etc. Implementing the Header Nodes When the data type of the header contents is the same as the contents of the node in a list then the header node can be implemented as just another node in the beginning of the list. For example Struct node { int info; struct node *link } Struct node *head; If the data type of the header node is different from the contents of the node in list then the header node can be declared as a separate variable. For example
14

SK

UNIT-5

Struct node { Char info; Struct node *link; }; Struct node h1; Here h1 can be used as the header node whose info part may contain information like the number of nodes and its link part will be pointing at the first node Struct headstr { Int length; Struct node *first; }; Struct headstr h1,h2; Here h1 and h2 is declared as variables of struct headstr its information part contains the length of the string and the first contains the address of the first node.

15

SK

UNIT-5

Lists in C Array implementation of Lists A list can be represented as an array of nodes. The elements are not ordered by the array.each element will contain within itself a pointer to its successor. For example a group of 500 nodes may be declared as an array of nodes as follow #define size 500 Struct node { int info; int link; }; Struct node n[size]; } In this method a pointer to a node is represented by an array index, therefore a pointer is an integer between 0 and size-1. The NULL pointer is represented by -1. Her the node is represented as node[p].information part is represented as node[p].info and the link part is represented as node[p].link.

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

25 20

3 18 11 -1

21 4

14 -1

16

SK

UNIT-5

23 24 In the above example list1 contains 8 which is the position of the first element The info is 3 and the position of the next element can be found from its link part that is 18 . The elements of list1 are 3 5 7 11. The elements of list2 is 21 25 14. Initially all the nodes are unused. No lists have been formed yet so all the nodes are in the available list.The global variable avail is used to point to the available list. List1 The available list can be initially organized as follows. avail=0; for(i=0;i<size-1;i++) node[i].link=i+1; node[size-1].link=-1
List2

all the 500 nodes are linked initially in their natural order, i.e. the ith node is linked to the (i+1)th node. The last node has the value -1 in the link part. Getnode When a node is needed in the linked list it is obtained from the availability list. The getnode operation removes a node from the available list and returns a pointer to it int getnode(void) { int p; if(avail==-1) { printf(overflow); return(avail) } p=avail; avail=node[avail].link; return(p) } Freenode When a node is no longer necessary it is returned to the available list. The function freenode accepts a pointer to a node and returns that node to the available list. Void freenode(int p) { Node[p].link=avail; Avail=p; }
17

SK

UNIT-5

The primitive operations for list are The insafter that accepts a pointer p to a node and an item x as parameters and then inserts x into a node following the node pointed to by p. The delafter(p,&x)-deleted the node following p and stores its conten in x; Void insafter(int p, int x) { int q; if (p==-1) return(invalid insertion) else { q=getnode(); node[q].info=x; node[q].link=node[p].link; node[p].link=q; } } Void delafter(int p, int *px) { int q; if (p=-1) printf(invalid insertions); else { Q=node[p].next; *px=node[q].info; node[p].next=node[q].next; freenode(q); }

Limitations of Array implementation The number of nodes that are needed cannot be predicted when the program is written. The number of nodes declared remains allocated. If the allocated nodes are not used it cannot be used for any other purpose. The time required to compute the address of node[p] is more as we have to add p to the base address. *p is given by the contents of p directly. Dangling pointer When a call to the function free(p) is made the storage for *p is freed and makes a subsequent reference to *p illegal. But actually the value of p is left unchanged even though it is illegal to access it, there is
18

SK

UNIT-5

no way to detect the illegality and such a pointer is called a dangling pointer. Therefore it is a good practice to explicitly set p to NULL after executing free(p).

Non integer lists It is not necessary that a node in a linked list should always represent an integer. For example To represent a collection of strings with a linked list we can declare the node as follows Struct node { Char info[50]; Struct node *next }; Here the info part can store a string with 49 characters.

For some applications it may be necessary for a node to store more than one item of information, for example to maintain the information of a student in a node we can have items like students name,roll no,marks etc. , such a node can be declared as follows. Struct stud { char name[30]; int roll_no; int m1,m2,m3; }; Separate C routines must be written to manipulate the lists. Non homogenous list Non homogeneous list are those that contains nodes of different types. To represent non homogeneous list a union can be used. For example
19

SK

UNIT-5

#define intgr 1 #define flt 2 #define strng 3 Struct node { int etype; //represents the data type of the element it can be intgr, flt or string depending on the value //stored in it Union { int ival; float fval; char *pval; } element; Struct node *next; }; Using struct node we can declare nodes whose items may be integer, float or string. Comparing the Dynamic and Array implementation of Lists The major disadvantage of dynamic implementation is that it requires more time to call the system to allocate and de-allocate memory. It is easier to manage a pre allocated availability list. The advantage is that the number of nodes are not allocated in advance. Another advantage is that a reference to *p does not involve the address computation that is necessary in computing the address of node[p]. To compute the address of node[p] the content of p must be added to the base address of the array node. Even if we have more than one list, the lists will not overflow until there is enough storage for the nodes Write a C program using dynamic variables to maintain the information of students using linked list. #include<stdio.h> #include<conio.h> struct student { char name[20]; int id; int sem; struct student *link; }; typedef struct student *STUD; STUD getnode() { STUD x; x=(STUD)malloc(sizeof(struct student));
20

SK

UNIT-5

if(x==NULL) { printf("Allocation failed\n"); exit(0); } return x; } STUD insert_front(char name[],int id,int sem,STUD first) { STUD temp; temp=getnode(); strcpy(temp->name,name); temp->id=id; temp->sem=sem; temp->link=NULL; temp->link=first; return temp; } STUD insert_rear(char name[],int id,int sem,STUD first) { STUD temp,cur; temp=getnode(); strcpy(temp->name,name); temp->id=id; temp->sem=sem; temp->link=NULL; if(first==NULL) return temp; cur=first; while(cur->link!=NULL) { cur=cur->link; } cur->link=temp; return first; } STUD delete_id(int id,STUD first) { STUD cur,prev; if(first==NULL) { printf("List is empty\n"); return first; } if(id==first->id) { cur=first; first=first->link;
21

SK

UNIT-5

free(cur); return first; } prev=NULL; cur=first; while(cur!=NULL&&id!=cur->id) { prev=cur; cur=cur->link; } if(id==cur->id) { prev->link=cur->link; free(cur); return first; } printf("Matching id not found\n"); return first; } void display(STUD first) { STUD temp; if(first==NULL) { printf("List is empty\n"); return; } printf("NAME ID SEM\n"); for(temp=first;temp!=NULL;temp=temp->link) { printf("%s\t%d\t%d\n",temp->name,temp->id,temp->sem); } } void main() { char name[20]; int ch,id,pos,sem; STUD first=NULL; clrscr(); for(;;) { printf("1:insert front\n2:insert rear\n3:delete_id\n6:display\n"); printf("Enter the choice\n"); scanf("%d",&ch); if(ch==1||ch==2||ch==3) { printf("Name\n");scanf("%s",name); printf("id\n");scanf("%d",&id);
22

SK

UNIT-5

printf("Sem\n");scanf("%d",&sem); } switch(ch) { case 1:first=insert_front(name,id,sem,first); break; case 2:first=insert_rear(name,id,sem,first); break; case 3:printf("Enter the id\n"); scanf("%d",&id); first=delete_id(id,first); break; case 4:display(first); break; default:exit(0); } } }

23

Potrebbero piacerti anche