Data Structures Made Simple

January 13, 2017 | Author: Raghav Agrawal | Category: N/A
Share Embed Donate


Short Description

covers data structures in concise,very good book for revising your concepts quickly...

Description

DATA STRUCTURES IN C MADE SIMPLE ( Second Edition)

KANNAN BALAKRISHNAN

SUMI HARIDAS

UMESH RAM

2011

Preface For many years the authors have felt the need of a simple book in data structures. This book is written especially for students in undergraduate classes. We have included basic concepts like stacks ,queues, linked lists, graphs, trees, searching and sorting algorithms in this book.Even though we do not claim any in depth treatment of the subject in this book, we hope that it will be surely useful for students who are studying data structures in C for the first time. Many programs are included in the book. Also a companion blog i s available at http://dssimple.wordpress.com .

We hope that this book will be of great use to students. Cochin 24.11.11 Authors

TABLE OF CONTENTS Chapter 1

Pointers 1.1 What Is A Pointer? 1.2 Pointer Declaration 1.3 Pointer Arithmetic 1.4 Accessing Variables Using Pointer 1.5 Address Operator (&) 1.6 Dereferencing Operator (*) 1.7 .One And Two Dimensional Arrays Using Pointers 1.8 Void Pointers 1.9 Pointers In Function Arguments 1.10 Recursion 1.11 Direct Recursion 1.12 Indirect Recursion 1.13 Array Of Pointers 1.14 Pointer To Pointer 1.15 Pointers To Strings 1.16 Pointers to functions Exercises Chapter 2 Structures and Unions 2.1 Definition 2.2 Accessing The Members Of A Structure 2.3 Array Of Structures 2.4 Structures Within Structure (Nested Structure) 2.5 Pointers To Structures 2.6 Structure In Functions 2.7 Unions 2.8 Difference and Similarity Between Structure And Union Exercises Chapter 3 Strings and String Operations 3.1 Strings 3.2 Strlen() 3.3 Strcmp() 3.4 Strcat() 3.5 Strcpy() 3.6 Pattern Matching 3.7 Dynamic Memory Allocation 3.8 Malloc() 3.9 Calloc()

3.10 Realloc 3.11 Freeing Memory Exercises Chapter 4 Sorting and Searching 4.1 Sorting 4.2 Different Sorting Techniques 4.3 Bubble sort Implementation 4.4 Selection sort 4.5 Selection sort implementation 4.6 Insertion sort 4,7 Insertion sort Implementation 4.8 Quick sort 4.9 Quick sort implementation 4.10 Merge Sort 4.11 Merge Sort Example 4.12 Bucket Sort 4.13 Heap Sort 4.14 Comparison Of Different Sorting Algorithms 4.15 Searching 4.16 Linear Search 4.17 Binary Search 4.18 Difference between Linear Search & Binary Search Exercises 5 Chapter 5 Stacks and Queues 5.1 Stack 5.2 Implementation of Stack using Arrays and pointers 5.3 Applications of Stacks 5.4 Queues 5.5 Circular Queue 5.6 Priority Queue 5.7 Dequeue 5.8 Input Restricted Dequeues 5.9 Output Restricted Dequeues 5.10 Applications of Queues Exercises Chapter 6 Linked lists 6.1 Linked List 6.2 Creation of Linked List 6.3 Inserting Node 6.4 Deletion of Nodes 6.5 Doubly Linked List 6.6 Operations on Doubly Linked List 6.7 Circular Linked List

6.8 Circular Doubly Linked List 6.9 Advantages/Disadvantages of Linked List Exercises Chapter 7 Trees 7.1 Tree 7.2 Root 7.3 Degree 7.4 Path length 7.5 Level 7.6 Forest 7.7 Labeled Trees 7.8 Binary Tree 7.9 Application Of Trees 7.10 Binary Tree Operations 7.11 Tree Traversal Methods 7.12 The Binary Search Tree 7.13 Threaded Binary Tree 7.14 Use Of Threaded Binary Tree Exercises Chapter 8 Graphs 8.1 Graphs 8.2 Definition 8.3 Adjacency List Representation 8.4 DFS And BFS 8.5 Depth First Search (DFS) 8.6 Breadth First Search (BFS) 8.7 Shortest Path 8.8 Weighted Graph 8.9 Dijkstra Algorithm Exercises

Chapter I Pointers in ‘C’

1.1. What is a pointer?

A pointer is a data type in C, which helps the programmer to access the memory locations of variables directly. A pointer contains a memory address which is the address of a variable. So, we define a pointer as follows Definition: A pointer is a variable that contains the address of another variable. We can have a pointer to any variable type. Using pointers complex data types can be declared and accessed efficiently.

1.2 Pointer Declaration: The syntax of declaring a pointer is type *pointerName. The type in the above declaration is called the base type of the pointer. Example: char *x declares x as a pointer to a character variable and int *y says that y is a pointer to an integer variable. When p is a pointer to a variable of integer type, we say that the base type of p is integer. Similarly when q is a pointer to a float variable, we say that the base type of q is float and so on.

After declaring a pointer variable one must assign values to it. That is the pointer must be assigned to some address. We can assign value to pointer in same way as any other variable data type.

int m, n;

int *p,*p1; P=&m;

Here the memory address of variable m is assigned to a pointer variable p. We are getting the address location of the variable, not the content of the pointer variable. •

• Sum =*p1; • Here the content of the pointer variable p1 is assigned to the variable sum. That is, value of p1 is the address of the integer variable sum.

Figure 1.1 A pointer to p1 to an integer variable sum

Program to display the address and contents of a pointer is given next.

Program1.1 #include void main() { int x;

int *p; // Here A pointer variable of base type integer is declared x=50; p=&x; //The pointer variable p is assigned the address of x printf(“Value of x is %d\n”,x); printf(“Value of the variable pointed by p is %d\n”,*p); printf(“Address of x is %d”,p); getch(); }

Output of the program Value of x is 50 Value of the variable pointed by p is 50 Address of x is 43522

1.2. Pointer Arithmetic

C language supports four arithmetic operations on pointers.

• • • •

Addition + Subtraction Incrementation ++ Decrementation - -

Here ++ increments the pointer to the address of the next memory location of the same type variable. The increment is done not by one but by the number of bytes required for the data type. That is if an integer is 4 bytes, ++ will increment an integer pointer by 4 and not by 1. Similarly for other operators. Also subtraction of a pointer p2 from a pointer p1 is defined only if p1 and p2 are pointers of the same base type.

Program illustrating pointer operations

Program1.2 #include void main() { int v,w ,*p,*q; v=80; w=90; p=&v; q=&w; printf("Value of p before increment operation=%u \n",p); p++; printf("Value of p after increment operation=%u\n",p); p--; printf("Value of p after decrement operation=%u\n",p); printf("Value of q=%u\n",q); printf("Value of p-q=%u\n",p-q); } Output of the program Value of p before increment operation=4276350260 Value of p after increment operation=4276350264 Value of p after decrement operation=4276350260 Value of q=4276350256 Value of p-q=1 1.3. Accessing Variables Using Pointer

In C you can see two type of unary operators for declaring a pointer type variable. They are listed below, • Address operator & • Dereferencing operator *

1.4. Address Operator(&)

Address operator can be represented by the combination of &(ampersand) with a pointer variable .Ampersand is a unary operator that returns memory address to its operand. For example: p =&x;

The pointer operator & returns the address of the variable following it. So we can say that ‘p’ is assigned the address of x.

1.5. Dereferencing Operator(*)

This can be represented the combination of *(asterisk) along with the variable. Asterisk should be before the variable name. It is also a unary operator that returns the value of the variable located at the address. For example: a=*p; Here a gets the value pointed by the pointer p. 1.5.1.1.1.1.

One and Two Dimensional Arrays Using Pointers

Pointers and arrays are equivalent in the following sense. The name of the array acts as a pointer to the first element of the array. Let us explain this with two examples: int a [50]; The above statement declares an array of integers of size 50, having elements a[0], a[1] ,.., a[49]. This is a one dimensional array. The variable a can be used as a pointer to the array. Variable a will point to the starting address of the array, that is a [0]. The elements of this array are a [0], a[1], …, a[49]. They are integer variables. Logically, these elements are stored in 50 consecutive memory locations. Therefore a pointer variable of base type integer can point to these elements. We know that int *ip declares ip as an integer type pointer. Now the two statements below, taken together are equivalent to the statement a[3] = 7 ip = &a[3]; *ip = 7; taken together are equivalent to the statement a[3] = 7

Also the statement ip = a is equivalent to saying that ip = &a[0]. Similarly, ip = a+5 is equivalent to saying that ip = &a[5].Generalizing ,We can say that the following is true.

If a is an array of size n, having elements a[0], …… a[n-1], of a particular data type, then a is a

pointer of that base type whose value is the address of a[0] and a+k points to a[k] for any k between 1 and n-1. A two dimensional array can be represented by a matrix.The next figure shows a two-dimensional array

Figure 1.2 A two dimensional array b[3][4] with three rows and four columns. The following statement declares a two-dimensional array. float b[3] [4].

C treats a two dimensional array as a one dimensional array of rows. Each row itself is again a one dimensional array.

Now b will point to b[0],which is the first row of the array. Also b+1, b+2, ….. Will be used to access to successive rows of the array b[ ][ ].Now b[0], is the first row .Since the first row is a one dimensional array,b[0] is a pointer to the first element b[0][0] of that array . Similarly b[1] is a pointer to the first element b[1][0] in the second row and so on. Also b[0]+j is a pointer to b[0][j]. Again *(b+i) is actually same as b[ i ] and *(*(b+i)+j) is the pointer representation of b[i][j].

Program to display the content of a one dimensional array using pointers: Program1.3

#include main() { int a[4]={1,2,3,4}; int *p1; int i,s,t1; s=4; printf("Display the contents of array\n"); for(i=0;irlink->llink=newnode; } } void deleteNode() //Delete element from the list { int val; printf("Enter the value to delete "); scanf("%d",&val); if(first->no==val) { first=first->rlink; first->llink=NULL; } else { temp=first; while(temp!=NULL&&temp->rlink->no!=val) temp=temp->rlink; if(temp==NULL) { printf("value not found in the list"); } temp->rlink=temp->rlink->rlink; temp->rlink->llink=temp; }

}

Output of the Program Doubly Linked list operation menu 1.Add 2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 1 Enter the value of the element 333 Doubly Linked list operation menu 1.Add 2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 1 Enter the value of the element 555 Doubly Linked list operation menu 1.Add 2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 2 Enter the element from left to right NULL->333->555->NULL Enter the element from l right to left NULL->555->333->NULL Doubly Linked list operation menu 1.Add

2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 3 Enter after the value:333 Enter the value to insert 444 Doubly Linked list operation menu 1.Add 2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 2 Enter the element from left to right NULL->333->444->555->NULL Enter the element from l right to left NULL->555->444->333->NULL Doubly Linked list operation menu 1.Add 2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 4 Enter the value to delete 444 Doubly Linked list operation menu 1.Add 2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 2 Enter the element from left to right

NULL->333->555->NULL Enter the element from l right to left NULL->555->333->NULL Doubly Linked list operation menu 1.Add 2.View 3.InsertNode 4.DeleteNode 5.Exit Enter u r choice 5

6.7 Circular Linked List

Circular linked list is similar to singly linked list. In the last node of the circular linked list we are storing the address of the first node. So we can directly go to the first node from last node

Advantage: Back traversal is possible in circular linked list. Disadvantage: In circular linked list there is a probability for an infinite loop.

Figure 6.5 circular linked list

Program for Circular Linked List:

Program 6.3 #include #include struct circularlink { int info; struct circularlink *next; }; struct circularlink *lastnode; void makeList(int); void deleteNode(int); void showList(); void insertFirst(int); void insertAfter(int,int); void main() { int option; int n,value,position,i; lastnode=NULL; do { printf("1.MakeList\n"); printf("2.Insert First\n"); printf("3.Insert After \n"); printf("4.Delete\n"); printf("5.ShowList\n"); printf("6.Quit\n"); printf("Enter your choice : "); scanf("%d",&option); switch(option) { case 1: printf("Enter the number of nodes "); scanf("%d",&n); for(i=0; i < n;i++) {

scanf("%d",&value); makeList(value); } break; case 2: printf("Enter the element : "); scanf("%d",&value); insertFirst(value); break; case 3: printf("Enter the element : "); scanf("%d",&value); printf("Enter the position after which this element is inserted : "); scanf("%d",&position); insertAfter(value,position); break; case 4: if(lastnode == NULL) { printf("List underflow\n"); continue; } printf("Enter the number for deletion : "); scanf("%d",&value); deleteNode(value); break; case 5: showList(); break;

}/*End of switch*/ }while(optioninfo = num; if(lastnode == NULL) { lastnode = tmp; tmp->next = lastnode; } else { tmp->next = lastnode->next; /*added at the end of list*/ lastnode->next = tmp; lastnode = tmp; } }/*End of makeList()*/ void insertFirst(int num) // Insert element at first position { struct circularlink *tmp; tmp = malloc(sizeof(struct circularlink)); tmp->info = num; tmp->next = lastnode->next; lastnode->next = tmp; }/*End of insertFirst()*/ void insertAfter(int num,int pos) // Insert element after a position { struct circularlink *tmp,*q; int i; q = lastnode->next; for(i=0; i < pos-1; i++) { q = q->next; if(q == lastnode->next) { printf("There are less than %d elements\n",pos);

return; } }/*End of for*/ tmp = malloc(sizeof(struct circularlink) ); tmp->next = q->next; tmp->info = num; q->next = tmp; if(q==lastnode) /*Element inserted at the end*/ lastnode=tmp; }/*End of insertAfter()*/ void deleteNode(int num) //Delete a particular node { struct circularlink *tmp,*q; if( lastnode->next == lastnode && lastnode->info == num) /*Only one element*/ { tmp = lastnode; lastnode = NULL; free(tmp); return; } q = lastnode->next; if(q->info == num) { tmp = q; lastnode->next = q->next; free(tmp); return; } while(q->next != lastnode) { if(q->next->info == num) { tmp = q->next; q->next = tmp->next; free(tmp); printf("%d deleted\n",num); return;

} q = q->next; }/*End of while*/ if(q->next->info == num) { tmp = q->next; q->next = lastnode->next; free(tmp); lastnode = q; return; } printf("Element %d not found\n",num); }/*End of deleteNode()*/ void showList() // Display elements { struct circularlink *q; if(lastnode == NULL) { printf("List is empty\n"); return; } q = lastnode->next; printf("List is :\n"); while(q != lastnode) { printf("%d ", q->info); q = q->next; } printf("%d\n",lastnode->info); }/*End of showList()*/

Output of the Program 1.MakeList 2.Insert First 3.Insert After 4.Delete

5.Show List 6.Quit Enter your choice : 1 Enter the number of nodes 4 11 33 44 55 1.MakeList 2.Insert First 3.Insert After 4.Delete 5.Show List 6.Quit Enter your choice : 3 Enter the element : 22 Enter the position after which this element is inserted : 1 1.MakeList 2. Insert First 3.Insert After 4.Delete 5.Show List 6.Quit Enter your choice : 5 List is : 11 22 33 44 55 1.MakeList 2.Insert First 3.Insert After 4.Delete 5. Show List 6.Quit Enter your choice : 4 Enter the number for deletion : 22 22 deleted 1.MakeList 2.Insert First 3.Insert After 4.Delete 5.Show List 6.Quit

Enter your choice : 5 List is : 11 33 44 55 1.MakeList 2.Insert First 3.Insert After 4.Delete 5.Show List 6.Quit Enter your choice : 6

6.8 Circular Doubly-linked List Circular doubly linked list is a doubly linked list in which the last node of the list has its next pointer pointing to the first node, and the previous pointer of the first node points to the last node. In a circular doubly linked list we can be traverse clockwise or anticlockwise manner. In this list all nodes are linked as shown in the below figure. The only difference between double linked list and circular double linked list is that here last node points to first node and first node points to last node .But in doubly linked list last node points to the NULL value.

Figure (6.5) circular doubly linked list A Sample program for Circular doubly linked list 6.4 Program #include #include struct cirdl {

int v; struct cirdl *r,*l; }; void addcirdl(); void printltor(); void printrtol(); void deletecird1(); struct cirdl *head,*pnode1,*t; int ch; void main() { head=(struct cirdl*)malloc(sizeof(struct cirdl)); head->r=head; head->l=head; pnode1=head; do { printf("\nCircular Doubly Linked list operation menu\n"); printf("1.Add\n2.PrintFromleft\n3.PrintFromRight\n4.Delete\n5.Exit"); printf("\nEnter u r choice\t"); scanf("%d",&ch); switch(ch) { case 1: addcirdl(); break; case 2: printltor (); break; case 3: printrtol(); break; case 4: deletecird1(); break;

} }while(chv); pnode1->l=head; pnode1->r=head; head->r=pnode1; head->l=pnode1; } else { t =(struct cirdl*)malloc(sizeof(struct cirdl)); printf("\nEnter the value to insert\t"); scanf("%d",&t->v); t->l=pnode1; pnode1->r=t; t->r=head; head->l=t; pnode1=pnode1->r; } }

void printltor() // Print elements from left to right { pnode1=head->r; while(pnode1!=head->l) { printf("%d->",pnode1->v); pnode1=pnode1->r;

} printf("%d",pnode1->v);

}

void deletecird1() // Delete a particular element { int v; printf("Enter the value to delete\t"); scanf("%d",&v); pnode1=head->r; if(v==pnode1->v) { head->r=pnode1->r; pnode1->r=head; } else { while(v!=pnode1->r->v&&pnode1!=head->l) pnode1=pnode1->r; pnode1->r=pnode1->r->r; pnode1->r->l=pnode1; } if(pnode1==head->l) { printf(" Sorry no such nodes exits"); } }

void printrtol() // Print Elements from eight to left { pnode1=head->l; while(pnode1!=head->r) { printf("%d->",pnode1->v);

pnode1=pnode1->l; } printf("%d",pnode1->v); }

Output of the Program

Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete 5.Exit Enter u r choice 1 Enter the value to insert 12 Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete 5.Exit Enter u r choice 1 Enter the value to insert 14 Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete 5.Exit Enter u r choice 1 Enter the value to insert 16 Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete

5.Exit Enter u r choice 2 12->14->16 Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete 5.Exit Enter u r choice 3 16->14->12 Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete 5.Exit Enter u r choice 4 Enter the value to delete 14 Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete 5.Exit Enter u r choice 2 12->16 Circular Doubly Linked list operation menu 1.Add 2.PrintFromleft 3.PrintFromRight 4.Delete 5.Exit Enter u r choice 5

6.9Advantages/Disadvantages of Linked Lists

Advantage

4. Linked lists use dynamic memory allocation. This makes efficient use of main memory. 5. Insertion and deletion of nodes arbitrary positions is easy. For insertion and deletion we need to just adjust the pointers. 6. We can move both directions using doubly linked list. 7. Linked lists do not require continuous memory blocks for allocation. 8. Linked list can grow and shrink according to user requiements

Disadvantage:

8. We have to mention the proper termination otherwise there is a probability for an infinite loop. 9. Doubly linked list take additional space to hold the address of the next node and address of the previous node. 10. Linked list allows only sequential access to elements access time is greater.

EXERCISE

1. What is a linked list? 2. Define circular linked list. List out its advantage and disadvantages. 3. Define doubly linked list. 4. List out the advantages and disadvantages of Linked list. 5. Write a program to search a particular value in a singly linked list. 6. List out the different steps for the creation of linked list. 7. Write a C program to implement doubly linked list. 8. Explain circular linked list. 9. Write a C program to implement Circular linked list. 10. Explain circular doubly linked list. 11. Write a C program to implement Circular doubly linked list. 12. Write a C program to reverse the linked list.

Chapter Vll TREES 7.1 Tree:

A tree is a finite set of nodes such that there is a special node called the ‘ROOT’ and remaining nodes are divided in to disjoined sets, where each of the set is a tree.

Figure 7.1 Tree

7.2 ROOT:

Root is a special node .It is the first node or top node in the tree. Every tree has only one root. In the above figure (7.1) ‘T’ is the root node.

7.3 Degree:

Degree of a node is the number of sub trees of the node, example, t1.t2, t3.Trees with ‘0’ degree is known as leaf nodes or terminal nodes.

Root of the sub tree of a node is called children of the node. If X is a node, Y is a child of X then X is called the parent of Y.Nodes having the same parents are called as Siblings. The maximum degree of nodes of a tree is called the degree of the tree. A path among two nodes X and Y of a tree is list of nodes starting from X and ending in Y with no node repeating.

7.4 Pathlengh

The number edges on a path are called the length of the path. it is one less than the number of nodes in the path.

7.5 Level

The level of the node is defined as follows: The level of the root is ‘1’, and then the level of the child is 1+ level of the parent. 7.6 Forest

A set of trees which are disjoint (Having no common nodes) is called as forest. For example: If we take the tree in the above example and delete the root node, we get a forest consisting of three disjoint trees.

Forest

A E F

B C D F G H

Figure 7.2 Forest

7.7 Labeled trees If a label (name) is assigned to each node of a tree, then it is called a labeled tree. A

B C D

F E

G H

Figure 7.3 Labeled tree

7.8 Binary tree A binary tree can be defined as tree in which every node has degree at most ‘two’. That is a tree is a binary tree if every node has ‘Zero’, ‘One’ or ’Two’ children. The two sub trees of a binary tree are called left sub tree and right sub tree.

Figure 7.4 Binary Tree

7.9 Application of trees

Trees have a variety of application. Some of them have listed below.

• Decision trees : when taking a decision we will have to consider several alternative and the decision is based on various condition this can be formulated as a tree If it rains or if it hot I will stay onside, else I will go out.

Figure 7.5 Decision Tree • Game trees: many games like tick tack toe, chess, drought, etc can be modeled by trees. Here the board positions are represented by nodes and edges represent moves. The root is the start position and finding a good move requires searching the tree. • Representing sets: In a set element can be represented by nodes and disjoint sub sets can be represented by sub trees. This representation makes operation like union very convenient.

• Oct trees and quad trees are used in computer graphics where a picture or a solid object is divided in to different parts, and each part is further divided, forming a tree representation of the picture or object. This representation saves much space and also is convenient for manipulating picture and objects. 7.10 Binary tree operations The common operations on a binary tree are: 10. Inserting a node

First we create a new node with the item as value. Then we search the binary tree to find a node to which the given item can be inserted as the child node. We get a new binary tree with the given node inserted. 2. Deleting a node In deletion there are three cases 2. The node to be deleted is a leaf node. In this case in the parent of the node, the pointer to the node is made Null and the node is freed. 2. The node to be deleted has only one child. In this case in the parent of the node, the pointer to the node is replaced by a pointer to the only child and the node is freed. 3. The node has both a left child and a right child. In this case the inorder successor of the node is deleted after storing its value in a temporary variable. Then the value of the node is changed to the stored value. Consider a tree having sub trees on both sides; here we are going to delete the node 25, for that we need to find out the inorder successor of the node 25.We get the Inorder successor by traversing the tree in inorder. Tree visited in sequence 20, 25,30,40,45,120,125,140,150. From sequence we found that 30 come after 25. After deletion tree looks like fig(7.5).

Figure (7.6) Figure (7.7)

3. Searching for a node.

It is examined whether a given node is in the tree or not.

Sample Program for implementing tree operations Program 7.1 #include #include #include struct BinaryTree { int n; struct BinaryTree *left; struct BinaryTree *right; }typedef BinaryTree; BinaryTree *root,*ptr,*prev,*bfor,*x,*y; int num; void main() { int ch; void createNewTree(); void displayTree(BinaryTree *); void searchTree(BinaryTree *); void insertTree(BinaryTree *); void deleteTree(BinaryTree *); do { printf("\n1.CREATENEW\n2.PRINT\n3.SEARCH\n4.INSERT\n5.DELETE\n6.EXIT"); printf("\nEnter your choice\t"); scanf("%d",&ch); switch(ch) { case 1 : { createNewTree(); break; } case 2 : { displayTree(root);

break; } case 3 : { searchTree(root); break; } case 4 : { insertTree(root); break; } case 5 : { deleteTree(root); break; } } }while(chleft=temp->right=NULL; root=temp; } else { ptr=prev=root; do

{ if(numn) { prev=ptr; ptr=ptr->left; } else if(num > ptr->n) { prev=ptr; ptr=ptr->right; } else { prev=NULL; break; } }while(ptr); if(prev) { temp=(BinaryTree*)malloc(sizeof(BinaryTree)); temp->n=num; temp->left=temp->right=NULL; if(temp->nn) prev->left=temp; if(temp->n > prev->n) prev->right=temp; } else printf("'%d' is already present..",num); } } } void displayTree(BinaryTree *ptr) // Displays the elements of the tree { if(!ptr) { printf("Tree empty..."); return; } void preorder(BinaryTree *ptr); printf("Root is '%d'",root->n); printf("\n Elements are .... "); preorder(root); }

void preorder(BinaryTree *ptr) { if(!ptr) return; printf("%2d ",ptr->n); preorder(ptr->left); preorder(ptr->right); return; }

void searchTree(BinaryTree *ptr) // Searches a particular element { if(!ptr) { if(ptr == root) { printf("Empty Tree"); return; } } printf("Enter the number to search : "); scanf("%d",&num); while(ptr) { if(ptr->n == num) { printf("Search Successfull..."); return; } else if(ptr->nright; else ptr=ptr->left; } printf("Search UnSuccessfull..."); } void insertTree(BinaryTree *ptr) // Insert an element {

BinaryTree *temp; if(!ptr) { printf("Tree is empty...First create & then insert... "); return; } ptr=prev=root; printf("Enter number to be inserted : "); scanf("%d",&num); do { if(numn) { prev=ptr; ptr=ptr->left; } else if(num > ptr->n) { prev=ptr; ptr=ptr->right; } else { prev=NULL; break; } }while(ptr); if(prev) { temp=(BinaryTree *)malloc(sizeof(BinaryTree )); temp->n=num; temp->left=temp->right=NULL; if(temp->n n) prev->left=temp; if(temp->n > prev->n) prev->right=temp; printf("'%d' is inserted...",num); } else printf("'%d' is already present...",num); return; }

void deleteTree(BinaryTree *ptr) // Deletes a particular element { if(!ptr) { if(ptr == root) { printf("Empty Tree"); return; } } printf("Enter the number to be deleted : "); scanf("%d",&num); prev=ptr; while(ptr) { if(ptr->n == num) { if(ptr==root) { x=ptr->right; root=x; while(x->left) x=x->left; x->left=ptr->left; free(ptr); printf("'%d' is deleted...",num); return; } else if(!(ptr->left) && !(ptr->right)) { if(prev->left == ptr) prev->left=NULL; else prev->right=NULL; free(ptr); printf("'%d' is deleted...",num); return; } else if(!(ptr->left)) { if(prev->left == ptr) { prev->left=ptr->right;

free(ptr); } else if(prev->right == ptr) { prev->right=ptr->right; free(ptr); } printf("'%d' is deleted...",num); return; } else if(!(ptr->right)) { if(prev->left == ptr) { prev->left=ptr->left; free(ptr); } else if(prev->right == ptr) { prev->right=ptr->left; free(ptr); } printf("'%d' is deleted...",num); return; } else { x=ptr->right; while(x->left) x=x->left; x->left=ptr->left; if(prev->left == ptr) prev->left=ptr->right; else if(prev->right == ptr) prev->right=ptr->right; free(ptr); printf("'%d' is deleted...",num); return; } } else if(ptr->n right; }

else { prev=ptr; ptr=ptr->left; } } printf("No Such Element Found.."); }

Output of the Program 1.CREATENEW 2.PRINT 3.SEARCH 4.INSERT 5.DELETE 6.EXIT Enter your choice 1 Enter the number of nodes 3 Enter the number 50 Enter the number 40 Enter the number 60 1.CREATENEW 2.PRINT 3.SEARCH 4.INSERT 5.DELETE 6.EXIT Enter your choice 2 Root is '50' Elements are .... 50 40 60 1.CREATENEW 2.PRINT 3.SEARCH 4.INSERT 5.DELETE 6.EXIT Enter your choice 4 Enter number to be inserted : 70 '70' is inserted... 1.CREATENEW 2.PRINT 3.SEARCH

4.INSERT 5.DELETE 6.EXIT Enter your choice 2 Root is '50' Elements are .... 50 40 60 70 1.CREATENEW 2.PRINT 3.SEARCH 4.INSERT 5.DELETE 6.EXIT Enter your choice 3 Enter the number to search : 70 Search Successfull... 1.CREATENEW 2.PRINT 3.SEARCH 4.INSERT 5.DELETE 6.EXIT Enter your choice 5 Enter the number to be deleted : 60 '60' is deleted... 1.CREATENEW 2.PRINT 3.SEARCH 4.INSERT 5.DELETE 6.EXIT Enter your choice 2 Root is '50' Elements are .... 50 40 70 1.CREATENEW 2.PRINT 3.SEARCH 4.INSERT 5.DELETE 6.EXIT Enter your choice 6

7.11 Tree traversal methods

By traversing a tree, we mean visiting the nodes of the tree in a systematic fashion. Based on the order in which we visit the nodes of a tree there are three tree traversal methods. The methods and the algorithm are given below: 3. Inorder traversal Traverse the left subtree in Inorder, visit the root and traverse the right sub tree in Inorder. 2. Pre order traversal Visit the root node, traverse the left sub tree in pre order, and traverse the right sub tree in pre order. 3. Post order traversal Traverse the left sub tree in post order, traverse the right sub tree in post order, and visit the root. We can explain the tree traversal with the following example.

Figure 7.8

Inorder traversal 20, 25, 30, 40, 45, 120, 125, 140,150 Pre-order traversal 120, 45, 25, 20, 40, 30, 140, 125, 150 Post-order traversal 20, 30, 40, 25, 45, 125, 150, 140, 120

Sample program for tree traversal Program 7.1 #include

struct treenode1 { struct treenode1 *left; char data; struct treenode1 *right;

}; typedef struct treenode1 tree; tree *root=NULL; void inserttree(); void inorder(tree*); void postorder(tree*); void preorder(tree*); int number,no; void main() { int i,option; printf("\n\tTree Operation-Menu\n"); printf("\n1.InsertNode\n2.Inorder\n3.Preorder\n4.Ppostorder\n5.Exit\n"); do { printf("\nEnter your operation\t"); scanf("%d",&option); switch(option) { case 1: inserttree(); break; case 2: printf("\nIn order traversal\n"); inorder(root); break; case 3: printf("\nPre order traversal\n"); preorder(root); break; case 4: printf("\nPost order traversal\n"); postorder(root); break; } }while(optiondata=number;

q->left=NULL; q->right=NULL; if(root==NULL) { root=q; return; } p=root; t=NULL; while(p!=NULL) { t=p; if(p->data>number) p=p->left; else p=p->right; } if(t->data>number) t->left=q; else t->right=q; } void inorder(tree *p) { if(p!=NULL) { inorder(p->left); printf("%d ",p->data); inorder(p->right); } } void preorder(tree *p) { if(p!=NULL) { printf("%d ",p->data); preorder(p->left); preorder(p->right); } } void postorder(tree *p) { if(p!=NULL) { postorder(p->left);

postorder(p->right); printf("%d ",p->data); } }

Output of the Program

Tree Operation-Menu 1.InsertNode 2.Inorder 3.Preorder 4.Ppostorder 5.Exit Enter your operation 1 Enter a number 50 Enter your operation 1 Enter a number 90 Enter your operation 1 Enter a number 80 Enter your operation 1 Enter a number 40 Enter your operation 1 Enter a number 30 Enter your operation 2 In order traversal 30 40 50 80 90 Enter your operation 3 Pre order traversal 50 40 30 90 80 Enter your operation 4 Post order traversal 30 40 80 90 50 Enter your operation 5

7.12 Binary Search tree

A binary search tree is a binary tree with the following properties. • The value of every node is unique. • The value of each node in the left sub tree is less than the value of any node in the right sub tree. • The value of any node in the left sub tree is less than the value of the root. • The value of any node in the right sub tree is greater than the value of the root. • Sub trees also satisfy the above properties. 7.13 Threaded binary tree A threaded binary tree is a binary tree in which every node without a right child has a pointer to its successor in an Inorder traversal. These pointers are called threads.

Figure 7.9 Threaded binary tree

7.14 Use of threaded binary trees Threaded binary tree can be used in tree traversal. If we use a threaded binary tree we can avoid recursion and the use of stacks. This saves a lot of memory and is much faster than recursive methods.

Exercises 3. What is tree? 4. Define sub tree. 5. Define root node and leaf node. 6. Define degree and level of a tree. 7. Explain the terms forest and labeled tree. 8. Explain the Application of trees. 9. What is a binary tree? Discuss the binary tree operation. 10. Discuss the different tree traversal methods. 11. What is binary search tree? 12. What is threaded binary tree? 11. Write a C program to implement the binary tree operations. 12. Write a c program to implement tree traversal. 13. Discuss the use of threaded binary tree.

Chapter Vlll GRAPH 8.1 Graph

Graph is also a nonlinear data structure which has application in many areas like networking, geographical information systems, traffic planning’s, project management and chemistry. 8.2 Definition

A graph G consists of a set of V of vertices and a set E of edges between the vertices. It can be represented as G= (V, E). Where V is a finate set of vertices and E is a set of pairs of vertices called edges.

Figure 8.1 Graph A graph can be either directed or undirected. In an undirected graph every edge is represented by unordered pair of vertices, whereas in a directed graph the edges are represented by ordered pairs of vertices. That is ,if u and v are vertices then in a directed graph an edge from u to v is represented as (u,v) and an edge from v to u is represented by (v,u).Also these are different edges. But in undirected graph (u,v) and (v,u) represent same edge between u and v.We use directed arrows to draw an edge in a directed graph and undirected line segments to draw edges in an undirected graph .see figures below

Figure 8.3 Figure 8.4

If( x, y) is an edge in a directed graph we say that xis adjacent to y. and y is adjacent from x.In the case of a undirected graph if (x,y ) is an edge, we say that x and y are adjacent. In the above example in figure (8.3), vertex a is adjacent to vertex c and vertex c is adjacent from a. In figure (8.4) vertices a and c are adjacent to each other. A subgraph of a graph G=(V,E) is a graph G’ =(V’,E’) such that the vertex set V’ of G’ is a subset of the vertex set V of G,and the set of edges E’of G’ is a subset of the set of edges E of G. A path from a vertex x to a vertex y in a graph G is a sequence of vertices. x =v0 ,v1,…,vr=y such that all vertices except possibly the first and last are distinct and (v0,v1), (v1,v2),…,(vr-1,vr) are edges in G.The number of edges in a path is called Length of a path. A cycle is a path with first and last matrix is same. An undirected graph is said to be connected if there is a path between every two distinct vertices. Other wise it called as disconnected. Representation of a Graph A graph can be represented in many ways, but the most used methods are given below: 1. Adjacency matrix representation 2. Adjacency list representation 8.3 Adjacency matrix representation Here a graph with n vertices {v1,v2,…,vn} is represented by an nxn matrix A. This matrix is called the adjacency matrix of the graph. In this matrix, the i,j th entry A[i,j] is 1 if there is an edge from vertex i to vertex j. Otherwise it is ‘0’.

Example:

Figure 8.5 Directed graph Figure 8.6 Adjacency Matrix

Figure 8.7 Figure 8.8

8.4 Adjacency list representation

In Adjacency list representation a linked list consisting of vertices adjacent to given vertex is attached to the vertex.

Figure 8.9 Figure 8.10 8.5 DFS and BFS

Given an undirected graph G and a vertex x, we may want to visit all vertices in G which are reachable from x in a systematic fashion. There are many methods to do this. Two of the most popular methods are listed below: 13. Depth First Search (DFS). 14. Breadth First Search (BFS). 8.6 Depth First Search (DFS).

In DFS we are going to visit the vertices in depth wise fashion. Starting from a vertex we are going to visit one of its neighbors, and then one of its neighbors and so on until the current vertex has no unvisited neighbors. Then we backtrack and continue visiting the next neighbor of the earlier vertex. Figure (8.13) shows the DFS spanning tree for the tree given in figure (8.11).

8.7 Breadth First Search (BFS)

In breadth first search we visit the vertices in a breadth wise fashion. Here first of all we start from a vertex, then visit all its neighbors, and then visit the neighbors of the neighbors and so on. Queue data

structure is used here. Figure (8.12) shows the BFS spanning tree for the tree given in figure (8.11).

Figure 8.11 Figure 8.12

Figure 8.13

In the figures above an undirected graph is visited starting from vertex 1. The DFS and BFS generate trees called the DFS tree and BFS tree respectively. These trees contain all the vertices of the graph G and are spanning trees.

BFS algorithm Input : A graph G and a source vertex s of G Output: A BFS Tree of the graph 14. Create a queue Q 15. Add s to Q 16. mark s 17. make s as the root of the tree T

5. while Q is not empty: 6. Remove a vertex v from Q 7. for each edge (v ,w) of G 8. if w is not marked: 9. mark w, 10. Make v the parent of w in T 11. add w to Q 12. end if 13. end while 14. Return T 15. STOP

Time complexity of BFS Since in the worst case BFS will have to consider all edges, the time complexity is O(m+n) on a graph with n vertices and m edges. Space complexity of BFS

Applications of BFS Breadth first search has many applications. Some of them are given below. 1 .Identifying connected components of a graph. BFS can be used to find all connected components in a graph. By starting from an arbitrary vertex BFS ends when all the vertices which are connected to that vertex is explored. Then start ing from a remaining vertex we get the next connected component.In this way we can find all the connected components. 2.Checking weather a graph is bipartite or not

A bipartite graph has the property that it has no cycles with an odd number of vertices. A bipartite graph can be recognosed by BFS.

3.Finding the shortest path from one vertex to all other vertices. A BFS starting from a single vertex gives a tree in which the path from the root to any other vertex is a shortest path.

DFS algorithm BFS algorithm Input : A graph G and a source vertex s of G Output: A DFS Tree of the graph

15. Create a Stack R 16. Push s to R 17. mark s 18. make s as the root of the tree T

5. while R is not empty: 6. pop a vertex v from R 7. for each edge (v ,w) of G 8. if w is not marked: 9. mark w, 10. Make v the parent of w in T 11. push w to R 12. end if 13. end while 14. Return T 15. STOP Time complexity Since in the worst case DFS will have to consider all edges of the graph and all vertices, the time complexity is O(m+n) on a graph with n vertices and m edges.

Applications DFS have a wide variety of applications.Some of them are given below. 15. .Finding the connected components of a graph. 16. In game playing 17. Solving mazes 18. Checking weather a given graph is planar (Weather it can be drawn on the pane without edges crossing) 5.Topological sorting. Notice That The only difference between DFS and BFS is that we use a Stack in DFS instead of a queue in BFS.

8.8 Shortest path and Dijkstra Algorithm

A shortest path from a vertex x to y in a graph G is a path from x to y having minimum number of edges .The length of any shortest path from x to y is the distance from x to y, and is denoted by d(x,y)..In an undirected graph d(x, y) and d(y, x) are same.

8.9 Weighed graph

A directed graph in which weights are assigned on edges is called a weighted graph.

Figure 8.14 A weighed graph may be used to represent many real life problems. For example a weighed graph may represent a road net work. Here vertices may represent cities; edges may represent roads between the cities. Weights indicating the cost of moving from one city to another city. A shortest path from a vertex x to a vertex y is a path from x to y B such that the sum of the weights of the edges in the path is minimum.

8.10 Dijkstra Algorithm

Dijkstra algorithm is used to find the shortest path and the costs of the paths from a given vertex x to all other vertices in a weighed graph G. Here we assume that all the costs are non-negative. Dijkstra’s Algorithm works by keeping a set of vertices whose distance from x is already determined. The algorithm proceeds by selecting a vertex v not in S, whose distance from all vertices of S is minimum. The time complexity of the algorithm is O (n ), where n is the number of vertices. The following program implements the algorithm 2

Program 8.1 #include

int distanceMatrix[20][20]; // To store the distance matrix int shortestPath[20]; // To store the shortest paths int findMax(int a, int b) // Find maximum of two numbers { if(a>b) return a; else return b; } void printPath(int sv,int n)// displays the shortest paths { int i; printf("From To ShortestPath\n\n"); for (i = 1; i
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF