mc0068 data structures using c

21
DATA STRUCTURE USING C+ AS SIGNMENT-1 1.Discuss the various types of data structure applications. ? Ans: Data structure is a particular way of storing and organizing data in a computer so that it can be used efficiently. Different kinds of data structures are suited to different kinds of applications, and some are highly specialized to specific 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. Data structures provide a means to manage huge amounts of data efficiently, such as large databases and internet indexing services. Usually, efficient data structures are a key to designing efficient algorithms. Some formal design methods and programming languages emphasize data structures, rather than algorithms, as the key organizing factor in software design. Types Of Data Stracture: Arrays The simplest data structures in Java are the primitive types byte, short, int, long, float, double, char and boolean. More correctly, we should refer to the corresponding Byte Integer Float wrapper classes etc. Each instance of these is capable of storing a data item of the corresponding type, with public methods for manipulating that item. Page | 1

Upload: ajay-dogney

Post on 06-Mar-2015

505 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

ASSIGNMENT-1

1.Discuss the various types of data structure applications. ?

Ans: Data structure is a particular way of storing and organizing data in a computer so that it can be used efficiently.

Different kinds of data structures are suited to different kinds of applications, and some are highly specialized to specific 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. Data structures provide a means to manage huge amounts of data efficiently, such as large databases and internet indexing services. Usually, efficient data structures are a key to designing efficient algorithms. Some formal design methods and programming languages emphasize data structures, rather than algorithms, as the key organizing factor in software design.

Types Of Data Stracture:

Arrays

The simplest data structures in Java are the primitive types byte, short, int, long, float, double, char and boolean. More correctly, we should refer to the corresponding

Byte Integer Float

wrapper classes etc. Each instance of these is capable of storing a data item of the corresponding type, with public methods for manipulating that item.

The expression ``data structure'', however, is usually used to refer to more complex ways of storing and manipulating data, such as arrays, stacks, queues etc. We begin by discussing the simplest, but one of the most useful data structures, namely the array.

Stacks

A stack is a data-structure providing two basic methods, usually called push and pop. It is a way of buffering a stream of objects, in which the last in is first out (LIFO). The objects could be data items for processing, instructions pending execution, etc.

A common picture is that of a pile of plates. The first plate begins the pile. The next is placed on top of the first, and the next on top of that, and so on. A plate may be removed from the pile at any time, but only from the top. The order of pushing plates onto the pile or popping them from the top is arbitrary. There will always be a certain number of plates on the pile. Pushing a plate onto the pile increases the number by one; popping a plate decreases it by

Page | 1

Page 2: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

one. But naturally you cannot pop a plate off an empty pile. Nor can you push a plate onto a full one--at least if there is a maximum number of plates the pile can hold. So these two conditions need to be monitored.

Queues

A queue is similar to a stack, except that you join the queue at one end and leave it at the other. In other words, it is a way of buffering a stream of objects so that the first in is first out (FIFO). The objects could be any data items awaiting processing, print requests, instructions awaiting execution, etc.

We shall again use an array for storing the items in the queue. This time, however, we shall need two pointers, one to indicate where the next item to be placed in the queue should be stored, which we call top, and another to indicate the location of the next item to retrieved which, we call base. Another new feature is that we shall treat the underlying array as a circular buffer. Thus top and base are now always incremented, but when either reaches the upper bound of the array, it wraps round back to the beginning.

Data Stracture Applocations:

1.) Linked Implementations

We previously implemented stacks and queues by means of arrays. At the same time we noted that the Stack interface, for instance, might be implemented in other ways. That was the purpose of separating the specification of the interface from any particular implementation. To recall, here is the interface again.

public interface Stack { public boolean isEmpty(); public void push(Object item); public Object pop();}

One of the problems that we had to deal with, when using arrays, was the need to grow the array dynamically if it threatened to overflow; and this involved copying the old array into the new one. The present solution is to create a single new storage element for each item pushed onto the stack. This is assumed to be recovered by the garbage collector once that item is popped.

2.) Enumerations and Iterators

Enumerations

It is frequently useful to be able to extract the elements of a vector, list, tree, graph etc. one at a time successively, and to do something with them. It might simply be to print them out to the screen or to a file. There is a standard way of approaching this problem in Java, which makes use of the Enumeration interface in the java.util package:

public interface Enumeration { boolean hasMoreElements();

Page | 2

Page 3: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

Object nextElement();}

The hasMoreElements method of an enumeration returns true or false depending on whether or not the enumeration is exhausted. The nextElement method returns the next element in the enumeration, if there is a next element, so that successive calls to this method enumerate the elements. The nextElement method should throw a NoSuchElementException if there are no more elements to enumerate. An implementation of the Enumeration interface must implement these two methods.

Note that the Enumeration interface only specifies what an enumeration of a collection must provide. It is up to the implementer of that collection to actually provide it. The Vector class, however, in java.util does provide an enumeration method called elements. The following code will therefore enumerate the elements of a vector v.

Enumeration e = v.elements();while (e.hasMoreElements()) { System.out.println(e.nextElement());}This declares a variable e of type Enumeration and assigns to it the enumeration obtained by calling the elements method of the Vector class.

The enumeration e is tied to a particular vector v when it is initialised; there is no need for any further reference to the vector v. The enumeration e enumerates the elements of v sequentially by successive calls to e.nextElement. Note that you cannot change direction and enumerate backwards at some point. Nor can you make any change in a collection by means of the enumeration methods. Changes could be made to the collection, in the course of an enumeration, by some other methods. But this is dangerous. A specific danger lies in removing from the collection the item that happens to be the current one in the enumeration. In that case the results are unpredictable.

Iterators

Current versions of Java provide an extended concept of enumeration through the Iterator interface. This takes the place of enumeration in the Collections framework.

The additional functionality is that an iterator allows the caller to remove elements from the underlying collection during the iteration. The Iterator interface is defined by

public interface Iterator { boolean hasNext(); Object next(); void remove();}The first two methods are the same as for enumerations, except that they have shorter names.

The remove method is new. It removes from the collection the element returned by the last call to next. For example, the following removes all elements of the vector v:

Iterator i = v.iterator();

Page | 3

Page 4: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

while (i.hasNext()) { i.next(); i.remove();}The remove method may only be called once per call to next. An implementation must ensure that an IllegalStateException is thrown if either (1) the next method has not yet been called or (2) the remove method has already been called since the last call to next. You could think of a sequence of calls to next and remove as defining a string such as NRNNNRNNRN in an alphabet of two characters N and R. Then a string is well-formed provided every occurrence of R is immediately preceded by an occurrence of N. The code in the example above corresponds to the string NRNR ...NR.

The remove method is optional. An UnsupportedOperationException must be thrown if the Iterator does not support this operation. The view is expressed in the Collections framework that new implementations should consider using Iterator in preference to Enumeration . This is no real restriction, in view of the optionality of remove, and generally we shall follow this advice.

Linked Lists

We have seen the usefulness of linked representations for implementing stacks and queues. We now introduce a fuller implementation of singly linked lists. The class will implement the following methods:public class LinkedList { public boolean isEmpty(); public int size(); public void addFirst(Object item); public Object firstItem(); public void removeFirst(); public boolean contains(Object item); public void reverse(); public Iterator iterator(); public boolean equals(Object other); public String toString();}

The approach here is deliberately simple. A list will be represented internally by a single ListNode constituting the head of the list. We shall use the device of setting this to be null to indicate an empty list. A more elegant approach to the problem of representing empty structures, but one which is a little less straightforward, will be adopted later when we deal with binary search trees.

Page | 4

Page 5: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

2. Illustrate the C program to represents the Stack Implementation on POP and PUSH

operation.

Ans:2

#include<studio.h>#include<conio.h>#define Max 5Int Staff [Max], top=-1;Void display(){If ((top==-1 || (top==0)){Printf(“\n stack is full\n”);}Else{Printf(“\n stack elements are\n”);For(int i=top-1;i>=0;i--)}}void push(){int ele;char ch;it(top-=-1)top=0;do{If (top>=5){Printf(“\n stack is full”);Break;}Else{Clrscr();Printf(“\n enter the element to be insearted\n”);Scanf(“%d”, &ele);Staff(top++)=eledisplay();}Printf(“\n Do u want to add more elements:?\n”);Scanf(“\n%c”, &ch);}While ((ch==’y’ ||(ch==’Y’));}void pop(){If ((top==-1)||(top==0)

Page | 5

Page 6: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

{Printf(“\nstack is under flow\n”);}Else{Printf(“%d is deleted fro stack\n”,Staff(--top]”);display();}}

Void main(){clrscr();char c;int choice;do{cirscr();printf(“\n enter the choice\n”);printf(“1->push\n”);printf(“2-pop\n”);scant(“%d”, &choice);if(choice==1)

push();elshif(choice==2)pop();elseprintf(“\in valid choice”);printf(“\n do u want to continue:?”);scanf(“\n%c”, &c);}While{(c==’y’)||(c==’Y’));

}

3. Show the result of inserting 3, 1, 4, 5, 2, 9, 6, 8 into a

a) bottom-up splay tree

b) top-down splay tree.

Ans:3 Splay Trees

We shall describe the algorithm by giving three rewrite rules in the form of pictures.  In these pictures, x is the node that was accessed (that will eventually be at the root of the tree).  By looking at the local structure of the tree defined by x, x’s parent, and x’s grandparent we decide which of the following three rules to follow.  We continue to apply the rules until x is at the root of the tree:

Page | 6

Page 7: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

Notes

1)    Each rule has a mirror image variant, which covers all the cases.

2)    The zig-zig rule is the one that distinguishes splaying from just rotating x to the root of the tree.

3)    Top-down splaying is much more efficient in practice.

The Basic Bottom-Up Splay Tree• A technique called splaying can be used so a logarithmic amortized bound can beachieved.• We use rotations such as we’ve seen before.• The zig case.o Let X be a non-root node on the access path on which we are rotating.o If the parent of X is the root of the tree, we merely rotate X and the root as shownin Figure 2.

Figure 2 Zig Caseo This is the same as a normal single rotation.• The zig-zag case.o In this case, X and both a parent P and a grandparent G. X is a right child and P isa left child (or vice versa).

Page | 7

Page 8: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

o This is the same as a double rotation.o This is shown in Figure 3.The zig-zig case.o This is a different rotation from those we have previously seen.o Here X and P are either both left children or both right children.o The transformation is shown in Figure 4.o This is different from the rotate-to-root. Rotate-to-root rotates between X and Pand then between X and G. The zig-zig splay rotates between P and G and X andP.Figure 4 Zig-zig Case

• Given the rotations, consider the example in Figure 5, where we are splaying c.

Top-Down Splay Trees• Bottom-up splay trees are hard to implement.• We look at top-down splay trees that maintain the logarithmic amortized bound.o This is the method recommended by the inventors of splay trees.• Basic idea – as we descend the tree in our search for some node X, we must take thenodes that are on the access path, and move them and their subtrees out of the way. Wemust also perform some tree rotations to guarantee the amortized time bound.• At any point in the middle of a splay, we have:o The current node X that is the root of its subtree.o Tree L that stores nodes less than X.o Tree R that stores nodes larger than X.• Initially, X is the root of T, and L and R are empty.• As we descend the tree two levels at a time, we encounter a pair of nodes.o Depending on whether these nodes are smaller than X or larger than X, they areplaced in L or R along with subtrees that are not on the access path to X.When we finally reach X, we can then attach L and R to the bottom of the middle tree,and as a result X will have been moved to the root.• We now just have to show how the nodes are placed in the different tree. This is shown

Page | 8

Page 9: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

below:o Zig rotation – Figure 7

Zig-Zig – Figure 8

Zig-Zag – Figure

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

Page | 9

Page 10: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

ASSIGNMENT-2

1. Define Tree ? Explain Binary tree with its properties.

Ans: Tree

A tree consists of a finite set of elements, called nodes and a finite set of directed lines, called branches that connect the nodes. The number of branches associated with a node is the degree of the node. When the branch is directed towards the node, it is an indegree branch; When the branch is directed away from the node it is an outdegree branch, the sum of outdegree and indegree branches equals to the degree of the node.

Binary Tree

In computer science, a binary tree is a tree data structure in which each node has at most two children. Typically, the child nodes are called left and right. Binary trees are commonly used to implement binary search trees and binary heaps.

A Binary tree T is defined as a finite set of elements, called nodes such that,

a. T is empty, called NULL tree or empty tree

b. T contains a distinguished node R, called Root of t and the remaining nodes of T from an ordered pair of disjoint binary Tree T1 and T2.

c. The node contains max two children.

A binary tree is a tree in which no node can have more than two subtrees. In other words, a node can have zero, one, or two subtrees. In other words, a tree in which every parent has one or two children (but not more than that) is called as binary tree.

The “root” component of binary tree is the forefather of all children. But it can have only upto two children one “right” child and “left” child. These children can become fathers and each can produce only two children. In fact a child can become a father, grandfather, great grandfather and son. Fig shows five binary trees all with three nodes.

We can have binary trees with any number of nodes.

2. Explain Insert/Delete a node at the rear, front end from circular singly linked list.

Page | 10

Page 11: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

Ans: A singly linked circular list is a linked list where the last node in the list points to the first node in the list. A circular list does not contain NULL pointers.

With a circular list, a pointer to the last node gives easy access also to the first node, by following one link. Thus, in applications that require access to both ends of the list (e.g., in the implementation of a queue), a circular structure allows one to handle the structure by a single pointer, instead of two.

A circular list can be split into two circular lists, in constant time, by giving the addresses of the last node of each piece. The operation consists in swapping the contents of the link fields of those two nodes. Applying the same operation to any two nodes in two distinct lists joins the two list into one. This property greatly simplifies some algorithms and data structures, such as the quad-edge and face-edge.

The simplest representation for an empty circular list (when such a thing makes sense) is a null pointer, indicating that the list has no nodes. With this choice, many algorithms have to test for this special case, and handle it separately. By contrast, the use of null to denote an empty linear list is more natural and often creates fewer special cases.

Insert a node at the rear end:

Consider the list contains 4 nodes and last is a pointer variable that contains the address of the last node.

Let us insert the item 80 at the end of this list.

Step 1:Obtain a free node temp from the availability list and store the item in info field. This can be accomplished using the following statementsTemp=getnode();Temp->info=item;

Step 2: Copy the address of the first node(i.e. last->link) into link field of newly obtained node temp and the statement to accomplish this task isTemp-> link=last->linkStep 3: Establish a link between the newly created node temp and the last node. This is achieved by copying the address of the node temp into link field of last node. The corresponding code for this is

Page | 11

50 20 45 10

Page 12: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

Last->link=temp;

Step 4: The new node is made as the last node using the statement:Return temp;

These steps have designed by assuming the list already exists.

Function to insert an item at the rear end of the list.NODE insert_rear(int item, NODE last){NODE temp;Temp=getnode();Temp->info=item;If(last==NULL)Last=temp;ElseEmp->link=last->link;Last->link=temp;Retrun temp;}

Insert a node at the front end:

Consider the list contains 4 nodes and a pointer variable last contains address of the last node.

Step 1: To insert an item 50 at the front of the list, obtain a free node temp from the availability list and store the item in info field. This can be accomplished using the following statements

Temp=getnode();Temp->info=item;

Step 2: Copy the address of the first node(i.e. last->link) into link field of newly obtained node temp and the statement to accomplish this task isTemp->link=last->link.

Step 3: Establish a link between the newly created node temp and the last node. This is achieved by copying the address of the node temp into link field of last node. The corresponding code for this isLast->link=temp;

Page | 12

20 45 10 80

Page 13: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

Now, an item is successfully inserted at the front of the list. All these steps have been designed by assuming the list is already existing. If the list is empty, make temp itself as the last node and establish a link between the first node and the last node. Repeatedly insert the items using the above procedure to create a list. Function to insert an item at the front end of the list. NODE insert_front(int item, NODE last){NODE temp;Temp=getnode();Temp->info=item;If(last==NULL)Last=temp;Elsetemp->link=last->link;Last->link=temp;Return last;}

3. a. Compare and contrast DFS and BFS and DFS+ID approaches

b. Discuss how Splay Tree differs from a Binary Tree? Justify your answer with

appropriate example.

Ans:3 a)

Once you’ve identified a problem as a search problem, it’s important to choose the right type of search. Here are some information which may be useful while taking the decision.

Search Time Space When to use

DFS O(c^k) O(k)Must search tree anyway, know the level the answers are on, or you aren’t looking for the shallowest number.

BFS O(c^d) O(c^d)Know answers are very near top of tree, or want shallowest answer.

DFS+ID O(c^d) O(d)Want to do BFS, don’t have enough space, and can spare the time.

d is the depth of the answer k is the depth searched d <= k

Remember the ordering properties of each search. If the program needs to produce a list sorted shortest solution first (in terms of distance from the root node), use breadth first search or iterative deepening. For other orders, depth first search is the right strategy.

If there isn’t enough time to search the entire tree, use the algorithm that is more likely to find the answer. If the answer is expected to be in one of the rows of nodes closest to the root, use

Page | 13

Page 14: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

breadth first search or iterative deepening. Conversely, if the answer is expected to be in the leaves, use the simpler depth first search. Be sure to keep space constraints in mind. If memory is insufficient to maintain the queue for breadth first search but time is available, use iterative deepening.

B) Binary Tree:

A binary tree is simply a tree in which each node can have at most two children.

A binary search tree is a binary tree in which the nodes are assigned values, with the following restrictions ;

-No duplicate values. -The left subtree of a node can only have values less than the node -The right subtree of a node can only have values greater than the node

and recursively defined; -The left subtree of a node is a binary search tree. -The right subtree of a node is a binary search tree.

Splay Trees

We shall describe the algorithm by giving three rewrite rules in the form of pictures.  In these pictures, x is the node that was accessed (that will eventually be at the root of the tree).  By looking at the local structure of the tree defined by x, x’s parent, and x’s grandparent we decide which of the following three rules to follow.  We continue to apply the rules until x is at the root of the tree:

Notes

1)    Each rule has a mirror image variant, which covers all the cases.

2)    The zig-zig rule is the one that distinguishes splaying from just rotating x to the root of the tree.

3)    Top-down splaying is much more efficient in practice.

Page | 14

Page 15: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

Consider the following class of binary-tree based algorithms for processing a sequence of requests:

on each access we pay the distance from the root to the accessed node.

Arbitrary rotations are also allowed, at a cost of 1 per rotation.

For a sequence Sigma, let C(T,Sigma) be the cost of the optimal algorithm in this class for processing a sequence Sigma starting from tree T. Then the cost of splaying the sequence (starting from any tree) is O(C(T,Sigma) + n).

What about dynamic operations that change the set of elements in the tree?  Here’s how we can do Insertion, Join, and Deletion.

Insertion

Say we want to insert a new item e.  Proceed like ordinary binary tree insertion, but stop short of linking the new item e into the tree.  Let the node you were about to link e to be called p.  We splay p to the root.  Now construct a tree according to one of the following pictures:

depending on if the item in e is before or after p.

Let’s analyze this when all the weights are 1.  The amortized cost of the splay is O(log n) according to the access lemma.  Then we have to pay the additional amortized cost which equals the potential of the new root.  This is log(n+1).  So the amortized cost of the whole thing is O(log(n)).

An alternative insertion algorithm is to do ordinary binary tree insertion, and then simply splay the item to the root.  This also has efficient amortized cost, but the analysis is a tiny bit more complicated.

Join

Here we have two trees, say, A and B.  We want to put them together with all the items in A to the left of all the items in B. This is called the "Join" operation.  This is done as follows.  Splay the rightmost node of A.  Now make B the right child of this node.  The amortized cost of the operation is easily seen to be O(log n) where n is the number of nodes in the tree after joining.  (Just assign uniform weights to all the nodes, as we did in the Insertion analysis.)

Deletion

Page | 15

Page 16: MC0068 Data Structures Using C

DATA STRUCTURE USING C+

To delete a node, x, simply splay it to the root and then Join its left and right sub-trees together as described above.  The amortized cost is easily seen to be O(log n), where n is the size before the deletion.

Page | 16