data structure manual for be students

129
100 LIST OF PROGRAMS DATA STRUCTURE LABORATORY Sub Code : 06CSL37 IA Marks : 25 Hrs / Week : 03 Exam Hours : 03 Total Hrs : 42 Exam Marks : 50 1. Write a C Program to create a sequential file with atleast 5 records, each record having the structure shown below: Name Marks1 Marks2 Marks3 Non-zero positive integer 25 Characters Positive Integer Positive Integer Positive Integer Write necessary functions a. To display all the records in the file. b. To search for a specific record based on the USN. In case the record is not found, suitable message should be displayed. Both the options in this case must be demonstrated. 2. Write and demonstrate the following C functions: a. newStrCpy that does the same job as strcpy b. newStrCat that does the same job as strcat without using any library functions.

Upload: raghu07k

Post on 12-Nov-2014

1.955 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Data Structure Manual for BE students

100

LIST OF PROGRAMS

DATA STRUCTURE LABORATORY

Sub Code : 06CSL37 IA Marks : 25

Hrs / Week : 03 Exam Hours : 03

Total Hrs : 42 Exam Marks : 50

1. Write a C Program to create a sequential file with atleast 5 records, each record having the structure shown below:

Name Marks1 Marks2 Marks3

Non-zero

positive

integer

25

Characters

Positive

Integer

Positive

Integer

Positive

Integer

Write necessary functions

a. To display all the records in the file.

b. To search for a specific record based on the USN. In case the record is not found, suitable message should be displayed. Both the options in this case must be demonstrated.

2. Write and demonstrate the following C functions:

a. newStrCpy that does the same job as strcpy

b. newStrCat that does the same job as strcat without using any library functions.

3. Write a C Program, which accepts the Internet Protocol (IP) address in decimal dot format (ex. 153.18.8.105) and converts it into 32-bit long integer (ex. 2568095849) using strtok library function and unions.

Page 2: Data Structure Manual for BE students

100

4. Write a C Program to construct a stack of integers and to perform the following operations on it:

a. Push

b. Pop

c. Display

The program should print appropriate messages for stack overflow, stack underflow, and stack empty.

5. Write a C Program to convert and print a given valid parenthesized infix arithmetic expression to postfix expression. The expression consists of single character operands and the binary operators + (plus), - (minus), * (multiply) and / (divide).

6. Write a C Program to evaluate a valid suffix/postfix expression using stack. Assume that the suffix/postfix expression is read as a single line consisting of non-negative single digit operands and binary arithmetic operators. The arithmetic operators are + (add), - (subtract), * (multiply) and / (divide).

7. Write a C Program to simulate the working of a queue of integers using an array. Provide the following operations:

a. Insert

b. Delete

c. Display

8. Write a C Program to simulate the working of a circular queue of integers using an array. Provide the following operations:

a. Insert

b. Delete

c. Display

9. Write a C Program using dynamic variables and pointers, to construct a singly linked list consisting of the following information in each node: student id (integer), student name (character string) and semester (integer). The operations to be supported are:

Page 3: Data Structure Manual for BE students

100

a. The insertion operation

i. At the front of a list

ii. At the back of the list

iii. At any position in the list

b. Deleting a node based on student id. If the specified node is not present in the list an error message should be displayed. Both the options should be demonstrated.

c. Searching a node based on student id and update the information content. If the specified node is not present in the list an error message should be displayed. Both situations should be displayed.

d. Displaying all the nodes in the list. (Note: Only one set of operations among a, b and c with d may be asked in the examination).

10. Write a C Program using dynamic variables and pointers to construct a stack of integers using singly linked list and to perform the following operations:

a. Push

b. Pop

c. Display

The program should print appropriate messages for stack overflow and stack empty.

11. Write a C program using dynamic variables and pointers to construct a queue of integers using singly linked list and to perform the following operations:

a. Insert

b. Delete

c. Display

The program should print appropriate messages for queue full and queue empty.

12. Write a C Program to support the following operations on a doubly linked list where each node consists of integers:

a. Create a doubly linked list by adding each node at the front.

Page 4: Data Structure Manual for BE students

100

b. Insert a new node to the left of the node whose key value is read as an input

c. Delete the node of a given data, if it is found, otherwise display appropriate message.

d. Display the contents of the list.

(Note: Only either (a,b and d) or (a, c and d) may be asked in the examination).

13. Write a C Program

a. To construct a binary search tree of integers.

b. To traverse the tree using all the methods i.e., inorder, preorder and postorder.

c. To display the elements in the tree.

14. Write recursive C Programs for

a. Searching an element on a given list of integers using the Binary Search method.

b. Solving the Towers of Hanoi problem.

Note: In the examination each student picks one question from a lot of all 14 questions.

Introduction

In computer science, a data structure is a particular way of storing and organizing data in a computer so that it can be used efficiently.

Page 5: Data Structure Manual for BE students

100

Different kinds of data structures are suited to different kinds of applications, and some are highly specialized to certain tasks. For example, B-trees are particularly well-suited for implementation of databases, while compiler implementations usually use hash tables to look up identifiers.

Data structures are used in almost every program or software system. Specific data structures are essential ingredients of many efficient algorithms, and make possible the management of huge amounts of data, such as large databases and internet indexing services. Some formal design methods and programming languages emphasize data structures, rather than algorithms, as the key organizing factor in software design.

Basic principles

Data structures are generally based on the ability of a computer to fetch and store data at any place in its memory, specified by an address — a bit string that can be itself stored in memory and manipulated by the program. Thus the record and array data structures are based on computing the addresses of data items with arithmetic operations; while the linked data structures are based on storing addresses of data items within the structure itself. Many data structures use both principles

Language support

Assembly languages and some low-level languages such as BCPL generally lack support for data structures. Many high-level programming languages, on the other hand, have special syntax or other built-in support for certain data structures, such as vectors (one-dimensional arrays) in the C programming language, multi-dimensional arrays in Pascal, linked lists in Common Lisp, and hash tables in Perl. Many languages also provide basic facilities such as references and the definition record data types, that programmers can use to build arbitrarily complex structures.

Most programming languages feature some sort of library mechanism that allows data structure implementations to be reused by different programs. Modern programming languages usually come with standard libraries that implement the most common data structures. Examples are the C++ Standard Template Library, the Java Collections Framework, and Microsoft's .NET Framework.

Modern languages also generally support modular programming, the separation between the interface of a library module and its implementation. Some provide opaque data types that allow clients to hide implementation details from client programs. Object-oriented programming languages, such as C++ and Java, use classes for this purpose.

Before We begin to the Data Structures lets see Some Basic Concepts.

1. INTRODUCTION TO STRUCTURES:

A data structure is a group of data elements grouped together under one name. These data elements, known as

members, can have different types and different lengths

Page 6: Data Structure Manual for BE students

100

The first thing we have to know is that a data structure creates a new type: Once a data structure is

declared, a new type with the identifier specified as structure_name is created and can be used in the

rest of the program as if it was any other type. For example:

struct product {

int weight;

float price;

} ;

product apple;

product banana, melon;

We have first declared a structure type called product with two members: weight and price, each of a

different fundamental type. We have then used this name of the structure type (product) to declare

three objects of that type: apple, banana and melon as we would have done with any fundamental data

type.

Once declared, product has become a new valid type name like the fundamental ones int, char or short

and from that point on we are able to declare objects (variables) of this compound new type, like we

have done with apple, banana and melon.

Right at the end of the struct declaration, and before the ending semicolon, we can use the optional

field object_name to directly declare objects of the structure type. For example, we can also declare the

structure objects apple, banana and melon at the moment we define the data structure type this way:

struct product {

int weight;

float price;

} apple, banana, melon;

Page 7: Data Structure Manual for BE students

100

It is important to clearly differentiate between what is the structure type name, and what is an object

(variable) that has this structure type. We can instantiate many objects (i.e. variables, like apple,

banana and melon) from a single structure type (product).

Once we have declared our three objects of a determined structure type (apple, banana and melon) we

can operate directly with their members. To do that we use a dot (.) inserted between the object name

and the member name. For example, we could operate with any of these elements as if they were

standard variables of their respective types:

apple.weight

apple.price

banana.weight

banana.price

melon.weight

melon.price

Each one of these has the data type corresponding to the member they refer to: apple.weight,

banana.weight and melon.weight are of type int, while apple.price, banana.price and melon.price are of type

float.

2. A BRIEF NOTE ON STRINGS:

A string is an array of characters. Strings must have a 0 or null character after the last character to

show where the string ends. The null character is not included in the string.

There are 2 ways of using strings. The first is with a character array and the second is with a string

pointer.A character array is declared in the same way as a normal array.

char ca[10];

You must set the value of each individual element of the array to the character you want and you

must make the last character a 0. Remember to use %s when printing the string.

char ca[10];

ca[0] = 'H';

ca[1] = 'e';

ca[2] = 'l';

Page 8: Data Structure Manual for BE students

100

ca[3] = 'l';

ca[4] = 'o';

ca[5] = 0;

printf("%s",ca);

String handling functions

The strings.h header file has some useful functions for working with strings. Here are some of the

functions you will use most often:

strcpy(destination,source)

You can't just use string1 = string2 in C. You have to use the strcpy function to copy one string to

another. strcat copies the source string to the destination string.

s1 = "abc";

s2 = "xyz";

strcpy(s1,s2); // s1 = "xyz"

strcat(destination,source)

Joins the destination and source strings and puts the joined string into the destination string.

s1 = "abc";

s2 = "xyz";

strcat(s1,s2); // s1 = "abcxyz"

3. NOTE ON Strtok function:

It's fairly common for programs to have a need to do some simple kinds of lexical analysis and

parsing, such as splitting a command string up into tokens. You can do this with the strtok function,

declared in the header file `string.h'.

Function: char * strtok (char *newstring, const char *delimiters)

A string can be split into tokens by making a series of calls to the function strtok.

The string to be split up is passed as the newstring argument on the first call only. The strtok function uses this

to set up some internal state information. Subsequent calls to get additional tokens from the same string are

indicated by passing a null pointer as the newstring argument. Calling strtok with another non-null newstring

Page 9: Data Structure Manual for BE students

100

argument reinitializes the state information. It is guaranteed that no other library function ever calls strtok

behind your back (which would mess up this internal state information).

The delimiters argument is a string that specifies a set of delimiters that may surround the token being

extracted. All the initial characters that are members of this set are discarded. The first character that is not a

member of this set of delimiters marks the beginning of the next token. The end of the token is found by

looking for the next character that is a member of the delimiter set. This character in the original string

newstring is overwritten by a null character, and the pointer to the beginning of the token in newstring is

returned.

On the next call to strtok, the searching begins at the next character beyond the one that marked the end of the

previous token. Note that the set of delimiters delimiters do not have to be the same on every call in a series of

calls to strtok.

If the end of the string newstring is reached, or if the remainder of string consists only of delimiter characters,

strtok returns a null pointer.

Warning: Since strtok alters the string it is parsing, you always copy the string to a temporary buffer before

parsing it with strtok. If you allow strtok to modify a string that came from another part of your program, you

are asking for trouble; that string may be part of a data structure that could be used for other purposes during

the parsing, when alteration by strtok makes the data structure temporarily inaccurate.

The string that you are operating on might even be a constant. Then when strtok tries to modify it, your

program will get a fatal signal for writing in read-only memory. See section Program Error Signals.

This is a special case of a general principle: if a part of a program does not have as its purpose the

modification of a certain data structure, then it is error-prone to modify the data structure temporarily.

The function strtok is not reentrant. See section Signal Handling and Nonreentrant Functions, for a discussion

of where and why reentrancy is important.

Here is a simple example showing the use of strtok.

#include <string.h>

#include <stddef.h>

Page 10: Data Structure Manual for BE students

100

...

char string[] = "words separated by spaces -- and, punctuation!";

const char delimiters[] = " .,;:!-";

char *token;

...

token = strtok (string, delimiters); /* token => "words" */

token = strtok (NULL, delimiters); /* token => "separated" */

token = strtok (NULL, delimiters); /* token => "by" */

token = strtok (NULL, delimiters); /* token => "spaces" */

token = strtok (NULL, delimiters); /* token => "and" */

token = strtok (NULL, delimiters); /* token => "punctuation" */

token = strtok (NULL, delimiters); /* token => NULL */

4. ABSTRACT IDEA OF A STACK:

The stack is a very common data structure used in programs. By data structure, we mean something

that is meant to hold data and provides certain operations on that data.

One way to describe how a stack data structure behaves is to look at a physical analogy, a stack of

books... Now, a minimal set of things that we might do with the stack are the following:

Page 11: Data Structure Manual for BE students

100

We'll consider other, more complex operations to be inappropriate for our stack. For example,

pulling out the 3rd book from the top cannot be done directly because the stack might fall over.

How might you get the 3rd book from the top using only the simple operations?

Abstraction

Now, let's think about a stack in an abstract way. I.e., it doesn't hold any particular kind of thing (like

books) and we aren't restricting ourselves to any particular programming language or any particular

implementation of a stack.

Stacks hold objects, usually all of the same type. Most stacks support just the simple set of

operations we introduced above; and thus, the main property of a stack is that objects go on and

come off of the top of the stack.

Here are the minimal operations we'd need for an abstract stack (and their typical names):

o Push: Places an object on the top of the stack.

o Pop: Removes an object from the top of the stack and produces that object.

o IsEmpty: Reports whether the stack is empty or not.

Because we think of stacks in terms of the physical analogy, we usually draw them vertically (so the

top is really on top).

2. Order produced by a stack:

Place a book

on the top...

Take one off

the top...

See if the stack

is empty...

NOT Empty, there are

books on the stack!

Page 12: Data Structure Manual for BE students

100

Stacks are linear data structures. This means that their contexts are stored in what looks like a line

(although vertically). This linear property, however, is not sufficient to discriminate a stack from

other linear data structures. For example, an array is a sort of linear data structure. However, you can

access any element in an array--not true for a stack, since you can only deal with the element at its

top.

One of the distinguishing characteristics of a stack, and the thing that makes it useful, is the order in

which elements come out of a stack. Let's see what order that is by looking at a stack of letters...

Suppose we have a stack that can hold letters, call it stack. What would a particular sequence of Push

and Pops do to this stack?

We begin with stack empty:

-----

stack

Now, let's perform Push(stack, A), giving:

-----

| A | <-- top

-----

stack

Again, another push operation, Push(stack, B), giving:

-----

| B | <-- top

-----

| A |

-----

stack

Now let's remove an item, letter = Pop(stack), giving:

Page 13: Data Structure Manual for BE students

100

----- -----

| A | <-- top | B |

----- -----

stack letter

And finally, one more addition, Push(stack, C), giving:

-----

| C | <-- top

-----

| A |

-----

stack

You'll notice that the stack enforces a certain order to the use of its contents, i.e., the Last thing In is

the First thing Out. Thus, we say that a stack enforces LIFO order.

Now we can see one of the uses of a stack...To reverse the order of a set of objects.

Implementing a stack with an array:

Let's think about how to implement this stack in the C programming language.

First, if we want to store letters, we can use type char. Next, since a stack usually holds a bunch of

items with the same type (e.g., char), we can use an array to hold the contents of the stack.

Now, consider how we'll use this array of characters, call it contents, to hold the contents of the stack.

At some point we'll have to decide how big this array is; keep in mind that a normal array has a fixed

size.

Let's choose the array to be of size 4 for now. So, an array getting A, then B, will look like:

-----------------

| A | B | | |

-----------------

0 1 2 3

contents

Is this array sufficient, or will we need to store more information concerning the stack?

Page 14: Data Structure Manual for BE students

100

Answer: We need to keep track of the top of the stack since not all of the array holds stack elements.

What type of thing will we use to keep track of the top of the stack?

Answer: One choice is to use an integer, top, which will hold the array index of the element at the

top of the stack.

Example:

Again suppose the stack has (A,B) in it already...

stack (made up of 'contents' and 'top')

----------------- -----

| A | B | | | | 1 |

----------------- -----

0 1 2 3 top

contents

Since B is at the top of the stack, the value top stores the index of B in the array (i.e., 1).

Now, suppose we push something on the stack, Push(stack, 'C'), giving:

stack (made up of 'contents' and 'top')

----------------- -----

| A | B | C | | | 2 |

----------------- -----

0 1 2 3 top

contents

(Note that both the contents and top part have to change.)

So, a sequence of pops produce the following effects:

letter = Pop(stack)

stack (made up of 'contents' and 'top')

----------------- ----- -----

| A | B | | | | 1 | | C |

Page 15: Data Structure Manual for BE students

100

----------------- ----- -----

0 1 2 3 top letter

contents

letter = Pop(stack)

stack (made up of 'contents' and 'top')

----------------- ----- -----

| A | | | | | 0 | | B |

----------------- ----- -----

0 1 2 3 top letter

contents

letter = Pop(stack)

stack (made up of 'contents' and 'top')

----------------- ----- -----

| | | | | | -1| | A |

----------------- ----- -----

0 1 2 3 top letter

contents

so that you can see what value top should have when it is empty, i.e., -1.

5. ALGEBRAIC EXPRESSIONS, AN INTRODUCTION:

An algebraic expression is a legal combination of operands and operators. Operand is the quantity (unit of

data) on which a mathematical operation is performed. Operand may be a variable like x, y, z or a constant

like 5, 4,0,9,1 etc. Operator is a symbol which signifies a mathematical or logical operation between the

operands. Example of familiar operators include +,-,*, /, ^ ( throughout the tutorial '^' will be referred to as

Exponential Operator ) etc.

Considering these definitions of operands and operators now we can write an example of expression as x+y*z.

Note the phrase "LEGAL combination" in the definition of an Algebraic Expression, in aforementioned

example of expression x+y*z, the operands x , y, z and the operators +,* form some legal combination. Take

Page 16: Data Structure Manual for BE students

100

another example +xyz*, in this expression operators and operands do not make any LEGAL combination; this

expression is not a valid algebraic expression.

An Algebraic Expression can be represented using three different notations:

INFIX: From our school times we have been familiar with the expressions in which operands surround the

operator, e.g. x+y, 6*3 etc this way of writing the Expressions is called infix notation.

PREFIX: Prefix notation also Known as Polish notation, is a symbolic logic invented by Polish

mathematician Jan Lukasiewicz in the 1920's. In the prefix notation, as the name only suggests, operator

comes before the operands, e.g. +xy, *+xyz etc.

POSTFIX: Postfix notation is also Known as Reverse Polish notation. They are different from the infix and

prefix notations in the sense that in the postfix notation, the operator comes after the operands, e.g. xy+,

xyz+* etc.

Now, the obvious question that comes in our mind is, Why use these weird looking PREFIX and POSTFIX

notations when we have a sweet and simple INFIX notation?

To our surprise INFIX notations are not as simple as they seem specially while evaluating them. To evaluate

an infix expression we need to consider Operators' Priority and Associativity.

For example, will expression 3+5*4 evaluate to 32 i.e. (3+5)*4 or to 23 i.e. 3+(5*4). To solve this problem

Precedence or Priority of the operators were defined. Operator precedence governs evaluation order. An

operator with higher precedence is applied before an operator with lower precedence.

Following figure shows operator Precedence in descending order.

Now, as we know the precedence of the operators, we can evaluate the expression 3+5*4 as 23. But wait, it

doesn't end here what about the expression 6/3*2? Will this expression evaluate to 4 i.e. (6/3)*2 or to 1 i.e.

Page 17: Data Structure Manual for BE students

100

6/(3*2).As both * and the / have same priorities, to solve this conflict, we now need to use Associativity of the

operators. Operator Associativity governs the evaluation order of the operators of same priority. For an

operator with left-Associativity, evaluation is from left to right and for an operator with right-Associativity;

evaluation is from right to left.

/, +, - have left Associativity. So the expression will evaluate to 4 and not 1.

N.B: We use Associativity of the operators only to resolve conflict between operators of same priority.

Due to the above mentioned problem of considering operators' Priority and Associativity while evaluating an

expression using infix notation, we use prefix and postfix notations. Both prefix and postfix notations have an

advantage over infix that while evaluating an expression in prefix or postfix form we need not consider the

Priority and Associativity of the operators. E.g. x/y*z becomes */xyz in prefix and xy/z* in postfix. Both

prefix and postfix notations make Expression Evaluation a lot easier. (we will discuss this in detail, later in

this tutorial)

But it is not easy to remember and manually write expressions in prefix or postfix form e.g. which one of

following equations is easy to remember (x+y)/z*a (Infix) or xy+z/a* (Postfix)?

So, what is actually done is that the expression is scanned from the user in infix form; it is converted into

prefix or postfix form and then evaluated without considering the parenthesis and priority of the operators.

Now let us move on the programming part, How to convert an expression from one notation to another? Well

there are two ways to convert expression from one notation to another. First one uses Stack and second

method uses Expression trees.

As there are 3 notations namely prefix, infix and postfix , there are a total of 6 conversions that can be

done ,i.e. infix -> prefix, infix -> postfix, prefix -> infix, prefix -> postfix, postfix -> prefix, postfix -> infix.

For the first 2 conversions we will be using stacks and for remaining 4 conversions we will be using Binary

Expression Trees.

To convert an expression from infix to prefix and postfix, we are going to use stacks. Those who do not know

what a stack is, here are a few words about it. A stack is a special type of data structure in which items are

removed in reverse order from which they are added. Stack follows Last In First Out (LIFO) pattern. Adding

an element to a stack is called PUSH and removing an item from a stack is called POP.

Converting Expression from Infix to Postfix using STACK

To convert an expression from infix to postfix, we are going to use a stack.

Page 18: Data Structure Manual for BE students

100

Algorithm

1) Examine the next element in the input.

2) If it is an operand, output it.

3) If it is opening parenthesis, push it on stack.

4) If it is an operator, then

i) If stack is empty, push operator on stack.

ii) If the top of the stack is opening parenthesis, push operator on stack.

iii) If it has higher priority than the top of stack, push operator on stack.

iv) Else pop the operator from the stack and output it, repeat step 4.

5) If it is a closing parenthesis, pop operators from the stack and output them until an opening parenthesis is

encountered. pop and discard the opening parenthesis.

6) If there is more input go to step 1

7) If there is no more input, unstack the remaining operators to output.

Example

Suppose we want to convert 2*3/(2-1)+5*(4-1) into Prefix form: Reversed Expression: )1-4(*5+)1-2(/3*2

Page 19: Data Structure Manual for BE students

100

Char Scanned Stack Contents(Top on right) Postfix Expression

2 Empty 2

* * 2

3 * 23

/ / 23*

( /( 23*

2 /( 23*2

- /(- 23*2

1 /(- 23*21

) / 23*21-

+ + 23*21-/

5 + 23*21-/5

* +* 23*21-/5

( +*( 23*21-/5

4 +*( 23*21-/54

- +*(- 23*21-/54

1 +*(- 23*21-/541

) +* 23*21-/541-

  Empty 23*21-/541-*+

So, the Postfix Expression is 23*21-/541-*+

Refer program #1 for infix to postfix Conversion

Converting Expression from Infix to Prefix using STACK

Page 20: Data Structure Manual for BE students

100

It is a bit trickier algorithm, in this algorithm we first reverse the input expression so that a+b*c will become

c*b+a and then we do the conversion and then again the output string is reversed. Doing this has an advantage

that except for some minor modifications the algorithm for Infix->Prefix remains almost same as the one for

Infix->Postfix.

Algorithm

1) Reverse the input string.

2) Examine the next element in the input.

3) If it is operand, add it to output string.

4) If it is Closing parenthesis, push it on stack.

5) If it is an operator, then

i) If stack is empty, push operator on stack.

ii) If the top of stack is closing parenthesis, push operator on stack.

iii) If it has same or higher priority than the top of stack, push operator on stack.

iv) Else pop the operator from the stack and add it to output string, repeat step 5.

6) If it is a opening parenthesis, pop operators from stack and add them to output string until a closing

parenthesis is encountered. Pop and discard the closing parenthesis.

7) If there is more input go to step 2

8) If there is no more input, unstack the remaining operators and add them to output string.

9) Reverse the output string.

Example

Suppose we want to convert 2*3/(2-1)+5*(4-1) into Prefix form: Reversed Expression: )1-4(*5+)1-2(/3*2

Page 21: Data Structure Manual for BE students

100

Char Scanned Stack Contents(Top on right) Prefix Expression(right to left)

) )  

1 ) 1

- )- 1

4 )- 14

( Empty 14-

* * 14-

5 * 14-5

+ + 14-5*

) +) 14-5*

1 +) 14-5*1

- +)- 14-5*1

2 +)- 14-5*12

( + 14-5*12-

/ +/ 14-5*12-

3 +/ 14-5*12-3

* +/* 14-5*12-3

2 +/* 14-5*12-32

  Empty 14-5*12-32*/+

Reverse the output string : +/*23-21*5-41 So, the final Prefix Expression is +/*23-21*5-41

Refer program #1 For infix to prefix Conversion.

Page 22: Data Structure Manual for BE students

100

Remaining Conversions

All the remaining conversions can easily be done using a Binary Expressions Tree. In fact the above 2

conversions, viz Infix-> Prefix and Infix -> Postfix, can also be done using Binary Expression Trees but that is

a very tricky thing and stacks can be used to handle the conversions easily. Now we will move a step ahead

and define a Binary Expression Tree.

N.B. A binary expression tree does not contain parenthesis, the reason for this is that for evaluating an

expression using expression tree, structure of tree itself decides order of the operations.

When we run Pre-order traversal (visit root, left child and then right child) on the Binary Expression Tree we

get prefix notation of the expression, similarly an Post-order traversal (visit left child, right child and then

root) will yield postfix notation. What will we get from an in-order Traversal (visit left child, root and then

right child)? Well, for the expressions which do not contain parenthesis, in-order traversal will definitely give

infix notation of expression but expressions whose infix form requires parenthesis to override conventional

precedence of operators can not be retrieved by simple in-order traversal.

Doing the Conversions with Expression Trees

Prefix -> Infix

The following algorithm works for the expressions whose infix form does not require parenthesis to override

conventional precedence of operators. 1) Create the Expression Tree from the prefix expression

2) Run in-order traversal on the tree.

Prefix -> Postfix

1) Create the Expression Tree from the prefix expression

2) Run post-order traversal on the tree.

Well you see how easy it is! Most important point here is to create Expression tree from Prefix expression,

following algorithm does that for you:

Algorithm for creating Expression Tree from a Prefix Expression

Page 23: Data Structure Manual for BE students

100

1) Reverse the prefix expression

2) Examine the next element in the input.

3) If it is operand then

i) create a leaf node i.e. node having no child (node- >left_child=node->right_child=NULL)

ii) copy the operand in data part

iii) PUSH node's address on stack

4) If it is an operator, then

i) create a node

ii) copy the operator in data part

iii) POP address of node from stack and assign it to node->left_child

iv) POP address of node from stack and assign it to node->right_child

v) PUSH node's address on stack

5) If there is more input go to step 2

6) If there is no more input, POP the address from stack, which is the address of the ROOT node of

Expression Tree.

Refer program #2 For prefix to infix and postfix conversion.

Postfix -> Infix

The following algorithm works for the expressions whose infix form does not require parenthesis to override

conventional precedence of operators. 1) Create the Expression Tree from the postfix expression 2) Run in-

order traversal on the tree.

Postfix -> Prefix

1) Create the Expression Tree from the postfix expression 2) Run pre-order traversal on the tree.

Algorithm for creating Expression Tree from a Postfix Expression

1) Examine the next element in the input.

2) If it is operand then

i) create a leaf node i.e. node having no child (node->left_child=node->left_child=NULL)

ii) copy the operand in data part

iii) PUSH node's address on stack

3) If it is an operator, then

i) create a node

ii) copy the operator in data part

Page 24: Data Structure Manual for BE students

100

iii) POP address of node from stack and assign it to node->right_child

iv) POP address of node from stack and assign it to node->left_child

v) PUSH node's address on stack

4) If there is more input go to step 1

5) If there is no more input, POP the address from stack, which is the address of the ROOT node of

Expression Tree.

Refer program #2 For postfix to infix and prefix conversion.

Well, at last we are done with converting the expressions from one type to another. As a summary here is

what we have done so far : 1) Infix -> Prefix using stack

2) Infix -> Postfix using stack

3) Prefix -> Infix using Expression Trees

4) Prefix -> Postfix using Expression Trees

5) Postfix -> Infix using Expression Trees

6) Postfix -> Prefix using Expression Trees

Now all we are left with is Evaluating an Expression. Evaluating an expression involves two phases: 1) Create

an expression tree for given expression

2) Evaluate the tree recursively

We already know how to create an expression tree for prefix and postfix notations. Algorithm for creating

Expression Tree from Infix expression is left as reader exercise and some help can be found at

http://www.seas.gwu.edu/~csci131/fall96/exp_to_tree.html

Following procedure will evaluate an expression tree in a recursive fashion:

Procedure Name: Evaluate Tree Arguments : Address of root of the tree int Evaluate Tree (struct node*

root)

IF root != NULL

IF current node contains an operator

x = Evaluate Tree(root -> left_child)

y = Evaluate Tree(root -> right_child)

Perform operation on x and y, specified by the

operator and store result in z

Return z

else Return root->data

Refer program #2 for evaluation of an Expression Tree.

6. POSTFIX NOTATION:

Postfix notation is a way of writing algebraic expressions without the use of parentheses or rules of

operator precedence. The expression above would be written as AB+CD-/ in postfix notation. (Don't

Page 25: Data Structure Manual for BE students

100

panic! We'll explain this in a moment.) Postfix notation had its beginnings in the work of Jan

Łukasiewicz* (1878-1956), a Polish logician, mathematician, and philosopher. Łukasiewicz

developed a parenthesis-free prefix notation that came to be called Polish notation and a postfix

notation now called Reverse Polish Notation or RPN. From these ideas, Charles Hamblin developed

a postfix notation for use in computers. Łukasiewicz's work dates from about 1920. Hamblin's work

on postfix notation was in the mid-1950's. Calculators, notably those from Hewlett-Packard, used

various postfix formats beginning in the 1960s.

In this mini-lecture we will use variables represented by single letters and operators represented by

single characters. Things are more complicated in real life. Variables have names composed of many

characters and some operators, like ** for exponentiation, require more than a single character.

However, we can make these simplifications without loss of generality.

In our simplified examples, each variable is represented by a single letter and each operator by a

single character. These are called tokens. In a more complex implementation, your program would

still scan a series of tokens, but they would likely be pointers into symbol tables, constant pools, and

procedure calls for operators.

Evaluating Postfix Notation

Evaluating an expression in postfix notation is trivially easy if you use a stack. The postfix

expression to be evaluated is scanned from left to right. Variables or constants are pushed onto the

stack. When an operator is encountered, the indicated action is performed using the top elements of

the stack, and the result replaces the operands on the stack.

Let's do an example using the postfix expression AB+CD-/. In order to see what's going on as the

expression is evaluated, we will substitute numbers for the variables. The expression to be evaluated

becomes 9 7 + 5 3 - /. This is equivalent to (9 + 7) / (5 - 3) so we expect the answer to be eight. Click the

"Go" button at the right to see an animation showing the evaluation of the expression.

You will see the expression scanned from left to right. A yellow highlight shows the term currently

being scanned. The digits in the expression are pushed onto the stack and the operators are

performed.

Experiment with the animation until you are sure you understand what's going on.

Page 26: Data Structure Manual for BE students

100

Now that you see how easy it is to evaluate an expression that's in RPN form, you will want to

convert ordinary infix expressions to RPN so that you can evaluate them. That turns out to be easy

too, if you use a stack.

 7. QUEUES:

Overview of Queues

A queue is a first-in first-out data structure (FIFO). Conceptually, the queue data structure behaves

like a line. New data is placed at the rear of the queue and when data is removed it is taken from the

front. A printer maintains a list of jobs in a queue; the oldest job, the one that has been in the queue

the longest, is serviced first.

The operations supported by a queue are as follows:

void enqueue(Object o) - place object o on the rear of the queue

Object dequeue() - remove and return the object at the front of the queue

Object front() - return the object at the front of the queue without removing it

int size() - return the size of the queue

boolean isEmpty() - return true if the queue contains no elements, false otherwise

Queues are typically depicted as follows:

The previous queue would be the result of the following operations:

enqueue(1)

Page 27: Data Structure Manual for BE students

100

enqueue(2)

enqueue(3)

A dequeue on the queue above would return the object 1 and the resulting queue would look as

follows:

A front on the queue above would return the object 2 and the queue itself would remain unchanged.

Implementation

A queue can be implemented using an array or a linked list. In essense, the queue operations simply

limit the way in which we access data stored in a data structure such as an array. A queue can also be

implemented using two stacks and a stack using two queues. Though these implementations are not

terribly efficient, it is a good exercise to consider how you would build such an implementation.

When choosing which rudimentary data structure to use for an implementation, it is imperative that

you consider efficiency. How many steps will enqueue and dequeue require?

To implement a queue, you will need to implement a Queue class that provides the queue operations

described above. You will also want to provide appropriate error reporting. Therefore, it might make

sense to have the dequeue operation throw a QueueEmptyException in the event that the programmer

tries to dequeue from a queue with no elements.

Abstract idea of a queue:

The queue is another data structure. A physical analogy for a queue is a line at a bank. When you go to the

bank, customers go to the rear (end) of the line and customers come off of the line (i.e., are serviced) from the

front of the line.

Page 28: Data Structure Manual for BE students

100

Aside: In fact, other English-speaking countries use this term for a line, e.g., they might say "Queue up!"

rather than "Get in a line!"

Like a stack, a queue usually holds things of the same type. We usually draw queues horizontally. Here's a

queue of characters with 3 elements:

queue

-------------

| a | b | c |

-------------

^ ^

| |

front rear

The main property of a queue is that objects go on the rear and come off of the front of the queue.

Here are the minimal set of operations we'd need for an abstract queue:

o Enter (or Insert)

Places an object at the rear of the queue.

o Delete (or Remove)

Removes an object from the front of the queue and produces that object.

o IsEmpty

Reports whether the queue is empty or not.

2. Order produced by a queue:

Queues are useful because they produce a certain order in which the contents of the queue are used. Let's

see what order that is by looking at a queue of characters. Now, what would a particular sequence of Enter

and Deletes do to this queue:

queue

Page 29: Data Structure Manual for BE students

100

-------------

| a | b | c |

-------------

^ ^

| |

front rear

Now, Enter(queue, 'd')...

queue

-----------------

| a | b | c | d |

-----------------

^ ^

| |

front rear

Now, ch = Delete(queue)...

queue ch

------------- -----

| b | c | d | | a |

------------- -----

^ ^

| |

front rear

You'll notice that the queue enforces a certain order to the use of its contents. Is the ordering of the queue

Last thing In is the First thing Out (LIFO) or First Thing In is the First thing Out (FIFO)?

Answer: Queues produce FIFO order. Remember that stacks produce LIFO order.

3. Implementing a queue with an array:

Page 30: Data Structure Manual for BE students

100

Since a queue usually holds a bunch of items with the same type, we could implement a queue with an

array. Let's simplify our array implementation of a queue by using an array of a fixed size,

MAX_QUEUE_SIZE.

What other pieces of data would you need (besides an array) to implement a queue in this way?

One of the things we'll need to keep track of is the number of elements in the queue, i.e., not all the

elements in the array may be holding elements of the queue at any given time.

So far, the pieces of data we need for our array implementation of the queue are:

an array

a count

Will these pieces be sufficient? Let's look at an example to find out...We'll start with a queue with 3

elements:

queue (made up of 'contents' and 'count')

----------------- -----

| a | b | c | | | 3 |

----------------- -----

0 1 2 3 count

contents

where a is at the front and c is at the rear. Now, we enter a new element with: Enter(queue, 'd')...

queue (made up of 'contents' and 'count')

----------------- -----

| a | b | c | d | | 4 |

----------------- -----

0 1 2 3 count

contents

All seems well. How about if we remove an element with: ch = Delete(queue)?...

Page 31: Data Structure Manual for BE students

100

queue (made up of 'contents' and 'count')

----------------- ----- -----

| | b | c | d | | 3 | | a |

----------------- ----- -----

0 1 2 3 count ch

contents

Hmmm, we have a problem because the front of the queue is no longer at array position 0. One solution would

be to move all the elements down one, giving:

queue (made up of 'contents' and 'count')

----------------- -----

| b | c | d | | | 3 |

----------------- -----

0 1 2 3 count

contents

We reject that solution though because it is too expensive to move everything down every time we remove an

element.

Instead, can we use an additional piece of information to keep track of the front?

Answer: Yes! We can use the index of the element at the front, giving:

queue (made up of 'contents', 'front' and 'count')

----------------- ----- -----

| | b | c | d | | 1 | | 3 |

----------------- ----- -----

0 1 2 3 front count

Contents

Now, what if we enter another element with: Enter(queue, 'e')? Currently, the rear of the queue holds 'd' and is

at the end of the array. Where will we put 'e'?

Page 32: Data Structure Manual for BE students

100

9. A CIRCULAR QUEUE:

A circular queue is a particular implementation of a queue. It is very efficient. It is also quite useful

in low level code, because insertion and deletion are totally independant, which means that you don't

have to worry about an interrupt handler trying to do an insertion at the same time as your main code

is doing a deletion.

How does it work?

A circular queue consists of an array that contains the items in the queue, two array indexes and an optional

length. The indexes are called the head and tail pointers and are labelled H and T on the diagram.

The head pointer points to the first element in the queue, and the tail pointer points just beyond the last

element in the queue. If the tail pointer is before the head pointer, the queue wraps around the end of the array.

Is the queue empty or full?

There is a problem with this: Both an empty queue and a full queue would be indicated by having the head

and tail point to the same element. There are two ways around this: either maintain a variable with the number

of items in the queue, or create the array with one more element that you will actually need so that the queue

is never full.

Operations

Insertion and deletion are very simple. To insert, write the element to the tail index and increment the tail,

wrapping if necessary. To delete, save the head element and increment the head, wrapping if necessary. Don't

Page 33: Data Structure Manual for BE students

100

use a modulus operator for wrapping (mod in Pascal, % in C) as this is very slow. Either use an if statement or

(even better) make the size of the array a power of two and simulate the mod with a binary and (& in C).

How does it work?

It works very much like a circular queue, except that it doesn't "wrap around". Instead, you make the array

much bigger than the maximum number of items in the queue. When you run out of room at the end of the

array, you move the entire contents of the queue back to the front of the array (this is the "bulk move" from

which the structure gets its name).

Operations

Insertion and deletion are very simple. To insert, write the element to the tail index and increment the tail. To

delete, save the head element and increment the head. If after an insertion the tail points beyond the end of the

array, then do the following:

1. Copy the contents of the queue to the front of the array (I recommend the move procedure in Pascal or

the memcpy function in C, rather than doing it manually).

2. Set the head pointer to the new head of the queue and the new tail pointer to the new tail of the queue.

Note if the queue occupies more than half the array, then you must be careful that you don't overwrite the

frontmost queue elements before they are copied because the old and new queue will overlap (and memcpy

doesn't allow overlap - use memmove in this case).

9. SINGLY-LINKED LISTS :

  The singly-linked list is the most basic of all the linked data structures. A singly-linked list is simply a

sequence of dynamically allocated objects, each of which refers to its successor in the list. Despite this

obvious simplicity, there are myriad implementation variations. Figure  shows several of the most common

singly-linked list variants.

  

Page 34: Data Structure Manual for BE students

100

Figure: Singly-linked list variations.

The basic singly-linked list is shown in Figure  (a). Each element of the list refers to its successor and

the last element contains the null reference. One variable, labeled head  in Figure  (a), is used to keep

track of the list.

The basic singly-linked list is inefficient in those cases when we wish to add elements to both ends of

the list. While it is easy to add elements at the head of the list, to add elements at the other end (the

tail ) we need to locate the last element. If the basic basic singly-linked list is used, the entire list

needs to be traversed in order to find its tail.

Figure  (b) shows a way in which to make adding elements to the tail of a list more efficient. The

solution uses a second variable, tail , which refers to the last element of the list. Of course, this time

efficiency comes at the cost of the additional space used to store the variable tail.

The singly-linked list labeled (c) in Figure  illustrates two common programming tricks. There is

an extra element at the head of the list called a sentinel . This element is never used to hold data and

it is always present. The principal advantage of using a sentinel is that it simplifies the programming

of certain operations. For example, since there is always a sentinel standing guard, we never need to

modify the head variable. Of course, the disadvantage of a sentinel such as that shown in (c) is that

extra space is required, and the sentinel needs to be created when the list is initialized.

The list (c) is also a circular list . Instead of using a null reference to demarcate the end of the list, the

last element of the list refers to the sentinel. The advantage of this programming trick is that insertion

at the head of the list, insertion at the tail of the list, and insertion at an arbitrary position of the list

are all identical operations.

Of course, it is also possible to make a circular, singly-linked list that does not use a sentinel.

Figure  (d) shows a variation in which a single variable is used to keep track of the list, but this time

Page 35: Data Structure Manual for BE students

100

the variable, tail, refers to the last element of the list. Since the list is circular in this case, the first

element follows the last element of the list. Therefore, it is relatively simple to insert both at the head

and at the tail of this list. This variation minimizes the storage required, at the expense of a little

extra time for certain operations.

Figure  illustrates how the empty list (i.e., the list containing no list elements) is represented for each

of the variations given in Figure. Notice that the sentinel is always present in list variant (c). On the

other hand, in the list variants which do not use a sentinel, the null reference is used to indicate the

empty list.

Figure: Empty singly-linked lists.

In the following sections, we will present the implementation details of a generic singly-linked list.

We have chosen to present variation (b)--the one which uses a head and a tail--since is supports

append and prepend operations efficiently.

10. IMPLEMENTING A STACK WITH A LINKED LIST:

Using a linked list is one way to implement a stack so that it can handle essentially any number of elements.

Here is what a linked list implementing a stack with 3 elements might look like:

Page 36: Data Structure Manual for BE students

100

list

|

v

-------- -------- ---------

| C | -+-->| B | -+-->| A | 0 |

-------- -------- ---------

Where should we consider the top of the stack to be, the beginning or end of the list, and why?

How will we represent an empty stack?

C implementation:

Now, think about how to actually implement this stack of characters in C.

It is usually convenient to put a data structure in its own module, thus, we'll want to create files stack.h and a

stack.c.

The operations needed for our stack are mainly determined by the operations provided by an abstract stack,

namely:

StackPush()

StackPop()

StackIsEmpty()

We may need to add a few other operations to help implement a stack. These will become apparent as we start

to implement.

11. QUEUE - LINKED-LIST IMPLEMENTATION – TYPES:

Here, besides discussing the queue data structure, we will demonstrate how to better hide the details

of a data structure using ADTs/CDTs and generic type definitions.

Page 37: Data Structure Manual for BE students

100

1. Abstract idea of a queue:

The queue is another data structure. A physical analogy for a queue is a line at a bank. When

you go to the bank, customers go to the rear (end) of the line and customers come off of the

line (i.e., are serviced) from the front of the line.

Aside: In fact, other English-speaking countries use this term for a line, e.g., they might say "Queue

up!" rather than "Get in a line!"

Like a stack, a queue usually holds things of the same type. We usually draw queues

horizontally. Here's a queue of characters with 3 elements:

queue

-------------

| a | b | c |

-------------

^ ^

| |

front rear

The main property of a queue is that objects go on the rear and come off of the front of the

queue.

Here are the minimal set of operations we'd need for an abstract queue:

o Enter (or Insert)

Places an object at the rear of the queue.

Page 38: Data Structure Manual for BE students

100

o Delete (or Remove)

Removes an object from the front of the queue and produces that object.

o IsEmpty

Reports whether the queue is empty or not.

2. Order produced by a queue:

Queues are useful because they produce a certain order in which the contents of the queue are

used. Let's see what order that is by looking at a queue of characters. Now, what would a

particular sequence of Enter and Deletes do to this queue:

queue

-------------

| a | b | c |

-------------

^ ^

| |

front rear

Now, Enter(queue, 'd')...

queue

-----------------

| a | b | c | d |

-----------------

^ ^

| |

front rear

Now, ch = Delete(queue)...

queue ch

------------- -----

| b | c | d | | a |

------------- -----

Page 39: Data Structure Manual for BE students

100

^ ^

| |

front rear

You'll notice that the queue enforces a certain order to the use of its contents. Is the ordering of

the queue Last thing In is the First thing Out (LIFO) or First Thing In is the First thing Out

(FIFO)?

Answer: Queues produce FIFO order. Remember that stacks produce LIFO order.

3. Implementing a queue:

Since a queue usually holds a bunch of items with the same type, we could implement a queue

with an array. However, here we'll use a linked list implementation.

Remember that a linked list can:

o hold as many objects as memory can hold (i.e., it's not a fixed size).

o grow easily without having to copy over the old contents.

Note: Copying over is the problem incurred with a dynamic array that has to be made bigger.

Recall that linked lists are made up of things called nodes:

A Node

-----------------

| | |

| Data | Link -+-->

| | |

-----------------

A node contains 2 main parts:

o some data and,

o a link to the node after it (for a singly-linked list).

In C, we know that these links will be pointers. Here is an example singly-linked list that

holds characters.

list

|

v

Page 40: Data Structure Manual for BE students

100

--------- --------- ---------

| a | --+---> | b | --+---> | c | 0 |

--------- --------- ---------

First, we must decide how the contents of this linked list corresponds to the structure of the

queue.

A logical choice would be to make the beginning of the linked list the front of the queue and

the end of the linked list the rear of the queue.

Given this representation, we'll rename the link to the beginning of the list to front:

front

|

v

--------- --------- ---------

| a | --+---> | b | --+---> | c | 0 |

--------- --------- ---------

Will this representation be sufficient for adding and removing things from the queue?

Answer: Yes, however, we see one inefficiency in that, unlike the stack, things aren't added

and removed from the same end. To add something to a queue, that thing must go on the

rear. Currently, the only way to get to the end is to traverse to the end of the list. We can be

more efficient if we keep track of the rear of the queue with a direct link.

Our augmented representation looks as follows:

front rear-----------------+

| |

v v

--------- --------- ---------

Page 41: Data Structure Manual for BE students

100

| a | --+---> | b | --+---> | c | 0 |

--------- --------- ---------

Empty Queue

Last, we'll need a representation of an empty queue. We'll make at least the front, but also maybe rear, link

to nothing when the queue is empty. In C, this means they will contain NULL pointers.

12. DOUBLY-LINKED LIST:

A more sophisticated kind of linked list is a doubly-linked list or two-way linked list. Each node

has two links: one points to the previous node, or points to a null value or empty list if it is the first

node; and one points to the next, or points to a null value or empty list if it is the final node.

A doubly-linked list containing three integer values: the value, the link forward to the next node, and the link

backward to the previous node

In some very low level languages, XOR-linking offers a way to implement doubly-linked lists using

a single word for both links, although the use of this technique is usually discouraged.

Doubly-linked lists

With doubly-linked lists there are even more pointers to update, but also less information is needed,

since we can use backwards pointers to observe preceding elements in the list. This enables new

operations, and eliminates special-case functions. We will add a prev field to our nodes, pointing to

the previous element, and a lastNode field to our list structure which always points to the last node in

the list. Both list.firstNode and list.lastNode are null for an empty list.

record Node {

data // The data being stored in the node

next // A reference to the next node; null for last node

Page 42: Data Structure Manual for BE students

100

prev // A reference to the previous node; null for first node

}

record List {

Node firstNode // points to first node of list; null for empty list

Node lastNode // points to last node of list; null for empty list

}

Iterating through a doubly linked list can be done in either direction. In fact, direction can change

many times, if desired.

Forwards

node := list.firstNode

while node ≠ null

<do something with node.data>

node := node.next

Backwards

node := list.lastNode

while node ≠ null

<do something with node.data>

node := node.prev

These symmetric functions add a node either after or before a given node, with the diagram

demonstrating after:

If h = height of a binary tree,

max # of leaves = 2h

max # of nodes = 2h + 1 - 1

A binary tree with height h and 2h + 1 - 1 nodes (or 2h leaves) is called a full binary tree

 

Page 43: Data Structure Manual for BE students

100

Figure 13.1 shows several examples of binary trees.

The nodes of a binary tree can be numbered in a natural way, level by level, left to right. For example, see

Figure 13.2.

A binary tree with n nodes is said to be complete if it contains all the first n nodes of the above

numbering scheme. Figure 13.3 shows examples of complete and incomplete binary trees.

Total number of binary trees having n nodes

= number of stack-realizable permutations of length n

= number of well-formed parentheses (with n left parentheses and n right parentheses)

Figure 13.2: Level by level numbering of a binary tree

Page 44: Data Structure Manual for BE students

100

Fig:13.3

Binary Tree Traversal:

1. Preorder

Visit root, visit left subtree in preorder, visit right subtree in preorder

2. Postorder

Visit left subtree in postorder, right subtree in postorder, then the root

3. Inorder

Visit left subtree in inorder, then the root, then the right subtree in inorder

Figure 13.4 shows several binary trees and the traversal sequences in preorder, inorder, and postorder.

We can construct a binary tree uniquely from preorder and inorder or postorder and inorder but not

preorder and postorder.

Page 45: Data Structure Manual for BE students

100

Figure 13.4.: Binary tree traversals

14.a A BINARY SEARCH ALGORITHM :

A binary search algorithm (or binary chop) is a technique for locating a particular value in a

sorted list of values. It makes progressively better guesses, and closes in on the sought value by

selecting the middle element in the span (which, because the list is in sorted order, is the median

value), comparing its value to the target value, and determining if the selected value is greater than,

less than, or equal to the target value. A guess that turns out to be too high becomes the new upper

bound of the span, and a guess that is too low becomes the new lower bound. Pursuing this strategy

iteratively, it narrows the search by a factor of two each time, and finds the target value or else

Page 46: Data Structure Manual for BE students

100

determines that it is not in the list at all. A binary search is an example of a dichotomic divide and

conquer search algorithm.

The most common application of binary search is to find a specific value in a sorted list. To cast this

in the frame of the guessing game (see Example below), realize that we now guess the index, or

numbered place, of the value in the list. This is useful because, given the index, other data structures

will contain associated information. Suppose a data structure containing the classic collection of

name, address, telephone number and so forth has been accumulated, and an array is prepared

containing the names, numbered from one to N. A query might be: what is the telephone number for

a given name X. To answer this the array would be searched and the index (if any) corresponding to

that name determined, whereupon it would be used to report the associated telephone number and so

forth. Appropriate provision must be made for the name not being in the list (typically by returning

an index value of zero), indeed the question of interest might be only whether X is in the list or not.

If the list of names is in sorted order, a binary search will find a given name with far fewer probes

than the simple procedure of probing each name in the list, one after the other in a linear search, and

the procedure is much simpler than organizing a hash table though once created, searching with a

hash table may well be faster, typically averaging just over one probe per lookup. With a non-

uniform distribution of values, if it is known that some few items are much more likely to be sought

for than the majority, then a linear search with the list ordered so that the most popular items are first

may do better than binary search. However, the choice of the best method may not be immediately

obvious. If, between searches, items in the list are modified or items are added or removed,

maintaining the required organisation may consume more time than the searches.

The binary search begins by comparing the sought value X to the value in the middle of the list;

because the values are sorted, it is clear whether the sought value would belong before or after that

middle value, and the search then continues through the correct half in the same way. Only the sign

of the difference is inspected: there is no attempt at an interpolation search based on the size of the

differences.

Page 47: Data Structure Manual for BE students

100

The method

In order to discuss the method in detail, a more formal description is necessary. The basic idea is that

there is a data structure represented by array A in which individual elements are identified as A(1),

A(2),...,A(N) and may be accessed in any order. The data structure contains a sub-element or data

field called here Key, and the array is ordered so that the successive values A(1).Key ≤ A(2).Key and

so on. Such a key might be a name, or it might be a number. The requirement is that given some

value x, find an (not necessarily the one and only) index p such that A(p).Key = x.

Page 48: Data Structure Manual for BE students

100

To begin with, the span to be searched is the full supplied list of elements, as marked by variables L

and R, and their values are changed with each iteration of the search process, as depicted by the

flowchart. Note that the division by two is integer division, with any remainder lost, so that 3/2

comes out as 1, not 1½. The search finishes either because the value has been found, or else, the

specified value is not in the list.

That it works

The method relies on and upholds the notion If x is to be found, it will be amongst elements (L + 1)

to (R - 1) of the array.

The initialisation of L and R to 0 and N - 1 make this merely a restatement of the supplied problem,

that elements 1 to N are to be searched, so the notion is established to begin with. Consider now that

some element p of the indicated range is selected. At this point, it does not matter which specific

element is selected, merely that one is. Compare x to A(p).Key. If x = A(p).Key then the method

terminates in success. Otherwise, suppose x < A(p).Key. If so, then because the array is in sorted

order, x will also be less than all later elements of the array, all the way to element (R - 1) as well.

Accordingly, the value of the right-hand bound index R can be changed to be the value p, since, by

the test just made, x < A(p).Key and so, if x is to be found, it will be amongst elements earlier than p,

that is (p - 1) and earlier. And contrariwise, for the case x > A(p).Key, the value of L would be

changed. Further, whichever bound is changed, the span remaining to be searched is reduced. If L is

changed, it is changed to a higher number (at least L + 1), whereas if R is changed, it is to a lower

number (at most R - 1) because those are the limits for p.

It remains to consider that a valid value for p is always chosen, which in turn depends on whether

there are any elements remaining in the search span (L + 1) to (R - 1). The number of such elements

remaining is clearly (R - L - 1) so computing (R - L) gives (number of elements + 1); halving that

number (with integer division) means that if one element remained, then p = 1, but if no elements

remain, p = 0, and in that case the method terminates with the report "Not found". Otherwise, for p >

0, the search continues with p:=L + p, which by construction is within the bounds (L + 1) to (R - 1).

Accordingly, with each iteration, if the search span is empty the result is "Not found", otherwise

either x is found at the probe point p or the search span is reduced for the next iteration. Thus the

method works, and so can be called an Algorithm.

Page 49: Data Structure Manual for BE students

100

That it is fast

The interval being searched is successively halved (actually slightly better than halved) in width with

each iteration, so the number of iterations required is at most the base two logarithm of N. - Zero for

empty lists. More precisely, each probe both removes one element from further consideration and

selects one or the other half of the interval for further searching.

Suppose that the number of items in the list is odd. Then there is a definite middle element at p = (N

+ 1)/2 - this is proper division without discarding remainders. If that element's key does not match x,

then the search proceeds either with the first half, elements 1 to p - 1 or the second, elements p + 1 to

N. These two spans are equal in extent, having (N - 1)/2 elements. Conversely, suppose that the

number of elements is even. Then the probe element will be p = N/2 and again, if there is no match

one or the other of the subintervals will be chosen. They are not equal in size; the first has N/2 - 1

elements and the second (elements p + 1 to N as before) has N/2 elements.

Now supposing that it is just as likely that N will be even as odd in general, on average an interval

with N elements in it will become an interval with (N - 1)/2 elements.

Working in the other direction, what might be the maximum number of elements that could be

searched in p probes? Clearly, one probe can check a list with one element only (to report a match,

or, "not found") and two probes can check a list of three elements. This is not very impressive

because a linear search would only require three probes for that. But now the difference increases

exponentially. With three probes, seven elements can be checked, four for fifteen, and so forth. In

short, to search N elements requires at most p probes where p is the smallest integer such that 2p > N

Taking the binary logarithm of both sides, p > lb(N)

Or, lb(N) (with any fractional part rounded up to the next integer), is the maximum number of probes

required to search N elements.

14.b THE TOWER OF HANOII PROBLEM:

The History:

The puzzle is called "Towers of Hanoi" because an early popular presentation wove a fanciful legend around

it. According to this myth (uttered long before the Vietnam War), there is a Buddhist monastery at Hanoi

which contains a large room with three time-worn posts in it surrounded by 21 golden discs. Monks, acting

out the command of an ancient prophecy, have been moving these disks, in accordance with the rules of the

puzzle, once every day since the monastery was founded over a thousand years ago.

Page 50: Data Structure Manual for BE students

100

They are said to believe that when the last move of the puzzle is completed, the world will end in a clap of

thunder. Fortunately, they are nowhere even close to being done.

The Rules:

There are n disks (1, 2, 3,..., n) and three towers (pegs). The towers are labeled 'A', 'B', and 'C'.

All the disks are initially placed on the first peg (the 'A' peg).

No disk may be placed on top of a smaller disk.

You may only move one disk at a time and this disk must be the top disk on a peg.

Page 51: Data Structure Manual for BE students

100

Program 1.

Write a c program to create a sequential file with atleast 5 records. Write necessary functionsa. To display all the records in the file.b. To search for a specific record based on the USN. In case the record is notfound, suitable message should be displayed. Both options in this case must bedemonstrated.

#include<stdio.h>#include<conio.h>#include<process.h>#include<string.h>

typedef struct{

int usn;char name[25];int marks1;int marks2;int marks3;

}STUDENT;

int search_record(int key_usn,FILE *fp){

STUDENT st;for(;;){

fscanf(fp,"%d %s %d %d %d",&st.usn, st.name, &st.marks1, &st.marks2, &st.marks3);if (feof(fp))break;if (key_usn==st.usn)return 1;

}return 0;

}

Page 52: Data Structure Manual for BE students

100

void display_records(FILE *fp,int pass){

STUDENT st;printf("USN\tName\t\t\t Marks1\tMarks2\tMarks3\n");for(;;){

fscanf(fp,"%d %s %d %d %d" ,&st.usn, st.name, &st.marks1, &st.marks2, &st.marks3); if(feof(fp))break; if(pass==st.usn)

{cprintf("%-5d %-10s",st.usn,st.name);printf("\t\t");cprintf(" %-5d %-5d %-5d",st.marks1,st.marks2,st.marks3);printf("\n");}

else printf("%-5d %-10s\t\t %-5d %-5d %5d\n", st.usn, st.name, st.marks1, st.marks2, st.marks3);

}}

void append_record(FILE *fp){

STUDENT st;printf("USN : ");scanf("%d",&st.usn);printf("Name : ");scanf("%s",st.name);printf("Marks1 : ");scanf("%d",&st.marks1);printf("Marks2 : ");scanf("%d",&st.marks2);printf("Marks3 : ");scanf("%d",&st.marks3);fprintf(fp,"%d %s %d %d %d\n",st.usn,st.name,st.marks1,st.marks2,st.marks3);

}

Page 53: Data Structure Manual for BE students

100

void main(){

STUDENT st;char fname[12];FILE *fp;int key_usn;int key = 0;int flag;int(choice);clrscr();printf("Enter the file name : ");scanf("%s",fname);for(;;){

printf("\n\n1.Insert Record\n2.Search Record\n");printf("3.Display Record\n4.Quit\n\n\n");printf("Enter the choice : ");scanf("%d",&choice);

switch(choice){case 1:

fp = fopen(fname,"a+");if(fp==NULL){

printf("File Open Failed");break;

}append_record(fp);fclose(fp);break;

case 2:fp = fopen(fname,"r");if(fp==NULL){

printf("File Open Failed");break;

}

Page 54: Data Structure Manual for BE students

100

printf("Enter USN : ");scanf("%d",&key_usn);flag = search_record(key_usn,fp);if (flag==0)

printf("Unsuccessful search\n");else

{printf("Successful search\n");fp = fopen(fname,"r");if(fp==NULL){

printf("File Open Failed");break;

}display_records(fp,key_usn);}

fclose(fp);break;

case 3:fp = fopen(fname,"r");if(fp==NULL){

printf("File Open Failed");break;

}display_records(fp,key);fclose(fp);break;

default:exit(0);

}}

}

Page 55: Data Structure Manual for BE students

100

Program 2.

Write and demonstrate the following C program.a) newstrcpy that does the same job as strcpyb) newstrcat that does the same job as strcat without using any library

functions.

#include<stdio.h>#include<conio.h>

void newstrcpy(char *dst,char *source){

while(*source!='\0'){

*dst=*source;dst++;source++;

}*dst='\0';

}

void newstrcat(char *s1,char *s2){

while(*s1!='\0')s1++;

while(*s2!='\0'){

*s1=*s2;s1++;s2++;

}*s1='\0';

}

Page 56: Data Structure Manual for BE students

100

void main(){

char str1[20],str2[20];int choice;clrscr();while(choice!=3){printf("\nEnter the first string:");scanf("%s",str1);printf("\nEnter the second string:");scanf("%s",str2);printf("\nEntered string 1: %s , string 2 : %s",str1,str2);printf("\nEnter1 to copy and 2 to concatinate:");printf("\nEnter the choice:");scanf("%d",&choice);switch(choice){

case 1: newstrcpy(str1,str2);break;case 2: newstrcat(str1,str2);break;default:printf("undefined operation");

}

printf("String 1: %s\n",str1);printf("String 2: %s\n",str2);printf("press 2 to continue or 3 to exit:");scanf("%d",&choice);}getch();

}

Page 57: Data Structure Manual for BE students

100

Program – 3

Write a C program which accepts the IP address in decimal dot format and converts it into a 32 bit long integer using strtok library functions and unions.

#include<stdio.h>

union x{

unsigned long add;char c[4];

}ip;

main(){

char ch, **end,inp[16],*p;int i=0;clrscr();printf("Enter the IP address: ");fflush(stdin);gets(inp);p=strtok(inp,".");ip.c[3]=strtol(p,end,10);for(i=2;i>=0;i--)

{p=strtok(NULL,".");ip.c[i]= strtol(p,end,10);}

printf("Converted address is : %lu",ip.add);getch();

}

Page 58: Data Structure Manual for BE students

100

Program 4.

Write a C program to construct a stack of integers to perform the following operations:

a.Push b.Pop c.Display

It must print appropriate messages for Overflow, Underflow and empty.

#include<stdio.h>#include<conio.h>#include<process.h>#define stack_size 2

int ele,i;int flag=1;struct stack{

int item[5];int top;

}s;

void push(struct stack *ptr, int ele){

if(ptr->top==stack_size-1)printf("\n Overflow.\n");

else{ptr->top++;ptr->item[ptr->top]=ele;}

}

Page 59: Data Structure Manual for BE students

100

void pop(struct stack *ptr){

if(ptr->top= =-1){printf("\nUnderflow.\n");}

elseprintf("\nThe popped value is %d.",(ptr->item[(ptr->top)--]));

}

void display(struct stack *ptr){

if(ptr->top= =-1)printf("\nEmpty Stack.\n");

else{printf("\n\n");for(i=0;i<=ptr->top; i++)

printf("%d\t",ptr->item[i]);}

}

main(){

clrscr();s.top=-1;while(1){

printf("\n\n1.PUSH\n2.POP\n3.DISPLAY\n4.Exit");printf("\nEnter your Choice: ");scanf("%d",&i);

Page 60: Data Structure Manual for BE students

100

switch(i){

case 1: printf("\nEnter the element: ");scanf("%d",&ele);push(&s,ele);break;

case 2: pop(&s);break;

case 3: display(&s);break;

case 4: exit(0);break;

default: printf("\nInvalid Input.");}

}getch();

}

Page 61: Data Structure Manual for BE students

100

Program – 5

Write a C program to convert & print a valid parenthesized infix expression to postfix. The expression should consist of single character operands and binary operators.

#include<stdio.h>#include<conio.h>#include<process.h>#include<ctype.h>

#define stack_size 25

int elem,i;char str[25],res[25];

char stack[25];int top;

void push(char ele){

if(top==stack_size-1)printf("\n Overflow.\n");

else{top++;stack[top]=ele;}

}

char pop(){

if(top==-1){printf("\nUnderflow.\n");return (-1);}

Page 62: Data Structure Manual for BE students

100

elsereturn (stack[top--]);

}

void convert(){

int i=0,j=0;

for(i=0;str[i]!='\0';i++){if(isalpha(str[i]) || isdigit(str[i]))

res[j++]=str[i];elseswitch(str[i]){

case '(': push(str[i]); break;case '$': while(stack[top]=='$')

res[j++]=pop(); push(str[i]); break;

case '/': case '*':while(stack[top]=='$' || stack[top]=='/'||stack[top]=='*')

res[j++]=pop(); push(str[i]); break;

case '+':case '-':while(stack[top]=='$'||stack[top]=='*'||

stack[top]=='/'||stack[top]=='+'||stack[top]=='-')

res[j++]=pop(); push(str[i]); break;

case ')': while(stack[top]!='(')res[j++]=pop();

pop(); break;

}}

Page 63: Data Structure Manual for BE students

100

while(top>-1)res[j++]=pop();

res[j]='\0';printf("Postfix Expression is: %s ",res);

}

main(){

clrscr();top=-1;printf("Enter a valid infix expression: ");scanf("%s",str);convert();getch();

}

Page 64: Data Structure Manual for BE students

100

Program 6.

Wrie a C program to evaluate a valid postfix expression using a stack. Assume that the postfix expression is read as a single line consisting of non negative singe digit operands and binary arithmatic operators. The operators are +,-,*,/.

#include<stdio.h>#include<conio.h>#include<process.h>#include<ctype.h>#define stack_size 10

int elem,i;char str[20];

struct stack{

int item[10];int top;

}s;

void push(struct stack *ptr, int ele){

if(ptr->top==stack_size-1)printf("\n Overflow.\n");

else{ptr->top++;ptr->item[ptr->top]=ele;}

}

int pop(struct stack *ptr){

if(ptr->top==-1){printf("\nUnderflow.\n");return (-1);}

Page 65: Data Structure Manual for BE students

100

elsereturn (ptr->item[(ptr->top)--]);

}

int evaluate(){

int a,b,res;for(i=0;str[i]!='\0';i++)

{if(isdigit(str[i]))

push(&s,str[i]-'0');else

{b=pop(&s);a=pop(&s);s

witch(str[i]){case '/': res=a/b;break;case '*': res=a*b;break;case '-': res=a-b;break;case '+': res=a+b;break;}

push(&s,res);}

}res=pop(&s);return res;

}

Page 66: Data Structure Manual for BE students

100

main(){

clrscr();s.top=-1;printf("Enter a valid postfix expression: ");scanf("%s",str);printf("\n\n Final result is : %d",evaluate());getch();

}

Page 67: Data Structure Manual for BE students

100

Program 7:

Write a program to simulate the working of queue of integers using an array. Provide the following operations: a] Insert b] Delete c] Display

#include<stdio.h>#include<conio.h>#define MAX 50struct queue{ int ele[MAX]; int rear;};void insert(struct queue *,int);int removeElement(struct queue *);int isEmpty(struct queue *);int isFull(struct queue *);void displayQueue(struct queue *);int menu();void main(){

int element,choice;struct queue q;q.rear=-1;do{

choice=menu(); switch (choice) {

case 1: if(isFull(&q)) printf("\n The queue is full"); else { printf("\n Enter the element to be inserted : ");

scanf("%d",&element); insert(&q,element);

} break;

Page 68: Data Structure Manual for BE students

100

case 2: if(isEmpty(&q))

printf("\n Queue is empty"); else

printf("\n Element removed = %d",removeElement(&q)); break;

case 3: if(isEmpty(&q))

printf("\n The queue is empty"); else

printf("\n The queue is not empty"); break;

case 4: if(isFull(&q))

printf("\n The queue is full"); else

printf("\n The queue is not full"); break;

case 5: displayQueue(&q); break;

case 6: printf("\n Thank You"); break;

default: printf("\n Please enter your choice correctly"); break;

} }while(choice!=6); getch();

}

Page 69: Data Structure Manual for BE students

100

int menu(){

int ch; getch(); clrscr(); printf("\n 1-Insert an element into the queue"); printf("\n 2-Remove an element from the queue"); printf("\n 3-Check whether the queue is empty"); printf("\n 4-Check whether the queue is full"); printf("\n 5-Display the elements of the queue"); printf("\n 6-Exit"); printf("\n Enter your choice : \t"); scanf("%d",&ch); return ch;

}void insert(struct queue *pq, int e){

pq->rear++;pq->ele[pq->rear]=e;

}int removeElement(struct queue *pq){

int eleRem=pq->ele[0],i;for(i=1;i<=pq->rear;i++)

pq->ele[i-1]=pq->ele[i];pq->rear--;return eleRem;

}int isEmpty(struct queue *pq){

if(pq->rear==-1) return 1;

else return 0;

}

Page 70: Data Structure Manual for BE students

100

int isFull(struct queue *pq){

if(pq->rear ==(MAX-1))return 1;

else return 0;

}void displayQueue(struct queue *pq){

int i;if(isEmpty(pq))

printf("\n The queue is empty");else{

printf("\n Elements of the queue from front to rear are : ");for(i=0;i<=pq->rear;i++)

printf("\t %d",pq->ele[i]);}

}

Page 71: Data Structure Manual for BE students

100

Program 8:

Write a program to simulate the working of circular queue of integers using an array. Provide the following operations: a] Insert b] Delete c] Display

#include<stdio.h>#include<conio.h>#define MAX 50

struct queue{ int ele[MAX]; int front,rear;};

void insert(struct queue *,int);int removeElement(struct queue *);int isEmpty(struct queue *);int isFull(struct queue *);void displayQueue(struct queue *);int menu();

void main(){

int element,choice;struct queue q;q.rear=MAX-1;q.front=MAX-1;

do{

choice=menu();

Page 72: Data Structure Manual for BE students

100

switch (choice) {

case 1: if(isFull(&q))

printf("\n The queue is full"); else {

printf("\n Enter the element to be inserted : "); scanf("%d",&element); insert(&q,element);

} break;

case 2: if(isEmpty(&q))

printf("\n Queue is empty"); else

printf("\n Element removed = %d",removeElement(&q)); break;

case 3: if(isEmpty(&q))

printf("\n The queue is empty"); else

printf("\n The queue is not empty"); break;

case 4: if(isFull(&q))

printf("\n The queue is full"); else

printf("\n The queue is not full"); break;

Page 73: Data Structure Manual for BE students

100

case 5: displayQueue(&q); break;

case 6: printf("\n We are now going to exit the queue program"); printf("\n Thank You"); break;

default: printf("\n Please enter your choice correctly"); break;

} }while(choice!=6); getch();}int menu(){

int ch; printf("\n\n\n\n Press any key to continue..........."); getch(); clrscr(); printf("\n Circular Queue Implementation Program"); printf("\n 1-Insert an element into the queue"); printf("\n 2-Remove an element from the queue"); printf("\n 3-Check whether the queue is empty"); printf("\n 4-Check whether the queue is full"); printf("\n 5-Display the elements of the queue"); printf("\n 6-Exit"); printf("\n Enter your choice (1-6) : \t"); scanf("%d",&ch); return ch;

}

Page 74: Data Structure Manual for BE students

100

void insert(struct queue *pq, int e){

if(pq->rear==MAX-1) pq->rear=0;

elsepq->rear++;

pq->ele[pq->rear]=e;}int removeElement(struct queue *pq){

if(pq->front==MAX-1)pq->front=0;

else pq->front++;

return (pq->ele[pq->front]);}int isEmpty(struct queue *pq){

if(pq->rear==pq->front) return 1;

else return 0;

}int isFull(struct queue *pq){

int i;if(pq->rear ==(MAX-1))

i=0;else

i=pq->rear+1;if(i==pq->front)

return 1;else

return 0;}

Page 75: Data Structure Manual for BE students

100

void displayQueue(struct queue *pq){

int i;if(isEmpty(pq))

printf("\n The queue is empty");else{

if(pq->front==MAX-1)i=0;

elsei=pq->front+1;

printf("\n Elements of the queue from front to rear are : ");while(i!=pq->rear){

printf("\t %d",pq->ele[i]);if(i==MAX-1)

i=0;else

i++;}printf("\t %d",pq->ele[i]);

}}

Page 76: Data Structure Manual for BE students

100

Program 9:

Write a C program using dynamic variables and pointers, to construct a singly linked list containing of the following information in each node: student ID(int), name(string) and semester(int). The operations to be supported are:

a] The insertion operation:i] At the front of the listii] At the back of the listiii] At any position of the list

b] Deleting a node based on student ID. If the specified node is not present in the list, an error message to be displayed.c] Searching a node based on student ID and update the information content. If the specified node is not present in the list, an error message to be displayed.d] Displaying all nodes of a file.

#include<stdio.h>#include<conio.h>#include<alloc.h>

struct node{int id;char name[20];int sem;struct node *next;};

void insertfront(struct node**,struct node**);void insertback(struct node**,struct node**);void insertpos(struct node**,struct node**);void rem(struct node**,struct node**);void search(struct node*,int);void display(struct node*);

Page 77: Data Structure Manual for BE students

100

void main(){int choice,id;struct node *f=NULL;struct node *r=NULL;clrscr();do

{printf("\n1.Insert front\n2.Insert back\n3.Insert at specified position\n4.delete id\

n5.Search id\n6.Display\n7.Exit\n");scanf("%d",&choice);switch(choice)

{case 1: insertfront(&f,&r);

break;case 2: insertback(&f,&r);

break;case 3: insertpos(&f,&r);

break;case 4: rem(&f,&r);

break;case 5: printf("\nEnter id to search...\n");

scanf("%d",&id);search(f,id);break;

case 6: display(f);break;

case 7: break;}

}while(choice!=7);getch();}

void insertfront(struct node**f,struct node **r){struct node*p;p=(struct node*)malloc(sizeof(struct node));printf("\nEnter name...\n");scanf("%s",p->name);

Page 78: Data Structure Manual for BE students

100

printf("Enter ID(integer)...\n");scanf("%d",&p->id);printf("Enter Semester...\n");scanf("%d",&p->sem);if(*f==NULL)

{(*f)=(*r)=p;p->next = NULL;}

else{p->next=(*f);(*f)=p;}

}

void insertback(struct node**f,struct node **r){struct node*p;p=(struct node*)malloc(sizeof(struct node));printf("\nEnter name...\n");scanf("%s",p->name);printf("Enter ID(integer)...\n");scanf("%d",&p->id);printf("Enter Semester...\n");scanf("%d",&p->sem);if((*f)==NULL)

{(*f)=(*r)=p;p->next=NULL;}

else{p->next=NULL;(*r)->next=p;(*r)=p;}

}

Page 79: Data Structure Manual for BE students

100

void insertpos(struct node**f,struct node**r){int pos,count=0;struct node*p,*q,*s;q=(*f);p=(struct node*)malloc(sizeof(struct node));printf("\nEnter postion to enter...\n");scanf("%d",&pos);printf("\nEnter name...\n");scanf("%s",p->name);printf("Enter ID(integer)...\n");scanf("%d",&p->id);printf("Enter Semester...\n");scanf("%d",&p->sem);while((q->next!=NULL)&&(count!=(pos-1)))

{count++;s=q;q=q->next;}

if(count<(pos-1)){printf("\nInvalid postion\n");}

else{p->next=s->next;s->next=p;if(p->next==NULL)

{(*r)=p;}}

}

void rem(struct node **f,struct node **r){int i;struct node *p,*q;printf("\nEnter ID(integer) to delete...\n");scanf("%d",&i);p=*f;

Page 80: Data Structure Manual for BE students

100

while((p->next!=NULL)&&(p->id!=i)){q=p;p=p->next;}

if(p->id==i){if((*f)==p && (*f)->next==NULL)

{printf("%s",p->name);}else if ((*r)==p)

{printf("%s",p->name);q->next=NULL;(*r)=q;}

else {printf("%s",p->name);q->next=p->next;}free(p);

}else

{printf("\nNODE NOT FOUND...\n");}}

void search(struct node *f,int i){printf("\nEnter ID to search...\n");while((f->next!=NULL)&&(f->id!=i))

{f=f->next;}

if (f->id==i){printf("\nRecord FOUND...\n");printf("\nNAME-%s\nSEMESTER-%d",f->name,f->sem);}

Page 81: Data Structure Manual for BE students

100

else{printf("\nSorry SEARCH FAILED...\n");}

}

void display(struct node *f){do

{printf("\n%s\t%d\t%d",f->name,f->id,f->sem);f=f->next;}while(f!=NULL);

}

Page 82: Data Structure Manual for BE students

100

Program 10.

Write a C program using dynamic variables and pointers to construct a stack of integers using singly linked list to perform the following operations:

a.Push b.Pop c.Display

It must print appropriate messages for Stack overflow and empty.

#include<stdio.h>#include<conio.h>struct node{

int info; struct node* next;

};int displayMenu();void push(struct node**,int);int pop(struct node**);int isEmpty(struct node**);void display(struct node**);void main(){

struct node *top; int element,choice; top=NULL; do {

choice=displayMenu(); switch (choice) {

case 1: printf("\n Enter the element to be pushed : "); scanf("%d",&element); push(&top,element); break;

case 2: if(isEmpty(&top))

printf("\n Stack is empty");

Page 83: Data Structure Manual for BE students

100

else printf("\n Element removed = %d",pop(&top)); break;

case 3: if(isEmpty(&top))

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

printf("\n Stack is not empty"); break;

case 4: display(&top); break;

case 5:printf("\n Exiting the program, thank you for using it");

break; default:

printf("\n Please enter your choice correctly");break;

} }while(choice!=5); getch();

}int displayMenu(){

int ch;printf("\n Press any key to continue...........");getch();clrscr();printf("\n Stack implementation using Singly Linked List");printf("\n 1-Push an element on the top of the stack");printf("\n 2-Pop out an element from the top of the stack");printf("\n 3-Check whether the stack is empty");printf("\n 4-Display the elements of the stack");printf("\n 5-Exit");printf("\n Enter your choice(1-5) : ");scanf("%d",&ch);return ch;

}

Page 84: Data Structure Manual for BE students

100

void push(struct node **t,int e){

struct node *p; p=(struct node*)malloc(sizeof(struct node)); if(p==NULL)

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

p->info=e; p->next=*t; *t=p;

}}int pop(struct node **t){

int poppedElement; struct node *p; p=*t; *t=p->next; poppedElement=p->info; free(p); return poppedElement;

}int isEmpty(struct node **t){

if(*t==NULL)return 1;

elsereturn 0;

}void display(struct node **t){

int i; struct node *p; if(isEmpty(t))

printf("\n The stack is empty");

Page 85: Data Structure Manual for BE students

100

else {

p=*t; printf("\n"); while(p!=NULL) {

printf("\t %d",p->info);p=p->next;

} }

}

Page 86: Data Structure Manual for BE students

100

Program 11.

Write a C program using dynamic variables and pointers to construct a queue of integers using a singly linked list to perform the following operations:

a. Insert b. Deletec. Display

It must print appropriate messages for queue full and empty.

#include<stdio.h>#include<conio.h>struct node{ int info; struct node *next;};void add(struct node **f,struct node **r,int a);int rem(struct node **f,struct node **r);int empty(struct node **f);void display(struct node **f);void main(){ struct node *f=NULL,*r=NULL; int choice,a,i,yes=1; clrscr(); do { printf("\n1:Add\n2:Remove\n3:Display"); printf("\n Enter choice"); scanf("%d",&choice); switch(choice) { case 1:

printf("Enter the element to be added "); scanf("%d",&a); add(&f,&r,a); break;

Page 87: Data Structure Manual for BE students

100

case 2: if(empty(&f))

printf("Queue Empty"); else {

i=rem(&f,&r);printf("%d",i);

} break;

case 3: display(&f); break;

default: printf("Wrong Choice "); exit(0);

} }while(yes); getch();}

void add(struct node **f,struct node **r,int a){ struct node *p; p=(struct node *)malloc(sizeof(struct node)); p->info=a; p->next=NULL; if(*f==NULL) *f=p; else (*r)->next=p; *r=p;}

int rem(struct node **f,struct node **r){ int i; struct node *p; p=*f; i=p->info;

Page 88: Data Structure Manual for BE students

100

(*f)=(*f)->next; if(*f==NULL) *r=NULL; free(p); return i;}

int empty(struct node **f){ if(*f==NULL) return 1; else return 0;}

void display(struct node **f){ struct node *p; if(*f==NULL) printf("\nQueue Empty"); else { p=*f; while(p!=NULL) { printf(" %d ",p->info); p=p->next; } }}

Page 89: Data Structure Manual for BE students

100

Program 12:

Write a C program to support the following operations on a doubly linked list where each node consists of integers.

a] Create a doubly linked list by adding each node at the front.b] Insert new nodes to the left of the node whose key value is read as an

inputc] Delete the node of the given data, if it is found, otherwise display

appropriate message.d] Display the contents of the file.

#include<stdio.h>#include<conio.h>#include<alloc.h>

struct node{int id;char name[20];int sem;struct node *succ;struct node *pred;};

void insertfront(struct node**,struct node**);void insertback(struct node**,struct node**);void insertpos(struct node**,struct node**);void rem(struct node**,struct node**);void search(struct node*,int);void display(struct node*);

void main(){int choice,id;struct node *f=NULL;struct node *r=NULL;clrscr();

Page 90: Data Structure Manual for BE students

100

do{printf("\n1.Insert front\n2.Insert back\n3.Insert at specified position\n4.delete id\

n5.Search id\n6.Display\n7.Exit\n");scanf("%d",&choice);switch(choice)

{case 1: insertfront(&f,&r);

break;case 2: insertback(&f,&r);

break;case 3: insertpos(&f,&r);

break;case 4: rem(&f,&r);

break;case 5: printf("\nEnter id to search...\n");

scanf("%d",&id);search(f,id);break;

case 6: display(f);break;

case 7: break;}

}while(choice!=7);getch();}

void insertfront(struct node**f,struct node **r){struct node*p;p=(struct node*)malloc(sizeof(struct node));printf("\nEnter name...\n");scanf("%s",p->name);printf("Enter ID(integer)...\n");scanf("%d",&p->id);printf("Enter Semester...\n");scanf("%d",&p->sem);

Page 91: Data Structure Manual for BE students

100

if(*f==NULL){(*f)=(*r)=p;p->succ = NULL;p->pred = NULL;}

else{p->succ=(*f);p->pred=NULL;(*f)=p;}

}

void insertback(struct node**f,struct node **r){struct node*p;p=(struct node*)malloc(sizeof(struct node));printf("\nEnter name...\n");scanf("%s",p->name);printf("Enter ID(integer)...\n");scanf("%d",&p->id);printf("Enter Semester...\n");scanf("%d",&p->sem);if((*f)==NULL)

{(*f)=(*r)=p;p->succ=NULL;p->pred=NULL;}

else{p->succ=NULL;p->pred=(*r);(*r)->succ=p;(*r)=p;}

}

Page 92: Data Structure Manual for BE students

100

void insertpos(struct node**f,struct node**r){int pos,count=0;struct node*p,*q,*s;q=(*f);p=(struct node*)malloc(sizeof(struct node));printf("\nEnter postion to enter...\n");scanf("%d",&pos);printf("\nEnter name...\n");scanf("%s",p->name);printf("Enter ID(integer)...\n");scanf("%d",&p->id);printf("Enter Semester...\n");scanf("%d",&p->sem);while((q->succ!=NULL)&&(count!=(pos-1)))

{count++;s=q;q=q->succ;}

if(count<(pos-1)){printf("\nInvalid postion\n");}

else{p->succ=s->succ;p->pred=s;s->succ->pred=p;s->succ=p;if(p->succ==NULL)

{(*r)=p;}}

}

void rem(struct node **f,struct node **r){int i;struct node *p,*q;printf("\nEnter ID(integer) to delete...\n");scanf("%d",&i);

Page 93: Data Structure Manual for BE students

100

p=*f;while((p->succ!=NULL)&&(p->id!=i))

{q=p;p=p->succ;}

if(p->id==i){if((*f)==p && (*f)->succ==NULL)

{printf("%s",p->name);}else if ((*r)==p)

{printf("%s",p->name);q->succ=NULL;(*r)=q;}

else {printf("%s",p->name);q->succ=p->succ;p->succ->pred=q;}free(p);

}else

{printf("\nNODE NOT FOUND...\n");}}

void search(struct node *f,int i){printf("\nEnter ID to search...\n");while((f->succ!=NULL)&&(f->id!=i))

{f=f->succ;}

if (f->id==i){printf("\nRecord FOUND...\n");printf("\nNAME-%s\nSEMESTER-%d",f->name,f->sem);}

Page 94: Data Structure Manual for BE students

100

else{printf("\nSorry SEARCH FAILED...\n");}

}

void display(struct node *f){do

{printf("\n%s\t%d\t%d",f->name,f->id,f->sem);f=f->succ;}while(f!=NULL);

}

Page 95: Data Structure Manual for BE students

100

Program 13:

Write a C program:a] To construct a binary search tree of integers.b] To traverse the tree using all methods i.e., inorder , preorder and

postorder.c] To display the elements in the tree.

#include<stdio.h>#include<conio.h>struct node{

int info;struct node *left,*right;

};void main(){ void freenode(struct node **r) ;void setright(struct node *p,int x);

void create(struct node **p) ;void inorder(struct node *r) ;void preorder(struct node *r);void setleft(struct node *p,int x);struct node* maketree(int x);void postorder(struct node *r);struct node *root=NULL;create(&root);preorder(root);inorder(root);postorder(root);freenode(&root);postorder(root);getch();

}struct node* maketree(int x){

struct node *r;r=(struct node*)malloc(sizeof(struct node));r->info=x;r->left=r->right=NULL;

Page 96: Data Structure Manual for BE students

100

return(r);}void setleft(struct node *p,int x){

if(p==NULL)printf("Invalid\n");else{

if(p->left!=NULL)printf("Invalid\n");elsep->left=maketree(x);

}}void setright(struct node *p,int x){

if(p==NULL)printf("Invalid\n");else{

if(p->right!=NULL)printf("Invalid\n");elsep->right=maketree(x);

}}

void create(struct node **r){

struct node *q,*p;char ch;int temp;printf("Enter number\n ");scanf("%d",&temp);*r=maketree(temp);do{

printf("enter the number\n");scanf("%d",&temp);

Page 97: Data Structure Manual for BE students

100

q=NULL;p=*r;while(p!=NULL && p->info!=temp){

q=p;if(temp<p->info)p=p->left;elsep=p->right;

} if(p->info==temp) printf("Duplicate %d num & hence discarded",temp); else if(temp<q->info) setleft(q,temp); else setright(q,temp); printf("do you want to continue\n"); fflush(stdin); scanf("%c",&ch); }while(ch=='y');

}void preorder(struct node *r){ printf("Preorder\n");

if(r!=NULL){

printf("%d\n",r->info);preorder(r->left);preorder(r->right);

}}void inorder(struct node *r){ printf("Inorder\n");

if(r!=NULL){

inorder(r->left);printf("%d\n",r->info);inorder(r->right);

}

Page 98: Data Structure Manual for BE students

100

}void postorder(struct node *r){ printf("post order\n");

if(r!=NULL){postorder(r->left);postorder(r->right);printf("%d\t",r->info);}

}void freenode(struct node **r){ struct node *p=*r; printf("freenode\n"); freenode((*r)->left); free(p); freenode((*r)->right);}

Page 99: Data Structure Manual for BE students

100

Program 14:

Write a recursive C program fora] Searching an element on a given list of integers using binary search

method.

#include<stdio.h>#include<conio.h>#define MAX 50int binarySearch(int [],int,int,int);void main(){

int a[MAX],i,n,found,element; clrscr(); printf("\n Enter the number of elements : "); scanf("%d",&n); printf("\n Now enter the elements one by one in ascending order : "); for(i=0;i<n;i++) {

printf("\n a[%d] = ",i); scanf("%d",&a[i]);

} printf("\n Enter the element to be searched : "); scanf("%d",&element); found=binarySearch(a,0,n-1,element); if(found==-1)

printf("\n The element is not found"); else

printf("\n The element is found at position %d",found); getch();

}int binarySearch(int arr[],int low,int high,int key){

int mid;if(low>high)

return -1;mid=(low+high)/2;if(arr[mid]==key)

return mid;

Page 100: Data Structure Manual for BE students

100

else

{ if(key>arr[mid])

binarySearch(arr,mid+1,high,key); else

binarySearch(arr,low,mid-1,key);}

}

b] Solving the tower of Hanoi problem.

#include<stdio.h>#include<conio.h>#include<dos.h>void towersOfHanoi(int n,char source,char destination,char temp);void main(){

int numOfDiscs; clrscr(); printf("\n Enter the number of discs : "); scanf("%d",&numOfDiscs); towersOfHanoi(numOfDiscs,'s','d','t'); getch();

}void towersOfHanoi(int n,char source,char destination,char temp){static int i;

if(n>0) {

towersOfHanoi(n-1,source,temp,destination);delay(1000);

printf("\n Move disc %d from %c to %c %d",n,source,destination,i++);towersOfHanoi(n-1,temp,destination,source);

}}

___________________