0% found this document useful (0 votes)
32 views26 pages

Linked Lists: Representation

Download as pdf or txt
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 26

Linked Lists

*Sequential method of allocation is suitable for certain applications only. *Other applications where the sequential allocation method is unacceptable usually has the following characteristics. 1. unpredictable storage requirements:- The exact amount of data storage required by program in these areas often depends on the particular data being processed and consequently ,this requirement cannot be easily determined at the time the program is written. 2. Extensive manipulation of the stored data:- programs in these areas typically require that operations such as insertions and deletions be performed frequently on the data. The linked-allocation method of storage can be result in both the efficient use of computer storage and computer time. The use of pointers or links to refer to elements of a data structure (which is linearly ordered) implies that elements which are logically adjacent need not be physically adjacent in memory. This type of allocation is called Linked Allocation. A list has been defined to consist of an ordered set of elements which may vary in number. A simple way to represent a linear list is to expand each node to contain a link or pointer to the next node. This representation is called a one-way chain or singly linked linear list. Representation:

*List with array implementation requires O(n) time for insertion and deletion operations. *Linked list implementation of list requires O(1) time for insert/delete operations. Disadv: If the position of an element is given in the list it requires O(n) time to find in linked list. Single Linked List: *If we want to delete an element from a single linked list we need the address of its previous node. *We can only insert the new element after a given node. Insertion into single linked list:

Deletion from a linked list

A special node (dummy node) called as header node is used in the beginning of the list, which is used to maintain the information about the list like, no elements, type of the elements, owner of the list etc. Header node facilitates us to insert in the front of the list, as eliminating the special case of deleting first node.

Single Linked list :Implementation typedef struct node *nptr; struct node { int data; nptr next; }; *Creating the list nptr Createhead(void) { /*Creating the header node */ nptr L; L = (nptr)malloc (sizeof(struct node)); if (L = = NULL) printf(out of space); else L ->next = NULL return(L); }

Data

next

*Counting the no of nodes of the list int countnodes(nptr L) { /*Counting the no of nodes */ int k =0; nptr p; p = L -> next while(p! = NULL) { k++; p = p-> next; } return(k); } *printing the list void printlist(nptr L) { /*Printing the list */ nptr p; p = L ->next; while (p!=NULL) { printf(%d, p->data); p = p-> next; } } *Finding previous of the given element(delete) nptr findprev(nptr L, int x) {/*Finding the previous of given node */ nptr p; p = L; while ((p->next!=NULL) && (p->next ->data!= x) { p = p->next; } return(p); } The above function returns last node address when x does not exist.

X =25 *Finding the address of a node after which the new element is to be inserted. nptr findpos (nptr L ,int x) {/*Finding the position of the given node */ nptr p; p = L; while ((p->next!= NULL) &&(p->next ->data < x)) p = p-> next; return(p); } *Finding the address of the last node nptr findlast (nptr L) {/*Finding the address of last node */ nptr p; p = L; while(p->next != NULL) p = p->next; return(p); } *Inserting an element into an ordered list void ordinsert(nptr L,int x) {/*Inserting the element into a ordered list */ nptr temp p; p = findpos(L,x) temp = (nptr) malloc (sizeof(struct node)); if (temp = = NULL) printf(out of space); else { temp ->data = x; temp ->.next = p->next; p->next = temp; } }

*Inserting an element in the beginning of the list void beginsert (nptr L,int x) {/*Inserting the element at the beginning */ nptr temp; temp = (nptr) malloc (sizeof (struct node)); if(temp!= NULL) { temp ->data = x; temp -> next = L -> next; L-> next = temp; } else printf(out of space); } *Inserting an element at the end of the list void endinsert (nptr L,int x) { /*Inserting the element at the end */ nptr temp,last; last = findlast(L); temp = (nptr)malloc(sizeof(struct node)); if(temp = = =NULL) printf(out of space); else { temp ->data = x; temp ->next = last->next; last-> next = temp; } } *Creating an ordered list nptr Createlist(void) {/*Creating an ordered list*/ nptr L; int x; L = Createhead(); while(1) { printf(Enter the element 999 at the end); scanf(%d, &x); if(x = = - 999) break; else ordinsert(L,x); } return(L); }

*Deleting an element x from the given list void delete (nptr L,int x) {/*Deleting an element x from the given list */ nptr temp,prev; prev = findprev(L,x); if (prev-> next ! = NULL) { temp = prev -> next; prev->next = temp-> next; free(temp); } else printf(Element is not existing); }

*updating an element of a given SLL void update(nptr L,int x,int y) { nptr p; p = find(L,x); if(p = = NULL) printf (Element is not existing); else p->data = y; }

*Appending two lists

nptr append(nptr L1,nptr L2) { nptr last; if(L1 -> next = = NULL) return(L2); else if(L2 ->next = = NULL) return(L1) else { last = findlast(L1) last->next =L2->next; free(L2); return(L1) }

*splitting a given list into two lists based on the given value of x. nptr split(nptr L1,int x) { nptr p,L2; L2 =createhead(); p = find(L1,x); L2 -> next = p ->next; p->next = NULL; return(L2); }

*Merging two linked lists

nptr merge (nptr L1,nptr L2) { nptr L3, t1,t2,t3,temp; L3 =createhead(); t1 = L1 -> next; t2 = L2-> next; t3 = L3; while((t1! = NULL) && (t2! = NULL)) { temp = (nptr)malloc(sizeof(struct node)); t3->next = temp; t3 =temp; if( t1 ->data <= t2->data) { temp -> data = t1->data; t1 = t1->next; } else { temp->data = t2->data; t2 = t2->next; } }

while (t1!= NULL) { temp = (nptr) malloc (sizeof(struct node )); t3->next = temp; t3 =temp; temp->data = t1->data; t1 = t1->next; } while (t2!= NULL) { temp = (nptr)malloc(sizeof(struct node )); temp->data = t2->data; t2 =t2->next; t3->next = temp; t3 = temp; } t3->next = NULL; return (L3); } *Merging two lists without using any extra memory nptr merge (nptr L1,nptr L2) { nptr t1,t2,t3; t1 = L1->next; t2 =L2 -> next; while ((t1!= NULL) && (t2!=NULL) { if (t1->data <= t2->data) { t3 ->next = t1; t1 = t1->next; } else . { t3-> next = t2; t2 = t2 -> next; } t3 = t3->next; } if (t1= = NULL) t3->next = t2; else t3->next = t1; free(L2); return(L1); }

*Reversing a given SLL L P q r

void reverse(nptr L) { nptr p,q,r; p = NULL; q = L -> next; while (q!= NULL) { r = q ->next; q->next = p; p = q; q = r; } L->next = p; }

Polynomial Implementation: One variable polynomials can be implemented using arrays ex : 8x6 + 5x 4 + 3x 3 + 6x + 5 Each term of the polynomial consists of two values size: Coef. and xpower. In the array they can be represented using the value and position. 9 0 8 0 7 0 6 8 5 0 4 5 3 2 2 0 1 6 0 5

*Functions for polynomial Addition A function which can read the polynomial and return the highest degree (user enters c,e; 0, 0 at the end) int readpoly(int p []) { int hd.,c,e,i; for (i = 0;i< size;i++) p[i] = 0; while (1) { printf(Enter coef & xpower); scanf(%d %d ,&c ,&e); if(c= = 0) return(hd); else { p[e] = c; if(hd < e) hd = e; } } }

*printing a polynomial when the highest degree is given void printpoly(int p[], int hd) { int i; for(i = hd;i>0 ; i++) { if(p[i] ! = 0) { printf(+(%d) x ^ %d ,p [i] , i): } } printf(+(%d),p[i]); } *Adding two polynomials is adding two arrays *Disadvantage with array representation is wastage of memory. Polynomials can be implemented using an array of structures. ex: 10 x7 + 5x 5 + 3x 4 + 4x 0 1 2 10 5 3 7 5 4 Implementation struct term { int coef; int exp; }; typedef struct term sterm; *Function to read the polynomial & returns no of terms. int readpoly(sterm p[]) { int i; i = 0; do { printf(Enter the coef & xpower); scanf(%d %d, & p[i].coef , &p[i].xp); i++; } while(p[i-1].coef != 0); return(i-1); }

3 4 1

*printing a polynomial when the no of terms is known void printpoly(stem p[] ,int n) { int i; for( i = n-1 ; i>= 0;i--) { if(p[i].xp = = 0) break; else printf(+(%d) x^%d, p[i].coef,p[i] .xp); } if(i > = 0) printf( + (%d), p[i].coef ); }

Adding two polynomials

m-1 P1 10 8 6 5 3 2 4 1 2 0

n-1 P2 2 4 10 6 4 4 1 4 4 3 2 0

P3

int polynomialadd( sterm p1[ ] , sterm p2[ ], sterm p3[] ,int m,int n) { int i,j ,k; i = j= k =0 while( ( i< m) &&( j < n)) { if( p1[i] .xp = = p2[j].xp) { p3[k].coef = p1[i] .coef + p2[j].coef; p3[k].xp = p1[i] .xp; k++;i++;j++; } else if(p1[i].xp > p2[j].xp) { p3[k].coef = p1[i].coef; p3[k].xp = p1[i].xp; i++;k++; } else { p3[k].coef = p2[1].coef; p3[k].xp = p2[j].xp; j++; k++; } } while(i < m) { P3[k] = p2[j]; k++;j++; } while(j<n) { P3[k] = p2[j]; k++;j++; } return(k); }

Linked list Implementation of polynomials

typedef struct tnode * tnptr;; Struct tnode { int coef; int xp; tnptr next; };

coef

xp term

next

*Function to find the address of the term with the power e. tnptr findterm(tnptr p, int e) { tnptr t; t = p -> next; while(( t! = NULL) && ( t ->xp ! = e)) t = t->next; return(t); } *Function to find the address of a node after which the new term is to be inserted. tnptr findtpos(tnptr p ,int e) { tnptr t; t =p; while((t->next ! = NULL) &&(t->next ->xp >e)) t = t->next; return(t); }

*Function to insert a term into the polynomial void terminsert (tnptr p,int c,int e) { tnptr pos temp; pos = findterm(p,e); if (pos ! = NULL) pos ->coef + = c; else { pos = findtpos(p,e); temp = (tnptr)malloc(sizeof(struct tnode)); temp ->coef = c; temp ->xp = e; temp ->next = pos->next; pos->next = temp; } } *Multiplying two polynomials

tnptr polyprod(tnptr p1, tnptr p2) { tnptr t1,t2,p3; int c,e; p3 = createhead(); for( t1 = p1->next ;t1! = NULL;t1 = t1->next) for(t2 = p2->next;t2!= NULL;t2 = t2->next) { c = t1->coef * t2 ->coef; e = t1->xp + t2->xp; terminsert(p3,c,e); } return(p3); }

*Function to add two polynomials

tnptr polyadd(tnptr p1,tnptr p2) { tnptr t1, t2,t3,p3,temp; p3 = createhead(); t1 = p1->next; t2 = p2->next; t3 = p3; while((t1! = NULL) && (t2 != NULL) { temp = (tnptr)malloc (sizeof(struct tnode)); t3 ->next = temp; t3 = temp; if(t1 ->xp > t2 ->xp) { t3 ->coef = t1 ->coef; t3 -> xp = t1->xp; t1 = t1->next; } else if(t1->xp < t2->xp) { t3 ->coef = t2->coef; t3 ->xp = t2 ->xp; t2 = t2->next; }

else { t3 ->coef = t1->coef + t2->coef; t3 ->xp = t1->xp; t1 = t1->next; t2 = t2 ->next; } } while(t1!= NULL) { temp = (tnptr)malloc(sizeof(struct tnode)); temp -> coef = t1 ->coef; temp-> xp = t1->xp; t1 = t1->next; t3 ->next = temp; t3 = temp; } while (t2 != NULL) { temp =(tnptr) malloc (sizeof(struct tnode)); temp ->coef =t2->coef; temp-> xp = t2 ->xp; t2 = t2->next; t3 -> next = temp; t3 = temp ; } t3 -> next = NULL; return(p3); }

Circular Linked List(CLL)

Last node next field will give the address of the first node/header node *If the address of any node is given we can access all the nodes, which is not possible in SLL. *Function to reverse the elements/nodes of CLL. void reversecll(nptr L) { nptr p,q,r; p =L; q= L->next; while(q! = L) { r = q->next; q->next = p; p->q; q-> r; } L->next = p; }

*Function to concatenate two CLLs

nptr concat(nptr L1,nptr L2) { nptr p; p = L1->next->next; L1->next ->next = L2->next->next; L2->next ->next = p; free(L1); return(L2); }

Double Linked List Each node gives the addresses of its previous node and its next node-two links are maintained. If the address of a node is given we can delete it which is not the case with SLL. If the address of a node is given we can insert a new element before it or after it. If one link is lost, we can restore it using the other link. We can traverse list in both the directions.

prev

dnode data

next

typedef struct dnode* dnptr; struct dnode { dnptr prev; int data; dnptr next; };

Representation :

*Function to delete a given element from DLL void delete(dnptr H, int x) { dnptr p; p=find(H,x); if (p = = NULL) printf(Element is not existing); else { if(H->prev = = H->next) { H->prev = H->next = NULL; } else if(p = = H->prev) { H->prev = p->next; p->next ->prev = NULL; } else if(p = = H->next) { H->next = p->prev; p->prev ->next = NULL; } else { p->next ->prev = p->prev; p->prev ->next = p->next; } free(p); } } * Function to insert an element into DLL before given node p. void dllinsertbp(dnptr H,dnptr p,int x) { dnptr temp; temp = (dnptr)malloc(sizeof(struct dnode)); temp ->data = x; if(p->NULL) { temp ->prev = temp ->next = NULL; H->prev = H->next = temp; } else

if (p = =H->prev) { temp ->next = p; temp->prev = NULL; p->next = temp; H->prev = temp; } else { temp ->next = p; temp ->prev = p->prev; p->prev ->next = temp; p->prev = temp; } }

Radix Sort:- Function m is the no of digits. void radixsort(nptr L,int m) { nptr B[10],T[10],p,q,prev; int i,j ,k d; for(i =0; i<=m;i++) { /* intializing the buckets*/ for(j=0;j<= 9;j++) B[j ] = T[j ] = NULL; p = L->next; /* Distributing the elements into buckets based on a digit*/ while(p!=NULL) { q = p->next d= p->data/pow(10,j)%10; if(T[d] = = NULL) T[d] = B[d] = p; else { T[d] ->next = p; T[d] =p; } T[d] ->next = NULL; p = q; } /* Combining all the buckets.*/ k = 0; while(B[k ] = = NULL) k++; L->next = B[k] ; for(j = k+1; j<= 9; j++) { prev = T[j-1]; if(B[j]!=NULL) prev -> next = B[j]; else T[j] = prev; } } } Time Complexity : T(n) = O(m * n).

You might also like