Data Structures UVK

285
08/20/08 Copyright © Vikas karanth,2007 All rights reserved. 1 Data Structures Prepared By: Vikas karanth Last modified: August 08 2008

description

data structures

Transcript of Data Structures UVK

Page 1: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

1

Data Structures

Prepared By: Vikas karanth

Last modified: August 08 2008

Page 2: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

2

Stacks

Page 3: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

3

Objectives

In this session, you will learnt to: Define a stack Describe the operations on a stack Implement a stack as a special case of a

linked list Describe applications of stacks

Page 4: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

4

What is a Stack?

A stack is a data structure in which insertions and deletions can only be done at the top.

A common example of a stack, which permits the selection of only its end elements, is a stack of books.

A person desiring a book can pick up only the book at the top, and if one wants to place a plate on the pile of plates, one has to place it on the top.

Page 5: Data Structures UVK

What is a Stack?

You would have noticed that whenever a book is placed on top of the stack, the top of the stack moves upward to correspond to the new element (the stack grows).

And, whenever a book is picked, or removed from the top of the stack, the top of the stack moves downward to correspond to the new highest element (the stack shrinks).

Page 6: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

6

What is a Stack?

(c)

top

2

4

6

8

10

2

4

6

8

10

12

2

4

6

8

10

12

14

(a) (b)

toptop

Page 7: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

7

Characteristics of a Stack

When you add an element to the stack, you say that you push it on the stack,

and if you delete an element from a stack, you say that you pop it from the stack.

Since the last item pushed into the stack is always the first item to be popped from the stack, a stack is also called as a Last In, First Out or a LIFO structure.

Page 8: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

8

Characteristics of a Stack Unlike an array that is static in size , stack grows dynamically at run time.

An ideal implementation of a stack would be

Using dynamic array,

linked list in which insertions and deletions can only be done at the top of the list.

Page 9: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

9

Operations on Stacks Some of the typical operations performed on stacks are:

create (s) – to create s as an empty stack

push (s, i) – to insert the element i on top of the stacks

pop (s) – to remove the top element of the stack and to return the removed element.

top (s) – to return the top element of stack(s)

empty(s) – to check whether the stack is empty or not. It returns true if the stack is empty,

Page 10: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

10

Array Implementation of Stacks The implementation of stack using array can be explained as Declaration of stack data type:

# define MAX 1000 # define TRUE 1 # define FALSE 0 typedef int StackElement;

struct stack_info{ int top; StackElement data[MAX]; };

typedef struct stack_info Stack; Stack st;

Page 11: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

11

Function prototypes:

void create(Stack *);

int IsStackEmpty(Stack *);

int IsStackFull(Stack *);

StackElement pop(Stack *);

void push(Stack *, StackElement);

int menu(void);

Page 12: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

12

main(){

StackElement data;system("clear");create(&st);

do{switch(menu()){

case 1: printf("enter elemenmt to be pushed\n");scanf("%d",&data);push(&st,data);break;

case 2: printf("poped element is :%d\n",pop(&st));break;

default: printf("error in chioce");}printf("Do u want to continiue\n");

} while(getchar() != 'n' );}

Page 13: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

13

void create(Stack *s){

s -> top = -1;}

int IsStackEmpty(Stack *s){

if(s -> top == -1)return TRUE;

elsereturn FALSE;

}

int IsStackFull(Stack *s){

if(s -> top == MAX -1)return TRUE;

elsereturn FALSE;

}

Page 14: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

14

StackElement pop(Stack *s){

int t;StackElement element;if(IsStackEmpty(s))

printf("Stack empty\n");else{

t = s ->top ;element = s ->data[t];s -> top --;

}return element;

}

Page 15: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

15

void push(Stack *s, StackElement d){

if(IsStackFull(s))printf("Stack is full\n");

else{++(s -> top);s ->data[s ->top] = d;

}}

int menu(void){

int choice;printf("1 to push\n");printf("2 to pop\n");scanf("%d",&choice);return choice;

}

Page 16: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

16

Applications of stack

Infix , Prefix and postfix experections:

when we think of adding two numbers, normally we think of applying '+' operator to the operands. We can apply operators in different ways like:

A + B : Infix +AB : Prefix AB+ : Postfix

The prefixes "pre-", "post-" and "in-" refer to the relative position of the operator with respect to the two operands.

In prefix notation the operator precedes the two operands, in postfix notation the operator follows the two operands and in infix notation the operator is in between the two operands.

Page 17: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

17

Converting infix to postfix:

A+B*C Step 1: (A+(B*C)) Step 2: A+(BC*) Step 3: ABC*+.

In this conversion process are that operations with highest precedence are converted first, then after a portion of expression has been converted to postfix.

Page 18: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

18

Converting infix to postfix:

A+B*C

Step 1: (A+(B*C)) Step 2: (A+*BC) Step 3: +A*BC

The precedence rules for converting an expression from infix to prefix are identical. The only change is the operator is placed before the operands.

Page 19: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

19

Examples

Prefix Infix Postfix

+AB A + B AB+

-+ABC A + B – C AB+C-

*+AB-CD (A+B) * (C – D) AB+CD -*

+-*$ABCD//EF+GH A$B*C-D+E/F/(G+H) AB$C*D-EF/GH+/+

$-*+ABC-DE+FG ((A+B)*C-(D-E))$(F+G) AB+C*DE—FG+$

Page 20: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

20

Algorithm to convert an infix expression to postfix expression Step 1:Access infix expression in a string S

Step 2: i being position, let it be equal to 0.

Step 3:Initially top=-1, indicating stack is empty.

Step 4:If S[i] is equal to operand, print it, go to step 8.

Step 5:If S[i] is equal to opening bracket, push it, go to step 8.

Page 21: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

21

Step 6: If S[i] is equal to operator, then Step 6a: if stack empty push the operator got to step 8 else Pop the operator from the stack, say, p,

If priority of P is less than priority of S[i], then push p, push s[i] go to step 8.

Else print p, go to step 6a.

Step 7: If S[i] is equal to operator, then Step 7a: pop the operator from the stack, say, p,

If p is not equal to opening bracket, then print p, step 7a. Else go to to step 8.

Page 22: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

22

Step 8: Increment i.

Step 9: If S[i] is not equal to ‘\0’, then go to step 4 else step 10

Step 10: pop the operator from the stack, say, p

Step 11: Print p.

Step 12: If stack is not empty, then go to step 10.

Step 13: Stop.

Page 23: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

23

Non recursive algorithm for converting Infix to Prefix Step 1: Get the prefix expression, say S.

Step 2: Set the position counter, i to 0.

Step 3: Initially top1 and top2 are -1, indicating that the stacks are empty.

Step 4: If S[i] is equal to opening bracket, push it in stack1, go to step 8.

Step 5: If S[i] is equal to operand it in stack2, go to step 8.

Page 24: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

24

Step 6:

If S[i] is equal to operator, stack1 is empty or stack top elements has less priority as compared to S[i], go to step 8

Else p = pop the operator from stack1. o1 = pop the operator from stack1. o2 = pop the operand from stack2. From the Prefix expression p, o1, o2, Push in stack2 and go to step 6.

Page 25: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

25

Step 7: If S[i] = opening bracket, then

Step 7a: p = pop the operator from stack1If p is not equal to closing bracket, thenO1 = pop the operand from stack2.O2 = pop the operand from stack2.From the prefix expression p, o1, o2,Push in stack2 and go to step 7a Else go to step 8.

Step 8: Increment i.

Page 26: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

26

Step 9: If S[i] is not equal to ‘\0’, then go to step 4.

Step 10: Every time pop one operator from stack1, pop2 operands from stack2, from the prefix expression p, o1, o2, push in stack2 and repeat till stack1 becomes empty.

Step 11: Pop operand from stack2 and print it as prefix expression

Step 12:Stop

Page 27: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

27

Program to Evaluate a Postfix Expression

#include<stdio.h>#include<ctype.h>#include<math.h>#include<stdlib.h>#define MAX 20

typedef struct stack{

int top; float items[MAX];}S;

Page 28: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

28

/* PROTOTYPE DECLARATIONS */

void push(S *,float);float pop(S *);float eval(char []);float oper(char,float,float);main(){

char expr[MAX]; int pos=0; printf("Enter the postfix expression\n"); while((expr[pos++]=getchar())!='\n'); expr[--pos]='\0'; printf("The original postfix expression is %s",expr); printf("\n %f \n",eval(expr));

}

Page 29: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

29

float eval(char expr []){ char c; int pos; float opnd1,opnd2,value; S opndstack; opndstack.top=-1; pos=0; c=expr[pos]; while(c!='\0') { if(isdigit(c)) push(&opndstack,(float)(c-'0')); else {

opnd1=pop(&opndstack); opnd2=pop(&opndstack);

value=oper(c,opnd1,opnd2); push(&opndstack,value);

} c=expr[pos++]; } return (pop(&opndstack));}

Page 30: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

30

float oper(char symb,float op1,float op2) {

switch(symb) { case'+' :return(op1+op2); case'-' :return(op1-op2); case'*' :return(op1*op2); case'/' :return(op1/op2); case'$' :return(pow(op1,op2)); default :printf("Invalid option\n"); } return -1; }

void push(S *p,float x){

if(p->top==MAX-1) printf("Sorry! the stack is full\n");

else { ++p->top; p->items[p->top]=x;

}}

Page 31: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

31

float pop(S *p){

int num; if(p->top==-1) {

printf("The stack is empty\n"); return -1;

} else {

num=p->items[p->top]; --(p->top); return(num);

}}

Page 32: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

32

Linked Implementation of Stacks

An ideal implementation for a stack is a linked list that can dynamically grow and shrink at runtime.

Since you are going to employ a variation of a linked list that functions as a stack, you need to employ an additional pointer (top) that always points to the first node in the stack, or the top of the stack.

It is using top that a node will either be inserted at the beginning or top of the stack (push a node into the stack), or deleted from the top of the stack (popping a node at the top or beginning of the stack).

Page 33: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

33

Code Implementing for a Stack The push( ) and the pop( ) operations on a stack are

analogous to insert-first-node and delete-first-node operations on a linked list that functions as a stack.

struct stack {

int info; struct stack *next; };

/* pointer declaration to point to the top of the stack */ struct stack *top;

Page 34: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

34

Code Implementing for a Stack

main( ){

top = NULL;char menu = ‘0 ‘;while (menu != ‘3’) {

printf( “Add Nodes :\n”);printf( “Delete Nodes :\n”);

printf( “Exit :\n”); menu = getchar( );

switch (menu) {case ‘1’ : push( );

break;

Page 35: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

35

Code Implementing for a Stack

case ‘2’ : pop( )

break;

case ‘3’: exit( );

break;

} /* end of switch */

} /* end of main( ) */

Page 36: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

36

Implementing push( )

push( ){ struct stack * new; char ch = ‘y’; while (ch = = ‘y’) { new = getnode( )

/* checking for an empty stack */ if ( top = = null) { top = new; }

Page 37: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

37

Implementing push( )

else { new->next = top; top = new; } printf("%s","Want to add more nodes\n"); scanf( "%c", &ch ); fflush( stdin ); } /* end of while */

} /* end of push( )

Page 38: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

38

Creating a Node on a Stack

struct stack * makenode() { struct stack *new; new=(struct stack *)

malloc(sizeof(struct(stack)); scanf("%d",&new->info); new->next = NULL; return(new); }

Page 39: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

39

Implementing pop( )

pop( ){ struct stack * temp; int x; /* check for an empty stack */ if (top = = null) { printf (“Cannot remove nodes from an empty stack */ exit( ); }

Page 40: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

40

Implementing pop( )

else

{

temp = top;

x = top->info;

top = top->next;

free( temp);

return x;

}

Page 41: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

41

Applications of Stacks As a stack is a LIFO structure, it is an appropriate

data structure for applications in which information must be saved and later retrieved in reverse order.

Consider what happens within a computer when function main( ) calls another function.

How does a program remember where to resume execution from after returning from a function call?

From where does it pick up the values of the local variables in the function main( ) after returning from the subprogram?

Page 42: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

42

Applications of Stacks As an example, let main( ) call a( ). Function a( ), in turn,

calls function b( ), and function b( ) in turn invokes function c( ).

main( ) is the first one to execute, but it is the last one to finish, after a( ) has finished and returned.

a( ) cannot finish its work until b( ) has finished and returned. b( ) cannot finish its work until c( ) has finished and returned.

Page 43: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

43

Applications of Stacks When a( ) is called, its calling information is pushed on to

the stack (calling information consists of the address of the return instruction in main( ) after a( ) was called, and the local variables and parameter declarations in main( ).

When b( ) is called from a( ), b( )’s calling information is pushed onto the stack (calling information consists of the address of the return instruction in a( ) after b( ) was called, and the local variables and parameter declarations in a( )).

Page 44: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

44

Applications of Stacks Then, when b( ) calls c( ), c( )’s calling information is

pushed onto the stack (calling information consists of the address of the return instruction in b( ) after c( ) was called, and the local variables and parameter declarations in b( )).

When c( ) finishes execution, the information needed to return to b( ) is retrieved by popping the stack.

Then, when b( ) finishes execution, its return address is popped from the stack to return to a( )

Page 45: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

45

Applications of Stacks Finally, when a( ) completes, the stack is again popped

to get back to main( ).

When main( ) finishes, the stack becomes empty.

Thus, a stack plays an important role in function calls.

The same technique is used in recursion when a function invokes itself.

Page 46: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

46

Summary In this session, you learnt to: Define a stack Describe the operations on a stack Implement a stack as a special case of a

linked list Describe applications of stacks

Page 47: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

47

Page 48: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

48

Chapter 11

Queues

Page 49: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

49

Objectives

In this session, you will learn to: Define a queue Describe the operations on a queue Implement a queue as a special case of a

linked list Describe applications of queues

Page 50: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

50

Defining a Queue

A Queue is a data structure in which elements are added at one end (called the rear), and elements are removed from the other end (called the front).

You come across a number of examples of a queue in real life situations.

For example, consider a line of students at a fee counter. Whenever a student enters the queue, he stands at the end of the queue (analogous to the addition of nodes to the queue)

Page 51: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

51

Defining a Queue

Every time the student at the front of the queue deposits the fee, he leaves the queue (analogous to deleting nodes from a queue).

The student who comes first in the queue is the one who leaves the queue first.

Therefore, a queue is commonly called a first-in-first-out or a FIFO data structure.

Page 52: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

52

Queue Insertions and Deletions

rearfront

frontrearfront

1 2 3 1 2 3 4

2 3 4

rear

(a) (b)

(c)

Page 53: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

53

Queue Operations To complete this definition of a queue, you must

specify all the operations that it permits.

The first step you must perform in working with any queue is to initialize the queue for further use. Other important operations are to add an element, and to delete an element from a queue.

Adding an element is popularly known as ENQ and deleting an element is know as DEQ. The following slide lists operations typically performed on a queue.

Page 54: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

54

Queue Operations create(q) – which creates q as an empty queue

enq(i) – adds the element i to the rear end of the queue

deq(q) – removes the element at the front end of the queue (q) and returns the removed element.

empty (q) – it checks the queue (q) whether it is empty or not. It returns true if the queue is empty and

returns false otherwise

front(q) – returns the front element of the queue without changing the queue

queuesize(q) – returns the number of entries in the queue

Page 55: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

55

Queues can be implemented using array#include <stdio.h>#define MAX 10 /* The maximum size of the queue */#include <stdlib.h>void insert(int queue[], int *rear, int value){ if(*rear < MAX-1) { *rear= *rear +1; queue[*rear] = value; } else { printf("The queue is full can not insert a value\n"); exit(0); } }

Page 56: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

56

void delete(int queue[], int *front, int rear, int * value) { if(*front == rear) { printf("The queue is empty can not delete a value\n"); exit(0); } *front = *front + 1; *value = queue[*front]; }main() { int queue[MAX]; int front,rear; int n,value; front=rear=(-1);

Page 57: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

57

do {

do {

printf("Enter the element to be inserted\n");

scanf("%d",&value);

insert(queue,&rear,value);

printf("Enter 1 to continue\n");

scanf("%d",&n);

} while(n == 1);

printf("Enter 1 to delete an element\n");

scanf("%d",&n);

Page 58: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

58

while( n == 1) { delete(queue,&front,rear,&value); printf("The value deleted is %d\n",value); printf("Enter 1 to delete an element\n"); scanf("%d",&n); } printf("Enter 1 to continue\n"); scanf("%d",&n);} while(n == 1);}

Page 59: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

59

# include <stdio.h># define MAX 10# define TRUE 1# define FALSE 0# define ERROR -1struct queueinfo{

int rear, front;int noelements;int qelements[MAX];

};typedef int queue_type;typedef struct queueinfo queue;void create(queue *);void Ins_queue(queue *, queue_type);int IsQueueFull(queue *);int IsQueueEmpty(queue *);int dequeue(queue *);int menu(void);queue Queue;

(Circular Queue implementation using (Circular Queue implementation using array)array)

Page 60: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

60

main(){

queue_type item;int re;create(&Queue);do{

switch(menu()) {case 1: printf("enter item to en-queue\n");

scanf("%d",&item); Ins_queue(&Queue, item);

break;case 2: item = dequeue(&Queue);

printf("Deleted item is %d\n",item);break;

default: printf("Error\n");}printf("Do you want to continue (y/n)\n");

} while(re!= 'n');}

Page 61: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

61

void create(queue *q){

q -> front = -1;q -> rear = -1;q -> noelements = 0;

}

int IsQueueEmpty(queue *q){

if(q ->noelements == 0) return TRUE;else return FALSE;

}

int IsQueueFull(queue *q){

if(q ->noelements == MAX) return TRUE;else return FALSE;

}

Page 62: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

62

void Ins_queue(queue *q, queue_type item){

char stop;if(IsQueueFull(q))

printf("Queue is full\n");else{

if(IsQueueEmpty(q)){q -> front ++; q ->rear ++;

}else if(q -> rear < (MAX -1) || q -> rear < (q ->front -1 ))

q ->rear++;else if(q ->rear == (MAX -1 ) && q ->noelements < MAX)

q ->rear = 0;q ->qelements[q ->rear] = item;q ->noelements ++;

}}

Page 63: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

63

int dequeue(queue *q){

int data;if(IsQueueEmpty(q)){

printf("Queue is empty\n");return ERROR;

}else{

data = q ->qelements[q ->front];if(q -> front == MAX -1) q ->front = 0;else q ->front++;q ->noelements --;if(IsQueueEmpty(q))

create(q);return data;

}}

Page 64: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

64

int menu(void)

{

int choice;

printf("1. en-queue\n");

printf("2. de-queue\n");

scanf("%d",&choice);

return choice;

}

Page 65: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

65

Implementing Queues

Linked lists offer a flexible implementation of a queue since insertion and deletion of elements into a list are simple, and a linked list has the advantage of dynamically growing or shrinking at runtime.

Having a list that has the functionality of a queue implies that insertions to the list can only be done at the rear of the list, and deletions to the list can only be done at front of the list.

Page 66: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

66

Implementing Queues Queue functionality of a linked list can be

achieved by having two pointers front and rear, pointing to the first element, and the last element of the queue respectively.

The following figure gives a visual depiction of linked list implementation of a queue.

rear

front 2 4 7

Page 67: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

67

Queue Declaration & Operationsstruct queue { int info; struct queue *next; };struct queue *front, *rear;

An empty queue is represented by q->front = q->rear = null. Therefore, clearq( ) can be implemented as follows:

void clearq(struct queue * queue_pointer){ queue_pointer->front = queue_pointer ->rear = null;}

Page 68: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

68

Queue Operations You can determine whether a queue is empty or not by checking its

front pointer.

The front pointer of a queue can be passed as an argument to emptyq( ) to determine whether it is empty or not.

int emptyq (queue_pointer)

{

if (queue_pointer = = null) return (1);

else return(0);

}

Page 69: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

69

Insertion into a Queuestruct queue

{ int info;

struct queue *next;

};

/* pointer declarations to point to the front, and rear of the queue */

struct queue *front, *rear;

main( )

{

front = NULL;

rear = NULL;

Page 70: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

70

Insertion into a Queuechar menu = ‘0 ‘;while (menu != ‘3’) { printf( “Add Nodes :\n”); printf( “Delete Nodes :\n”); printf( “Exit :\n”); menu = getchar( ); switch (menu) { case ‘1’ : enq( ); break; case ‘2’ : deq( ) break;

Page 71: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

71

Insertion into a Queue

case ‘3’: exit( );

break;

} /* end of switch */

} /* end of main( ) */

Page 72: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

72

Insertion into a Queuevoid enq( ) { struct queue *new; new = getnode( ); if(queue_pointer->front= =queue_pointer->rear = = null) { queue_pointer->front = new; queue_pointer->rear = new; } else { rear->next = new; rear = new; } }

Page 73: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

73

Creating a Node on a Queue

struct queue * makenode()

{

struct queue *new;

new=(struct queue *) malloc(sizeof(struct(queue));

scanf("%d",&new->info);

new->next = NULL;

return(new);

}

Page 74: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

74

Insertion into a Queue

New node inserted at rear of queue

nextnextnext

rear

front 2 4 7 8

New

Page 75: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

75

Deletion from a Queueint deq( ) { struct queue *temp; int x; if(queue_pointer->front= =queue_pointer->rear = = null) { printf( “Queue Underflow\n”); exit (1); } temp = front; x=temp->info; front = front->next; free(temp); if(front = = null) /* check for queue becoming empty after node deletion */ rear = null; return(x); }

Page 76: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

76

Deletion of a Node From a Queue

Node being deleted at the front of the queue

rear

front 2 4 7

Page 77: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

77

Applications of Queues

Queues are also very useful in a time-sharing multi-user operating system where many users share the CPU simultaneously.

Whenever a user requests the CPU to run a particular program, the operating system adds the request

This process ID is then added at the end of the queue of jobs waiting to be executed.

Page 78: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

78

Applications of Queues

Whenever the CPU is free, it executes the job that is at the front of the job queue.

Similarly, there are queues for shared I/O devices. Each device maintains its own queue of requests (Example printers).

An example is a print queue on a network printer, which queues up print jobs issued by various users on the network.

The first print request is the first one to be processed. New print requests are added at the end of the queue.

Page 79: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

79

Summary In this session, you learnt to:

Define a queue

Describe the operations on a queue

Implement a queue as a special case of a linked list

Describe applications of queues

Page 80: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

80

Page 81: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

81

Priority Queues

Page 82: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

82

Objectives

At the conclusion of this section, you will have demonstrated the ability to:

Discuss the usefulness and application of priority queues;

Choose between algorithms that trade-off speed and complexity against data size; and

Perform a complete, modularized priority queue implementation.

Page 83: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

83

Priority Queues

priority queue, which organizes data according to an arbitrary designation of importance.

Priority queues are a practical means of implementing schedulers,

such as real-time operating system schedulers that execute processes, or communications schedulers that transmit messages according to their priority.

Page 84: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

84

A priority queue is a queue in which each element is assigned a priority.

A priority is typically an integer, and higher integers represent higher priorities.

All elements having the same priority are said to belong to the same priority class.

Page 85: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

85

priority queue may be visualized as an array in which all elements of the same priority class are grouped together, and higher priority classes are grouped closer to the front of the array.

A new element is added to the tail of its priority class, and elements are always removed from the front of the queue.

A remove operation, therefore, always addresses the element of the highest priority class that has been enqueued the longest.

Page 86: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

86

Page 87: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

87

Simple Priority Queues operations

1. Create a queue;2. Create a queue item;3. Determine if a queue is empty;4. Add a new item to a queue;5. Remove the item at the front of a queue;6. Empty a queue;7. Destroy a queue item; and8. Destroy a queue.

Page 88: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

88

Page 89: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

89

Chapter 9Linked Lists

Page 90: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

90

Objectives

In this session, you will learn to:

Describe the limitations of using a data structure such as an array Define stack and heap variables Describe the characteristics of stack and heap variables State the need for dynamic memory allocation Use the malloc() function to allocate memory Define self-referential structures and their advantages

Write code to: Create a sorted linked list, Insert nodes into a sorted linked list Traverse a linked list Delete nodes from a linked list

Page 91: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

91

Array Usage – A Perspective Consider the following example:

#include<stdio.h>main( ){ int num_array[50],i; for( i=0; i < 50; i++ ) {

num_array[i]=0; scanf( "%d",&num_array[i] );

} }

Page 92: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

92

Array Usage – A Perspective

When this program is compiled, the compiler estimates the amount of memory required for the variables, and also the instructions defined by you as part of the program.

The compiler writes this information into the header of the executable file that it creates. When the executable is loaded into memory at runtime, the specified amount of memory is set aside.

A part of the memory allocated to the program is in an area of memory called a runtime stack or the call stack. Once the size of the stack is fixed, it cannot be changed dynamically.

Page 93: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

93

Array Usage – A Perspective Therefore, arrays present the classic problem of the

programmer having allocated too few elements in the array at the time of writing the program, and then finding at run time that more values are required to be stored in the array than what had originally been defined.

The other extreme is of the programmer allocating too many elements in the array and then finding at run time that not many values need to be stored in the array thereby resulting in wastage of precious memory.

Page 94: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

94

Array Usage – A Perspective Moreover, array manipulation (in terms of insertion

and deletion of elements from the array) is more complex and tedious, and a better alternative to all this is to go for dynamic data structures.

Before venturing into dynamic variables, or dynamic data structures, it would be prudent at this juncture to differentiate between stack and heap variables, and their characteristics.

Let us begin by understanding the concept of lifetime of variables.

Page 95: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

95

Lifetime Of A Variable

is a run-time concept period of time during which a variable has memory space

associated with it begins when space is allocated ends when space is de-allocated

three categories of "lifetime" static - start to end of program execution automatic (stack) - start to end of declaring function's

execution heap (variable declared dynamic at runtime, and also de-

allocated dynamically at runtime.

Page 96: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

96

Data Memory Model

static data

automatic data

heap data

run-time stack - activation records added and removed as program runs (expands and shrinks in an orderly LIFO manner)

space for global variables

space for variables allocated at run-time (allocation and de-allocation requests occur in unpredictable order)

Page 97: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

97

Heap Variables

Space for heap variables is allocated from an area of runtime memory known as the heap or free store.

Heap variables do not have an explicit name, and are accessed indirectly via a pointer.

Memory space for heap variables is explicitly allocated at runtime using malloc( ).

Space occupied by heap variables must be explicitly returned back to the heap to avoid memory leaks. This is done using the free( ) function.

Page 98: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

98

Dynamic Data Structures

Rather than pre-define array on the stack at compile time, the alternative should be to define a structure type, and dynamically declare at runtime as many instances of the structure variables as needed by the application.

When the code containing the structure type is compiled, what the compiler sees is only a structure type declaration.

It therefore, does not allocate memory for the structure type since no variable has been defined based on the structure type.

Page 99: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

99

Dynamic Data Structures

When the program begins execution, it will need to create variables of the structure type. Therefore, the language must support runtime declaration of variables.

The problem with these variables is that they cannot be accommodated into the stack, as they were not declared at the time of compilation, and the stack would have been sized based on the stack variables already declared at compile-time.

The C language provides the malloc() function which a program can use to declare variables dynamically.

Page 100: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

100

The malloc( ) Function The parameter to malloc( ) is an unsigned integer which

represents the number of bytes that the programmer has requested malloc( ) to allocate on the heap.

A more effective way of passing the number of bytes to malloc( ) would be to pass the structure type along with the sizeof( ) operator to malloc( ).

The sizeof( ) operator can be used to determine the size of any data type in C, instead of manually determining the size and using that value. Therefore, the benefit of using sizeof( ) operator in any program makes it portable.

Page 101: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

101

The malloc( ) Function

Consider the following example:#include<stdio.h>main() { struct marks_data { char name[11]; int marks; }; struct marks_data *ptr; /* declaration of a stack variable */ ptr = (struct marks_data *) malloc(sizeof(struct marks_data)); /* declaration of a block of memory on the heap and the block in turn being

referenced by ptr */ }

Page 102: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

102

The malloc( ) Function

ptr

100

Stack Heap

Name Marks

100

Page 103: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

103

The malloc( ) Function The malloc( ) function also returns the starting address to

the marks_data structure variable on the heap.

However, malloc( ) returns this not as a pointer to a structure variable of type marks_data , but as a void pointer.

Therefore, the cast operator was used on the return value of malloc( ) to cast it as a pointer to a structure of type marks_data before being assigned to ptr, which has accordingly been defined to be a pointer to a structure of type marks_data.

Page 104: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

104

THE LIST DATA STRUCTURE

A list is a sequential data structure, i.e. a collection of items accessible one after another beginning at the head and ending at the tail.

It is a widely used data structure for applications which do not need random access.

It differs from the stack and queue data structures in that additions and removals can be made at any position in the list.

Page 105: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

105

Operations On the list The main primitive operations of a list are known as:

Add : adds a new node

Update :updates the contents of a node

Remove : removes a node

Sort : sorting the list members

Insert : inserting the data at the given position.

Page 106: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

106

Storing a list in a static data structure (Array List)

This implementation stores the list in an array. The Array List has the following properties:

• The position of each element is given by an index from 0 to n-1, where n is the number of elements.

• Given any index, the element with that index can be accessed in constant time – i.e. the time to access does not depend on the size of the list.

Page 107: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

107

• To add an element at the end of the list, the time taken does not depend on the size of the list.

However, the time taken to add an element at any other point in the list does depend on the size of the list, as all subsequent elements must be shifted up. Additions near the start of the list take longer than additions near the middle or end.

• When an element is removed, subsequent elements must be shifted down, so removals near the start of the list take longer than removals near the middle or end.

Page 108: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

108

Storing a list in a dynamic data structure (Linked List)

The Linked List is stored as a sequence of linked nodes, each node in a linked list contains data AND a reference to the next node.

The Linked List has the following properties:

• The list can grow and shrink as needed.

• The position of each element is given by an index from 0 to n-1, where n is the number of elements.

Page 109: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

109

Given any index, the time taken to access an element

with that index depends on the index. This is because each element of the list must be traversed until the required index is found.

• The time taken to add an element at any point in the list does not depend on the size of the list, as no shifts are required. It does, however, depend on the index.

Additions near the end of the list take longer than additions near the middle or start. The same applies to the time taken to remove an element.

Page 110: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

110

Self-Referential Structures

Suppose, you have been given a task to store a list of marks. The size of the list is not known.

If it were known, then it would have facilitated the creation of an array of the said number of elements and have the marks entered into it.

Elements of an array are contiguously located, and

therefore, array manipulation is easy using an integer variable as a subscript, or using pointer arithmetic.

Page 111: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

111

Self-Referential Structures However, when runtime variables of a particular type are

declared on the heap, let's say a structure type in which we are going to store the marks, each variable of the structure type marks will be located at a different memory location on the heap, and not contiguously located.

Therefore, these variables cannot be processed the way arrays are processed, i.e., using a subscript, or using pointer arithmetic.

An answer to this is a self-referential structure.

Page 112: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

112

Self-Referential Structures

A self-referential structure is so defined that one of the elements of the structure variable is able to reference another subsequent structure variable of the same type, wherever it may be located on the heap.

In other words, each variable maintains a link to another variable of the same type, thus forming a non-contiguous, loosely linked data structure.

This self-referential data structure is also called a linked list.

Page 113: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

113

Types of List implementation

Singular Linked list

Single circular Linked list

Double Linked list

Double circular Linked list

Page 114: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

114

Declaring a Linked List

Let us define a self-referential structure to store a list of marks the size of which may not be known.

struct marks_list { int marks; struct marks_list *next; };

We have defined a structure of type marks_list. It consists of two elements, one integer element marks and the other element, a pointer next, which is a pointer to a structure of the same type, i.e., of type marks_list itself.

Page 115: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

115

Declaring a Linked List Therefore, a part of the structure is referencing a

structure type of itself, and hence the name self-referential structure.

Such data structures are also popularly known as linked lists, since each structure variable contains a link to other structure variables of the same type.

One can visualize a linked list as shown in the following slide:

Page 116: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

116

Visualizing a Linked List

marks

next

180100 140start

100 75 140 85 180 95 230 100 x

marks

next marks

next marks

next

Stack Heap

Page 117: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

117

Circularly linked lists

The tail of the list always points to the head of the list

Page 118: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

118

Doubly linked lists These permit scanning or searching of the list in

both directions. (To go backwards in a simple list, it is necessary to go back to the start and scan forwards.) In this case, the node structure is altered to have two links:

Page 119: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

119

Single Linked List can be explained as

struct node{ int data; struct node *next;};typedef struct node Node;int menu(void);Node *create(void);void insert(Node *,int);void display(Node *);int small(Node *);int large(Node *);int search(Node *,int);int delete(int);

Page 120: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

120

Node *fptr;main(){ int choice,element,num;

char ch='y';fptr=NULL;printf("enter the element\n");scanf("%d",&element);fptr=create();fptr->data=element;fptr->next=NULL;

do {

choice=menu(); switch(choice)

{

Page 121: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

121

case 1: printf("ENTER THE ELEMENTS\n"); scanf("%d",&element); insert(fptr,element); break;

case 2: printf("DISPLAYING THE CONTENTS OF THE LIST\n"); display(fptr); break;

case 3: if(fptr==NULL)printf("Empty list\n");

else printf("THE SMALLEST ELEMENT IS %d\n",small(fptr))

break;case 4: if(fptr==NULL)

printf("Empty list\n"); else

printf("THE LARGEST ELEMENT IS %d\n",large(fptr)); break;

Page 122: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

122

case 5: printf("ENTER THE ELEMENT TO BE SEARCHED\n"); scanf("%d",&num); search(fptr,num); break;

case 6: printf("ENTER THE ELEMENT TO BE DELETED\n"); scanf("%d",&num); element=delete(num); printf("THE ELEMENT %d IS DELETED\n",element);

break; case 7: exit(0);

default: printf("invalid option\n");}

printf("DO YOU WISH TO CONTINUE Y or N \n"); ch=getchar();

}while(ch!='N'||ch!='n');}

Page 123: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

123

Node *create(void){ Node *new; new=(Node *)malloc(sizeof(Node)); return(new);}void insert(Node *p,int x){ if(p==NULL) printf("error\n"); else {

while(p->next!=NULL) p=p->next; p->next=create(); p=p->next; p->data=x; p->next=NULL;

}}

Page 124: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

124

void display(Node *p){ while(p!=NULL) {

printf("%d\n",p->data); p=p->next; }}int small(Node *p){

int s;s=p->data;while(p! = NULL){

if(p->data<s) s=p->data;p=p->next;

}return(s);

}

Page 125: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

125

int large(Node *p){

int l;l=p->data;while(p!=NULL){

if(p->data>l) l=p->data;p=p->next;

}return(l);

}int search(Node *p,int x){

while(p!=NULL){if(p->data==x){

printf("THE ELEMENT %d EXISTS\n",x);return 0;

}else p=p->next;

}printf("ELEMENT NOT FOUND\n");return -1;

}

Page 126: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

126

int delete(int x){

Node *temp,*node,*old;temp=node=fptr;while(temp!=NULL){

if(node->data==x){fptr=fptr->next;free(node);return(x);

}else if(temp ->data == x){

old->next=temp->next;free(temp);return(x);

}old=temp;temp=temp->next;

}return -1;

}

Page 127: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

127

Creating a Sorted Linked List#include <stdio.h>struct node{

int info;struct node *next;

};struct node *head, *save;int j=0;struct node *create(void);void sort(struct node *);void insert(int );void display(struct node *);

Page 128: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

128

main(){

int n, i ,x;head = NULL;printf("Enter how many terms\n");scanf("%d", &n);printf("Enter elements\n");for(i = 0; i < n; i++){

scanf("%d",&x);insert(x);j++;

}printf("linked list is");display(head);sort(head);printf("Sorted linked list is \n");display(head);

}

Page 129: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

129

void insert(int x){

struct node *temp;if(j == 0){

temp=create();temp->info=x;temp->next = NULL;head = temp;save = temp;

}else {

temp = create();temp -> info = x;temp -> next = NULL;save -> next = temp;save = temp;

}}

Page 130: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

130

struct node *create(void){

struct node *p;p=(struct node *) malloc(sizeof(*head));return (p);

}void display(struct node *p){

while(p!= NULL){printf("%d ->", p -> info);p = p ->next;

}printf("\n\n");

}

Page 131: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

131

void sort(struct node *p){

struct node *p1,*p2,*p3;int temp;for(p1 = p; p1!= NULL;p1=p1 -> next)

for(p2 = p1 -> next; p2 != NULL;p2=p2 -> next){if( p1 -> info >= p2 -> info){

temp = p1 ->info;p1 -> info = p2 -> info;p2 -> info = temp;

}}

}

Page 132: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

132

Doubly Linked Lists

Page 133: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

133

Objectives

In this session, you will learn to:

Describe the need for, and advantages of a doubly linked list

Write code to: Create a sorted doubly linked list, Insert nodes into a sorted doubly linked list Traverse a doubly linked list Delete nodes from a doubly linked list

Page 134: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

134

Need For a Doubly Linked List

The disadvantage with a singly linked list is that traversal is possible in only direction, i.e., from the beginning of the list till the end.

If the value to be searched in a linked list is toward the end of the list, the search time would be higher in the case of a singly linked list.

It would have been efficient had it been possible to search for a value in a linked list from the end of the list.

Page 135: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

135

Properties of a Doubly Linked List

This would be possible only if we have a doubly linked list.

In a doubly linked list, each node has two pointers, one say, next pointing to the next node in the list, and another say, prior pointing to the previous node in the list.

Therefore, traversing a doubly linked list in either direction is possible, from the start to the end using next, and from the end of the list to the beginning of the list using prior.

Page 136: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

136

Properties of a Doubly Linked List In a doubly linked list, the prior pointer of the first node will

be null, as there is no node before the first node.

In a doubly linked list, the next pointer of the last node will be null, as there is no node after this list.

Bidirectional traversal of a doubly linked list is useful for implementing page up, and page down functionality when using doubly linked lists to create editors.

A doubly linked list would have two pointers, start and last to facilitate traversal from the beginning and end of the list respectively.

Page 137: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

137

Declaration of a Doubly Linked Liststruct marks_list

{

struct double_list *prior;

int info;

struct marks_list *next;

}

Page 138: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

138

Visualizing a Doubly Linked List

prior nextmarks

null 1 120

100

prior nextmarks

100 2 140

120

prior nextmarks

120 3 null

140

100

start

140

last

Page 139: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

139

Creating a Sorted Doubly Linked Liststruct marks_list *start, *last;/* variables declared outside main() are global in nature and can

be accessed by other functions called from main() */struct marks_list {

struct marks_list *prior; int marks; struct marks_list *next;

};main(){ struct marks_list * makenode(); /* function prototype declaration */

Page 140: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

140

Creating a Sorted Doubly Linked List

struct marks_list *new;start = NULL;char menu = ‘0 ‘;while (menu != ‘5’) { printf( “Add Nodes :\n”); printf( “Delete Nodes :\n”); printf( “Forward Traverse a list :\n”); printf( “Reverse Traverse a list :\n”); printf( “Exit :\n”); menu = getchar( );

Page 141: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

141

Creating a Sorted Doubly Linked Listswitch (menu) { case ‘1’ : addnode( ); break; case ‘2’ : deletenode( ) break; case ‘3’ : forward_traverse( ); break; case ‘4’ : reverse_traverse( ); break; case ‘5’: exit( ); break;} /* end of switch */ } /* end of main( ) */

Page 142: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

142

Creating a Sorted Doubly Linked List

addnode( ) { char ch = 'y'; while ( ch = = 'y' ) { new = makenode(); /* creation of a list is treated as a special case of insertion */ if ( start = = NULL) { start = new; start->prior = null; } else { insert(); traverse( ); }

Page 143: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

143

Creating a Sorted Doubly Linked List

printf("%s","Want to add more nodes\n");

scanf( "%c", &ch );

} /* end of while */

} /* end of addnode( )

Page 144: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

144

Creating a Sorted Doubly Linked List

struct marks_list * makenode()

{ struct marks_list *new;

new=(struct marks_list *) malloc(sizeof(struct(marks_list));

scanf("%d",&new->marks); new->prior = NULL;new->next = NULL;return(new);

}

Page 145: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

145

Creating a Sorted Linked List

insert( ){

struct marks_list *ptr, *prev;for(ptr=start,prev=start;(ptr);prev=ptr,ptr=ptr->next) { if (new->marks < start->marks) {

/* insertion at the beginning of a list */ new->next = start; new->prior = NULL; start->prior = new; last = start; start = new;

}

Page 146: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

146

Creating a Sorted Doubly Linked List/* insertion in the middle of a list */

if(new->marks > ptr->marks) { continue; }

else {

prev->next = new;

new->prior = prev;

new->next = ptr;

ptr->prior = new;

}

} /* end of for loop */

Page 147: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

147

Creating a Sorted Linked List

/* insertion at the end of the list */

if (ptr = = null) {

prev->next = new;

new->prior = prev;

new->next = null;

last = new;

}

} /* end of insert */

Page 148: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

148

Searching a Value in a Doubly Linked List

struct marks_list *search( int val){ for( ptr = start; (ptr); ptr = ptr->next) {

if (val = = ptr-> marks) return ptr; }

struct marks_list *search( int val){ for( ptr = last; (ptr); ptr = ptr->prior) {

if (val = = ptr-> marks) return ptr; }

Page 149: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

149

Deleting a Node From a Doubly Linked List

delete ( ){

struct marks_list *ptr, *prev, *temp; int score; /* search the linked list for the value to be deleted */ scanf(“%d”, &score);

for (ptr = start, prev = start; (ptr); prev = ptr, ptr = ptr->next) {

/* deletion of the first node in the list */ if (score = = start-> marks) {

temp =start; start = start-> next; start->prior = null; free(temp);

}

Page 150: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

150

Deleting a Node From a Linked List

/* deletion in the middle of a linked list */ if (score = = ptr-> marks) { prev-> next = ptr-> next; ptr->next->prior = ptr->prior; free(ptr); }

/* deletion at the end of the list */ if (ptr->next = = null) {

temp = ptr; prev->next = null; last = ptr->prior; }} }

Page 151: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

151

Traversal of a Doubly Linked List

/* forward traversal of a doubly linked list */

for( ptr = start; (ptr); ptr = ptr->next){

printf(“%d”, ptr->marks);

}

/* reverse traversal of a doubly linked list */

for( ptr = last; (ptr); ptr = ptr->prior) {

printf(“%d”, ptr->marks);

}

Page 152: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

152

Points to remember Linked lists are used when the quantity of data is not known

prior to execution.

In linked lists, data is stored in the form of nodes and at runtime, memory is allocated for creating nodes.

Due to overhead in memory allocation and deallocation, the speed of the program is lower.

The data is accessed using the starting pointer of the list.

Page 153: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

153

Summary In this session, you learnt to:

Describe the limitations of using a data structure such as an array

Define stack and heap variables Describe the characteristics of stack and heap variables State the need for dynamic memory allocation Use the malloc() function to allocate memory Define self-referential structures and their advantages Write code to:

Create a sorted linked list, Insert nodes into a sorted linked list Traverse a linked list Delete nodes from a linked list

Page 154: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

154

Summary

Describe the need for, and advantages of a doubly linked list

Write code to: Create a sorted doubly linked list, Insert nodes into a sorted doubly linked list Traverse a doubly linked list Delete nodes from a doubly linked list

Page 155: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

155

Page 156: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

156

Binary Trees

Page 157: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

157

Objectives

At the end of this lesson, you will be able to: Define a binary tree Describe the terminologies associated with a

binary tree Use a dynamically allocated data structure to

represent a binary tree Traverse a binary tree Add nodes to a binary tree Remove nodes from a binary tree Search a binary tree

Page 158: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

158

Eliminative or a Binary Search The mode of accessing data in a linked list is

linear.

Therefore, in the worst case scenario of the data in question being stored at the extremes of the list, it would involve starting with the first node, and traversing through all the nodes till one reaches the last node of the list to access the data.

Therefore, search through a linked list is always linear.

Page 159: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

159

Eliminative or a Binary Search

A linear search is fine if the nodes to be searched in a linked list are small in number.

But the linear search becomes ineffective as the number of nodes in a linked list increase.

The search time increases in direct proportion with the size of the linked list.

It becomes imperative to have better searching mechanisms than a linear search.

Page 160: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

160

Eliminative or a Binary Search

You will now be exposed to a game that will highlight a new mechanism of searching.

A B C

D E F

G H I

J K L

M N O

P Q R

X

YES NO

Coin Search in a Group

Page 161: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

161

Eliminative or a Binary Search

A coin is with one of the members in the audience divided into the two sections on the left and the right respectively as shown in the diagram.

The challenge facing X, the protagonist, is to find the person with the coin in the least number of searches.

Page 162: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

162

Employing the Linear Search

X, familiar with a linear search, starts using it to search for the coin among the group.

Let us assume the worst-case scenario of the coin being with R.

If X was to start the search with A and progress linearly through B, C, ….M and finally to R, he would have taken a minimum of 18 searches (R being the 18th person searched in sequence to find the coin.

Page 163: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

163

Employing the Linear Search

As you can see, this kind of search is not very efficient especially when the number of elements to be searched is high.

An eliminative search, also called a binary search, provides a far better searching mechanism.

Page 164: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

164

Employing the Eliminative or The Binary Search

Assume that X can pose intelligent questions to the audience to cut down on the number of searches.

A valid question that he could pose is “Which side of the audience has the coin?”

‘A’ in the audience to the left of him says that his side of the audience does not have the coin.

So X can completely do away with searching the audience to his left. That saves him 9 searches.

Page 165: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

165

Employing the Eliminative or The Binary Search

X has now got to search the audience to the right of him for searching out the coin.

Here too, he can split the audience into half by standing adjacent to the middle row, and posing the same question that he asked earlier “Which side of the audience has the coin?”

‘M’ in the middle row replies that the coin is with the audience to the left of him.

Page 166: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

166

Employing the Eliminative or The Binary Search

X has in the process now eliminated 6 more searches, that is, the middle row and the row to the left of the middle as shown in the diagram below.

J K L

M N O

P Q R

X

6 searches saved

NO

YES

Page 167: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

167

X is now left with row to the right of the middle row containing P, Q, and R that has to be searched.

Here too, he can position himself right at the middle of the row adjacent to Q and pose the same question,

“Which side of the audience has the coin?” ‘Q’ replies that the coin is to his left.

P Q R

X

NO YES

Page 168: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

168

Eliminative or Binary Search

That completes our eliminative or binary search.

It is called a binary search because at each stage of the search, the search is cut by more than half.

This kind of search forms the basis for the searching mechanism employed in a data structure wherein the data is represented in a hierarchal manner unlike the linear mechanism of storage employed in a linked list.

Page 169: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

169

Trees Compared to linked lists that are linear data structures, trees

are non-linear data structures.

In a linked list, each node has a link which points to another node.

In a tree structure, however, each node may point to several nodes, which may in turn point to several other nodes.

Thus, a tree is a very flexible and a powerful data structure that can be used for a wide variety of applications.

Page 170: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

170

Trees

Rajeev

Ravi Vijay Anjali

Ramesh Suresh Sukesh Arvind

Page 171: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

171

Trees

A tree consists of a collection of nodes that are connected to each other.

A tree contains a unique first element known as the root, which is shown at the top of the tree structure.

A node which points to other nodes is said to be the parent of the nodes to which it is pointing, and the nodes that the parent node points to are called the children, or child nodes of the parent node.

Page 172: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

172

Trees

The root is the only node in the tree that does not have a parent.

All other nodes in the tree have exactly one parent.

There are nodes in the tree that do not have any children. Such nodes are called leaf nodes.

Nodes are siblings if they have the same parent.

Page 173: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

173

Trees

A node is an ancestor of another node if it is the parent of that node, or the parent of some other ancestor of that node.

The root is an ancestor of every other node in the tree.

Similarly, we can define a node to be a descendant of another node if it is the child of the node, or the child of some other descendant of that node.

You may note that all the nodes in the tree are descendants of the root node.

Page 174: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

174

Tree

An important feature of a tree is that there is a single unique path from the root to any particular node.

The length of the longest path from the root to any node is known as the depth of the tree.

The root is at level 0 and the level of any node in the tree is one more than the level of its parent.

In a tree, any node can be considered to be a root of the tree formed by considering only the descendants of that node. Such a tree is called the subtree that itself is a tree.

Page 175: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

175

Binary Tree If you can introduce a restriction that each node can

have a maximum of two children or two child nodes, then you can have a binary tree.

You can give a formal definition of a binary tree as a tree which is either empty or consists of a root node together with two nodes, each of which in turn forms a subtree.

You therefore have a left subtree and a right subtree under the root node.

Page 176: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

176

Binary Search Tree A complete binary tree can be defined as one whose non-leaf nodes

have non-empty left and right subtrees and all leaves are at the same level.

This is also called as a balanced binary tree.

If a binary tree has the property that all elements in the left subtree of a node n are less than the contents of n, and all elements in the right subtree are greater than the contents of n, such a tree is called a binary search tree.

The following is an example of a balanced binary search tree.

Page 177: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

177

Balanced Binary Search Tree

4

6

5 731

2

N NNN N NNN

Page 178: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

178

Binary Vs. Linear Search

As the name suggests, balanced binary search trees are very useful for searching an element just as with a binary search.

If we use linked lists for searching, we have to move through the list linearly, one node at a time.

If we search an element in a binary search tree, we move to the left subtree for smaller values, and to the right subtree for larger values, every time reducing the search list by half approximately.

Page 179: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

179

Linear Search in a Linked List

100

1 120 2 140 3 160 4 180 5 200 6 220 7 null

Page 180: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

180

Binary Search in a Binary Search Tree

4

6

5 731

2

N NNN N NNN

7

Search Value

7

Search Value

7

Search Value

Page 181: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

181

The Essence of a Binary Search To summarize, you have completely done away with

searching with the entire left subtree of the root node and its descendant subtrees, in the process doing away with searching one-half of the binary search tree.

Even while searching the right subtree of the root node and its descendant subtrees, we keep searching only one-half of the right subtree and its descendants.

This is more because of the search value in particular, which is 7. The left subtree of the right subtree of the root could have been searched in case the value being searched for was say 5.

Page 182: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

182

The Essence of a Binary Search

Thus we can conclude that while searching for a value in a balanced binary search tree, the number of searches is cut by more than half (3 searches in a balanced binary search tree) compared to searching in a linked list (7 searches).

Thus a search that is hierarchical, eliminative and binary in nature is far efficient when compared to a linear search.

Page 183: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

183

Data Structure Representation of a Binary Trees

A tree node may be implemented through a structure declaration whose elements consist of a variable for holding the information and also consist of two pointers, one pointing to the left subtree and the other pointing to the right subtree.

A binary tree can also be looked at as a special case of a doubly linked list that is traversed hierarchically.

The following is the structure declaration for a tree node:

Page 184: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

184

Data Structure Representation of a Binary Trees

struct btreenode

{

int info;

struct btreenode *left;

struct btreenode *right;

};

Page 185: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

185

Traversing a Binary Tree

Traversing a binary tree entails visiting each node in the tree exactly once.

Binary tree traversal is useful in many applications, especially those involving an indexed search.

Nodes of a binary search tree are traversed hierarchically.

The methods of traversing a binary search tree differ primarily in the order in which they visit the nodes.

Page 186: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

186

Traversing a Binary Tree

At a given node, there are three things to do in some order. They are:

To visit the node itself To traverse its left subtree To traverse its right subtree We can traverse the node before traversing either sub

tree. Or, we can traverse the node between the sub trees. Or, we can traverse the node after traversing both sub

trees.

Page 187: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

187

Traversing a Binary Tree If we designate the task of visiting the root as R’,

traversing the left subtree as L and traversing the right subtree as R, then the three modes of tree traversal discussed earlier would be represented as:

R’LR – Preorder LRR’ – Postorder LR’R – In order

Page 188: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

188

Traversing a Binary Tree

The functions used to traverse a binary tree using these methods can be kept quite short if we understand the recursive nature of the binary tree.

Recall that a binary tree is recursive in that each subtree is really a binary tree itself.

Thus traversing a binary tree involves visiting the root node, and traversing its left and right subtrees.

The only difference among the methods is the order in which these three operations are performed.

Page 189: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

189

Traversing a Binary Tree

Depending on the position at which the given node or the root is visited, the name is given.

If the root is visited before traversing the subtree, it is called the preorder traversal.

If the root is visited after traversing the subtrees, it is called postorder traversal.

If the root is visited in between the subtrees, it is called the inorder traversal.

Page 190: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

190

Traversing a Binary Tree

A

B

C

D E

Page 191: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

191

Preorder Traversal

When we traverse the tree in preorder, the root node is visited first. So, the node containing A is traversed first.

Next, we traverse the left subtree. This subtree must again be traversed using the preorder method.

Therefore, we visit the root of the subtree containing B and then traverse its left subtree.

The left subtree of B is empty, so its traversal does nothing. Next we traverse the right subtree that has root labeled C.

Page 192: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

192

Preorder Traversal

Then, we traverse the left and right subtrees of C getting D and E as a result.

Now, we have traversed the left subtree of the root containing A completely, so we move to traverse the right subtree of A.

The right subtree of A is empty, so its traversal does nothing. Thus the preorder traversal of the binary tree results in the values ABCDE.

Page 193: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

193

Inorder Traversal

For inorder traversal, we begin with the left subtree rooted at B of the root.

Before we visit the root of the left subtree, we must visit its left subtree, which is empty.

Hence the root of the left subtree rooted at B is visited first. Next, the right subtree of this node is traversed inorder.

Page 194: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

194

Inorder Traversal

Again, first its left subtree containing only one node D is visited, then its root C is visited, and finally the right subtree of C that contains only one node E is visited.

After completing the left subtree of root A, we must visit the root A, and then traverse its right subtree, which is empty.

Thus, the complete inorder traversal of the binary tree results in values BDCEA.

Page 195: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

195

Postorder Traversal

For postorder traversal, we must traverse both the left and the right subtrees of each node before visiting the node itself.

Hence, we traverse the left subtree in postorder yielding values D, E, C and B.

Then we traverse the empty right subtree of root A, and finally we visit the root which is always the last node to be visited in a postorder traversal.

Thus, the complete postorder traversal of the tree results in DECBA.

Page 196: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

196

Code - Preorder Traversal

void preorder (p)struct btreenode *p; { /* Checking for an empty tree */

if ( p != null) {

/* print the value of the root node */ printf(“%d”, p->info); preorder(p->left); /* traverse its left subtree */

preorder(p->right); /* traverse its right subtree */ }

}

Page 197: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

197

Code – Inorder Traversal

void inorder(p)struct btreenode *p; {

/* checking for an empty tree */ if (p != null) {

/* traverse the left subtree inorder */ inorder(p->left);

/* print the value of the root node */ printf(“%d”, p->info);

/*traverse the right subtree inorder */ inorder(p->right);

} }

Page 198: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

198

Code – Postorder Traversal

void postorder(struct btreenode *p ){

/* checking for an empty tree */if (p != null) {

postorder(p->left); /* traverse in the left subtree */

postorder(p->right); /* traverse in the right subtree */

/* print the value of the root node */printf(“%d”, p->info);

} }

Page 199: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

199

Accessing Values From a BinarySearch Tree Using Inorder Traversal

You may note that when you traverse a binary search tree inorder, the keys will be in sorted order because all the keys in the left subtree are less than the key in the root, and all the keys in the right subtree are greater than that in the root.

The same rule applies to all the subtrees until they have only one key.

Therefore, given the entries, we can build them into a binary search tree and use inorder traversal to get them in sorted order.

Page 200: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

200

Insertion into a Tree Another important operation is to create and maintain a binary search

tree.

While inserting any node, we have to take care the resulting tree satisfies the properties of a binary search tree.

A new node will always be inserted at its proper position in the binary search tree as a leaf.

Before writing a routine for inserting a node, consider how a binary tree may be created for the following input: 10, 15, 12, 7, 8, 18, 6, 20.

Page 201: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

201

Insertion into a Tree

First of all, you must initialize the tree.

To create an empty tree, you must initialize the root to null. The first node will be inserted into the tree as a root node as shown in the following figure.

10Root

Page 202: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

202

Insertion into a Tree

Since 15 is greater than 10, it must be inserted as the right child of the root as shown in the following figure.

10Root

15

Page 203: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

203

Insertion into a Tree

Now 12 is larger than the root; it must go to the right subtree of the root.

Further, since it is smaller than 15, it must be inserted as the left child of the root as shown below.

10Root

15

12

Page 204: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

204

Insertion into a Tree

Next, 7 is smaller than the root.

Therefore, it must be inserted as the left child of the root as shown in the following figure.

10

15

12

7

Page 205: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

205

Insertion into a Tree

Similarly, 8, 18, 6 and 20 are inserted at the proper place as shown in the following figures.

10

15

12

7

8

10

15

12

7

8 18

Page 206: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

206

Insertion into a Tree

10

15

12

7

8 186

10

15

12

7

8 186

20

Page 207: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

207

Insertion into a Tree This example clearly illustrates that given the root of a

binary search tree and a value to be added to the tree, we must search for the proper place where the new value can be inserted.

We must also create a node for the new value and finally, we have to adjust the left and right pointers to insert the new node.

To find the insertion place for the new value, say 17, we initialize a temporary pointer p, which points to the root node.

Page 208: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

208

Insertion into a Tree

We can change the contents of p to either move left or right through the tree depending on the value to be inserted.

When p becomes null, we know that we have found the insertion place as in the following figure.

Page 209: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

209

Insertion into a Tree

10

15

12

7

8 186

20

Root

p

Page 210: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

210

Insertion into a Tree

But once p becomes null, it is not possible to link the new node at this position because there is no access to the node that p was pointing to (node with value 18) just before it became null.

From the following figure, p becomes null when we have found that 17 will be inserted at the left of 18.

Page 211: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

211

Insertion into a Tree

10

15

12

7

8 186

20

Root

p null

Page 212: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

212

Insertion into a Tree

You therefore need a way to climb back into the tree so that you can access the node containing 18, in order to make its left pointer point to the new node with the value 17.

For this, you need a pointer that points to the node containing 18 when p becomes null.

To achieve this, you need to have another pointer (trail) that must follow p as p moves through the tree.

Page 213: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

213

Insertion into a Tree

When p becomes null, this pointer will point to the leaf node (the node with value 18) to which you must link the new node (node with value 17).

Once you know the insertion place, you must adjust the pointers of the new node.

At this point, you only have a pointer to the leaf node to which the new node is to be linked.

You must determine whether the insertion is to be done at the left subtree or the right subtree of the leaf node.

Page 214: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

214

Insertion into a Tree

To do that, you must compare the value to be inserted with the value in the leaf node.

If the value in the leaf node is greater, we insert the new node as its left child; otherwise we insert the new node as its right child.

Page 215: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

215

Creating a Tree – A Special Case of Insertion A special case of insertion that you need to watch out for

arises when the tree in which you are inserting a node is an empty tree.

You must treat it as a special case because when p equals null, the second pointer (trail) trailing p will also be null, and any reference to info of trail like trail->info will be illegal.

You can check for an empty tree by determining if trail is equal to null. If that is so, we can initialize root to point to the new node.

Page 216: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

216

Code Implementation For Insertion Into a Tree

The C function for insertion into a binary tree takes two parameters; one is the pointer to the root node (root), and the other is the value to be inserted (x).

You will implement this algorithm by allocating the nodes dynamically and by linking them using pointer variables. The following is the code implementation of the insert algorithm.

Page 217: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

217

Code Implementation For Insertion Into a Tree

tree insert(tree *s, int x)

{

tree *trail, *p, *q;

q = (struct tree *) malloc (sizeof(tree));

q->info = x;

q->left = null;

q->right = null;

p = s;

trail = null;

Page 218: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

218

Code Implementation For Insertion Into a Tree

while (p != null) { trail = p; if (x < p->info) p = p->left; else

p = p->right;

}

Page 219: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

219

Code Implementation For Insertion Into a Tree

/*insertion into an empty tree; a special case of insertion */if (trail == null) { s = q; return (s); }if(x < trail->info) trail->left = q;else trail->right = q;return (s);}

Page 220: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

220

Code Implementation For Insertion Into a Tree Using Recursion

You have seen that to insert a node, you must compare x with root->info.

If x is less than root->info, then x must be inserted into the left subtree.

Otherwise, x must be inserted into the right subtree.

This description suggests a recursive method where you compare the new value (x) with the one in the root and you use exactly the same insertion method either on the left subtree or on the right subtree.

Page 221: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

221

Code Implementation For Insertion Into a Tree Using Recursion

The base case is inserting a node into an empty tree.

You can write a recursive routine (rinsert) to insert a node recursively as follows:

tree rinsert (tree *s, int x)

{

/* insertion into an empty tree; a special case of insertion */

if (!s) {

s=(struct tree*) malloc (sizeof(struct tree));

Page 222: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

222

Code Implementation For Insertion Into a Tree Using Recursion

s->info = x; s ->left = null; s->right = null; return (s); } if (x < s->info)

s->left = rinsert(x, s->left); else if (x > s->info)

s->right = rinsert(x, s->right);return (s);}

Page 223: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

223

Circumstances When a Binary Tree Degenerates Into a Linked List

The shape of a binary tree is determined by the order in which the nodes are inserted.

Given the following input, their insertion into the tree in the same order would more or less produce a balanced binary search tree as shown below:

Input values: 10, 15, 12, 7, 8, 18, 6, 20

Page 224: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

224

Circumstances When a Binary Tree Degenerates Into a Linked List

10

15

12

7

8 186

20

Root

Page 225: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

225

Circumstances When a Binary Tree Degenerates Into a Linked List

If the same input is given in the sorted order as

6, 7, 8, 10, 12, 15, 18, 20, you will construct a lopsided tree with only right subtrees starting from the root.

Such a tree will be conspicuous by the absence of its left subtree from the top.

Page 226: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

226

Circumstances When a Binary Tree Degenerates Into a Linked List

A Lopsided Binary Tree With Only Right Subtrees

6

7

8

10

12

15

18

20

Page 227: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

227

Circumstances When a Binary Tree Degenerates Into a Linked List However if you reverse the input as

20, 18, 15, 12, 10, 8, 7, 6, and insert them into a tree in the same sequence, you will construct a lopsided tree with only the left subtrees starting from the root.

Such a tree will be conspicuous by the absence of its right subtree from the top.

Page 228: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

228

Circumstances When a Binary Tree Degenerates Into a Linked List

A Lopsided Binary Tree With Only Left Subtrees

20

18

15

12

10

8

7

6

Page 229: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

229

Deletion from a Binary Search Tree

An important function for maintaining a binary search tree is to delete a specific node from the tree.

The method to delete a node depends on the specific position of the node in the tree.

The algorithm to delete a node can be subdivided into different cases.

Page 230: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

230

Case I – Deletion Of The Leaf Node If the node to be deleted is a leaf, you only

need to set appropriate link of its parent to null, and do away with the node that is to be deleted.

For example, to delete a node containing 1 in the following figure, we have to set the left pointer of its parent (pointing to 1) to null.

The following diagram illustrates this.

Page 231: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

231

Case I – Deletion Of The Leaf Node

2

p

2

null 331

Page 232: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

232

Case II – Deletion Of a Node With a Single Child If the node to be deleted has only one child, you cannot

simply make the link of the parent to nil as you did in the case of a leaf node.

Because if you do so, you will lose all of the descendants of the node that you are deleting from the tree.

So, you need to adjust the link from the parent of deleted node to point to the child of the node you intend to delete. You can subsequently dispose of the deleted node.

Page 233: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

233

Case II – Deletion Of a Node With a Single Child

Node to be deleted

5

43

2

Node to be deleted

5

43

2

To delete node containing the value 3, where the right subtree of 3 is empty, we simply make the link of the parent of the node with the value 3 (node with value 5) point to the child of 3 (node with the value 2).

Page 234: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

234

Case III – Deletion Of a Node With Two Child Nodes

Complications arise when you have to delete a node with two children.

There is no way you can make the parent of the deleted node to point to both of the children of the deleted node.

So, you attach one of the subtrees of the node to be deleted to the parent, and then link the other subtree onto the appropriate node of the first subtree.

Page 235: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

235

Case III – Deletion Of a Node With Two Child Nodes

You can attach the right subtree to the parent node and then link the left subtree on to the appropriate node of the right subtree.

Therefore, you must attach the left subtree as far to the left as possible. This proper place can be found by going left until an empty left subtree is found.

For example, if you delete the node containing x as shown in the following figure, you make the parent of x (node with the value r) point to the right subtree of x (node containing y) and then go as far left as possible (to the left of the node containing y) and attach the left subtree there.

Page 236: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

236

Case III – Deletion Of a Node With Two Child Nodes

y

Delete node x

r

q x

t

s uz

Before Deletion of Node x

r

q

t

y

s u

z

After Deletion of Node x

Page 237: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

237

Code Implementation for Node Deletionfor Cases I, II & III

void delete (Struct tree *p) {

struct tree *temp if (p == null) printf(“Trying to delete a non-existent node”); else if (p->left == null) {

temp = p; p = p->right; free(temp);

} else if (p->right == null) {

temp = p; p = p->left; free (temp);

}

Page 238: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

238

Code Implementation for Node Deletionfor Cases I, II & III

else if(p->left != null && p->right!= null){

temp = p->right; while (temp->left != null) { temp = temp->left; }

temp->left = p->left; temp = p; p = p->right; free (Temp); } }

Page 239: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

239

Code Implementation for Node Deletionfor Cases I, II & III

Note that the while loop stops when it finds a node with an empty left subtree so that the left subtree of the node to be deleted can be attached here.

Also, note that you first attach the left subtree at the proper place and then attach the right subtree to the parent node of the node to be deleted.

Page 240: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

240

Search The Tree

To search a tree, you employ a traversal pointer p, and set it equal to the root of the tree.

Then you compare the information field of p with the given value x. If the information is equal to x, you exit the routine and return the current value of p.

If x is less than p->info, you search in the left subtree of p.

Otherwise, you search in the right subtree of p by making p equal to p->right.

Page 241: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

241

Search the Tree You continue searching until you have found the desired value

or reach the end of the tree. You can write the code implementation for a tree search as follows:

search (struct tree *p; int x) { p = root; while (p != null && p->info != x) {

if (p->info > x) p = p->left; else p = p->right; } return (p); }

Page 242: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

242

threaded binary tree A binary tree is threaded by making all right child pointers that would

normally be null point to the inorder successor of the node, and all left child pointers that would normally be null point to the inorder predecessor of the node."

A threaded binary tree makes it possible to traverse the values in the binary tree via a linear traversal that is more rapid than a recursive in-order traversal.

It is also possible to discover the parent of a node from a threaded binary tree, without explicit use of parent pointers or a stack, albeit slowly.

This can be useful where stack space is limited, or where a stack of parent pointers is unavailable.

Page 243: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

243

struct TBTNODE{

 struct NODE *leftchild; int node_value; struct NODE *rightchild; struct NODE *thread;

};

struct thtree{int data;enum boolean left;struct thtree *leftchild;struct thtree *rightchild;enum boolean right;

};

Example : threadbt_cp.c

Page 244: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

244

Summary

In this session, you learnt to: Define a binary tree Describe the terminologies associated with a binary tree Use a dynamic allocated data structure to represent a

binary tree Traverse a binary tree Add nodes to a binary tree Remove nodes from a binary tree Search a binary tree

Page 245: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

245

Page 246: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

246

Sorting

Page 247: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

247

Sorting algorithms used in computer science are often classified by: Computational complexity (worst, average and best behaviour) of

element comparisons in terms of the size of the list.

For typical sorting algorithms good behavior is O(n log n) and bad behavior is (Omega(n^2)) Ideal behavior for a sort is O(n) .

Computational complexity of swaps (for "in place" algorithms).

Memory usage (and use of other computer resources). In particular, some sorting algorithms are "in place", such that only O(1) or (O( log n)) memory is needed beyond the items being sorted, while others need to create auxiliary locations for data to be temporarily stored.

Page 248: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

248

Recursion. Some algorithms are either recursive or non recursive, while others may be both (e.g., merge sort).

Stability: stable sorting algorithms maintain the relative order of records with equal keys (i.e., values).

Whether or not they are a comparison sort. A comparison sort examines the data only by comparing two elements with a comparison operator.

General method: insertion, exchange, selection, merging, etc. Exchange sorts include bubble sort and quicksort. Selection sorts include shaker sort and heapsort.

Page 249: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

249

Exchange sorts - Bubble sort

If N elements are given in memory then for sorting we do following steps-

First compare the 1st and 2nd element of array if 1st < 2nd then compare the 2nd with 3rd

If 2nd > 3rd then interchange the value of 2nd and 3rd

Now compare the value of 3rd (which has the value of 2nd ) with 4th .

Similarly compare until the N-1th element is compared with Nth element.

Now the highest value element is reached at the Nth place.

Now elements will be compared until N-1 elements.

Page 250: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

250

Time complexity This requires to perform (n−1) passes.

In the first pass we have (n−1) pairs, in the second pass we have (n−2) pairs, and in the last (or (n−1)th) pass, we have only one pair.

Therefore, the number of probes or comparisons that are required to be carried out is

(n-1)+(n-2)+(n-3)+ … +1 n*(n-1) / 2

and the order of the algorithm is O(n2).

Page 251: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

251

Void bubbleSort(int num[]){

for(i=0;i<5-1;i++)for(j=0;j<5-(i+1);j++) {

if(num[j]>num[j+1]) {temp=num[j];num[j]=num[j+1];num[j+1]=temp;

}}for(i=0;i<5;i++)

printf("%d\t",num[i]); }}

Page 252: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

252

Quick Sort The idea behind sorting is much easier in two lists than one

long list.

Take the first element of list as pivot.

Place pivot at the proper place in list. So one element of the list i.e, pivot will be at its proper place.

Create two sublists left and right side of pivot.

Repeat the same process until all elements of list are at proper position in list.

Page 253: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

253

The average case-time complexity of the quick sort algorithm can be determined as follows: We assume that every time this is done, the list gets split into two approximately

equal-sized sublists.

If the size of a given list is n, it gets split into two sublists of size approximately n/2.

Each of these sublists gets further split into two sublists of size n/4, and this is continued until the size equals 1.

When the quick sort works with a list of size n, it places the key element in its proper position in the list.

This requires no more than n iterations.

After placing the key element in its proper position in the list of size n, quick sort activates itself twice to work with the left and right sublists, each assumed to be of size n/2. Therefore T(n) is the time required to sort a list of size n.

Page 254: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

254

Since the time required to sort the list of size n is equal to the sum of the time required to place the key element in its proper position in the list of size n, and the time required to sort the left and right sublists, each assumed to be of size T(n/2).

T(n) turns out to be:

∴ T(n) = c*n + 2*T(n/2)

where c is a constant and T(n/2) is the time required to sort the list of size n/2.

Page 255: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

255

Similarly, the time required to sort a list of size n/2 is equal to the sum of the time required to place the key element in its proper position in the list of size n/2 and the time required to sort the left and right sublists each assumed to be of size n/4.

T(n/2) turns out to be: T(n/2) = c*n/2 + 2*T(n/4)

where T(n/4) is the time required to sort the list of size n/4. ∴ T(n/4) = c*n/4 + 2*T(n/8), and so on. We eventually we get T(1) = 1. ∴ T(n) = c*n + 2(c*n(n/2) + 2T(n/4)) ∴ T(n) = c*n + c*n + 4T(n/4)) = 2*c*n + 4T(n/4) = 2*c*n + 4(c*(n/4) +

2T(n/8)) ∴ T(n) = 2*c*n + c*n + 8T(n/8) = 3*c*n + 8T(n/8) ∴ T(n) = (log n)*c*n + n T(n/n)= (log n)*c*n + n T(1) = n + n*(log n) *c

∴ T(n) μ n log(n)

Page 256: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

256

To place the pivot at proper place, follow the steps

Compare the pivot element one by one from right to left for getting the element which has value less than pivot element.

Interchange the element with pivot element.

Now the comparison will start from the interchanged element position from left to right for getting the element which has higher value than pivot.

Repeat the same process until pivot is at it’s proper position.

Page 257: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

257

Example for Quick sort :

Microsoft Word Document

Page 258: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

258

Insertion sorts

Simple Insertion sort

Shell sort

Page 259: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

259

Insertion sort

Efficient on (quite) small data sets

Efficient on data sets which are already substantially sorted: it runs in O(n + d) time, where d is the number of inversions

More efficient in practice than most other simple O(n2) algorithms such as selection sort or bubble sort the average time is n2/4 and it is linear in the best case

Stable (does not change the relative order of elements with equal keys)

In-place (only requires a constant amount O(1) of extra memory space)

Page 260: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

260

Insertion sort

In abstract terms, every iteration of an insertion sort removes an element from the input data, inserting it at the correct position in the already sorted list, until no elements are left in the input.

Sorting is typically done in-place. The resulting array after k iterations contains the first k entries of the input array and is sorted.

In each step, the first remaining entry of the input is removed, inserted into the result at the right position, thus extending the result:

Microsoft Word Document

Page 261: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

261

Shell sort The original implementation performs O(n2) comparisons and exchanges in the

worst case.

Shell sort improves insertion sort by comparing elements separated by a gap of several positions.

This lets an element take "bigger steps" toward its expected position. Multiple passes over the data are taken with smaller and smaller gap sizes.

The last step of Shell sort is a plain insertion sort, but by then, the array of data is guaranteed to be almost sorted.

Consider a small value that is initially stored in the wrong end of the array. Using an O(n2) sort such as bubble sort or insertion sort, it will take roughly n comparisons and exchanges to move this value all the way to the other end of the array. Shell sort first moves values using giant step sizes, so a small value will move a long way towards its final position, with just a few comparisons and exchanges.

Page 262: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

262

One can visualize Shellsort in the following way: arrange the list into a table and sort the columns (using an insertion sort).

Repeat this process, each time with smaller number of longer columns. At the end, the table has only one column. While transforming the list into a table makes it easier to visualize, the algorithm itself does its sorting in-place (by incrementing the index by the step size,

For example, consider a list of numbers like [ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ].

If we started with a step-size of 5, we could visualize this as breaking the list of numbers into a table with 5 columns. This would look like this:

Page 263: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

263

13 14 94 33 82 25 59 94 65 23 45 27 73 25 3910 We then sort each column, which gives us

10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45

When read back as a single list of numbers, we get [ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].

Here, the 10 which was all the way at the end, has moved all the way to the beginning.

This list is then again sorted using a 3-gap sort, and then 1-gap sort (simple insertion sort).

Page 264: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

264

void shell_sort(int A[], int size) {

int i, j, increment, temp; increment = size / 2; while (increment > 0) {

for (i = increment; i < size; i++) { j = i; temp = A[i]; while ((j >= increment) && (A[j-increment] > temp)) {

A[j] = A[j - increment]; j = j - increment; } A[j] = temp;

} if (increment == 2) increment = 1; else increment = (int) (increment / 2.2);

} }

Page 265: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

265

Page 266: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

266

Merge sort

Merge sort

Radix sort

Page 267: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

267

Merge Sort

If there are two sorted lists of array then process of combining these sorted lists into sorted order is called merging

Ther are Two approaches - First approach

Take the first array, after that take second array and sort them with any sorting.

But it is not useful because both the lists are sorted and we are taking them as unsorted list.

Page 268: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

268

Merge Sort

The second approach is to take one element of each array, compare them and then take the smaller one in third array.

Repeat this process until the elements of any array are finished. Then take the remaining elements of unfinished array in third array.

Microsoft Word Document

Page 269: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

269

we start by viewing it to be n lists each of size 1, and merge the first list with the second list to form a single sorted list of size 2.

Similarly, we merge the third and the fourth lists to form a second single sorted list of size 2, and so on. This completes one pass.

We then consider the first sorted list of size 2 and the second sorted list of size 2, and merge them to form a single sorted list of size 4.

Similarly, we merge the third and the fourth sorted lists, each of size 2, to form the second single sorted list of size 4, and so on. This completes the second pass.

In the third pass, we merge these adjacent sorted lists, each of size 4, to form sorted lists of size 8. We continue this process until we finally obtain a single sorted list of size n.

Page 270: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

270

Page 271: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

271

Time complexity The merging of two sublists, the first running from the index 0 to m,

and the second running from the index (m + 1) to (n − 1) requires no more than (n−l + 1) iterations.

So if l =1, then no more than n iterations are required, where n is the size of the list to be sorted.

Therefore, if n is the size of the list to be sorted, every pass that a merge routine performs requires a time proportional to O(n), since the number of passes required to be performed is log2n.

The time complexity of the algorithm is O(n log2(n)), for both average-case and worst-case. The merge sort requires an additional list of size n.

Page 272: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

272

Radix sort In computer science, radix sort is a sorting algorithm that sorts

integers by processing individual digits. Because integers can represent strings of characters (e.g., names

or dates) and specially formatted floating point numbers, radix sort is not limited to integers.

Two classifications of radix sorts are least significant digit (LSD) radix sorts and most significant digit (MSD) radix sorts.

LSD radix sorts process the integer representations starting from the least significant digit and move towards the most significant digit.

MSD radix sorts work the other way around.

Page 273: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

273

Original, unsorted list: 170, 45, 75, 90, 2, 24, 802, 66

Sorting by least significant digit (1s place) gives: 170, 90, 2, 802, 24, 45, 75, 66

Sorting by next digit (10s place) gives: 2, 802, 24, 45, 66, 170, 75, 90

Sorting by most significant digit (100s place) gives: 2, 24, 45, 66, 75, 90, 170, 802

It is important to realize that each of the above steps requires just a single pass over the data, since each item can be placed in its correct bucket without having to be compared with other items.

Page 274: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

274

Page 275: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

275

Selection and tree sorting

Page 276: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

276

Selection sort

Selection sort is the selection of an element and keeping it in sorted order.

Take the smallest element and keep in the new list,

after that second smallest element and so on until the largest element of the list.

Microsoft Word Document

Page 277: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

277

Heap sort Heapsort is a sorting technique that sorts a contiguous list of

length n with O(n log2 (n)) comparisons and movement of entries, even in the worst case.

Hence it achieves the worst-case bounds better than those of quick sort, and for the contiguous list, it is better than merge sort, since it needs only a small and constant amount of space apart from the list being sorted.

Heapsort proceeds in two phases. First, all the entries in the list are arranged to satisfy the heap property, and then the top of the heap is removed and another entry is promoted to take its place repeatedly.

Page 278: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

278

Therefore, we need a function that builds an initial heap to arrange all the entries in the list to satisfy the heap property.

The function that builds an initial heap uses a function that adjusts the ith entry in the list, whose entries at 2i and 2i + 1 positions already satisfy the heap property in such a manner that the entry at the ith position in the list will also satisfy the heap property.

Microsoft Word Document

Page 279: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

279

Searching

Page 280: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

280

Sequential searching Sequential searching is nothing but searching an element in linear way.

This can be in array or in linked list.

We have a need to start the search from beginning and scan the elements one by one until the end of array or linked list.

If search is successful then it will return the location of element, otherwise it will return the failure notification.

Microsoft Word Document

Page 281: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

281

Binary Search

The sequential search situation will be in worst case if the element is at the end of the list. To eliminate this problem we have binary search.

The condition for binary search is the data should be in sorted array.

We compare the element with the middle element of the array. If it is less than the middle element then we search it in the left position of the array and if it is greater than the middle element then search in the right portion of the array.

Now we will take that portion only for search and compare with middle element of that portion. This process will be iteration until we find the element or middle element has no left or right portion to search.

Microsoft Word Document

Page 282: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

282

Page 283: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

283

Page 284: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

284

Page 285: Data Structures UVK

08/20/08Copyright © Vikas karanth,2007 All rights reserved.

285