ds lab handouts
DESCRIPTION
TRANSCRIPT
Data Structures Lab Handouts 2
Contents
Lab 1: C++ Review
Lab 2: Implementation of Stack
Lab 3: Recursion
Lab 4: Implementation of Queue
Lab 5: Implementation of Priority Queue
Lab 6: Implementation of Linked List
Lab 7: Application of Linked List
Lab 8: Implementation of Binary Tree
Lab 9: Implementation of Binary Search Tree
Lab 10: Implementation of Graph
Lab 11: Application of Graph
Lab 12-13: Using Standard Template Library
Lab 14-15: Implementation of Sorting Techniques
Lab 16: Implementation of Searching Techniques
Data Structures Lab Handouts 3
Lab 1
C++ Review
Fundamental Data Types
Category Available data types
Boolean bool
Character char signed char unsigned char
Signed integer short int long
Unsigned integer unsigned short unsigned unsigned long
Floating point float double long double
Named Constants
Cannot be changed during program execution
C style constants:
#define zero 0
C++ style constants:
const int zero = 0;
const float PI = 3.14159;
Type Aliases
typedef float real;
“real” may now be used in place of “float”
If more precision (i.e. more digits) needed, can replace this one statement by
typedef double real;
Data Structures Lab Handouts 4
Arithmetic Expressions
Binary operators: !, ", *, /, %
Unary operators: +, ", ++, " "
Usual precedence rules apply
Unary operators are right-associative: ++ X " " means ++ (X " ")
Binary operators are left-associative: A / B * C means (A / B) * C
Relational & Logical Expressions
Relational operators: <, >, <=, >=
Equality operators: = =, !=
Logical operators:
Unary: !
Binary: &&, | |
Examples:
(5 = = 4) && (a < b) // false, since 5 != 4
(5 = = 5) | | (a < b) // true, since 5 = = 5
Conditional Expressions
expression ? expression : expression
Executed like if " else statement, but has a value
Example:
larger = (A > B) ? A : B;
Data Structures Lab Handouts 5
Functions
int max1( int X, int Y )
{
return (X > Y) ? X : Y; // result returned as function value
}
void max2( int X, int Y, int &Larger )
{
Larger = (X > Y) ? X : Y; // result returned by reference
}
void max3( int X, int Y, int *Larger )
{
*Larger = (X > Y) ? X : Y; // result returned by pointer
}
Structures
struct Student
{
char name[30];
int section;
float total_points;
};
Student class[30];
Student *ptr = class;
class[0].name is the same as ptr-> name
Initialization:
Student Ali = {“Ali Ahmed”, 8, 592.5};
Structures may be copied with “=”
Structures may be passed to functions by value
Structures may be returned from functions
Structures may be nested
Arrays of structures may be defined
Data Structures Lab Handouts 6
C++ Classes
The class is the capsule that is used to encapsulate an abstract data type.
# A class defines a new data type. You can create many objects of this type.
# A class is composed of one or more members.
# Members are:
o data items (members)
o functions (member functions)
# Class definition usually placed in an include (.h) file for ease of use.
A Complex Number Class
#include <iostream>
#include <math.h>
using namespace std;
class Complex
{ private:
float re;
float im;
public:
Complex(float r,float i) {re = r; im = i;}
Complex(float r) {re = r; im = 0.0;}
~Complex() {};
double Magnitude() // calculate magnitude
{
return sqrt(re*re + Imag()*Imag()); }
float Real() {return re;} // return real part
float Imag() {return im;} // return imaginary part
Complex operator+(Complex b)
{return Complex(re + b.re, im + b.im);}
Complex operator=(Complex b)
{re = b.re;im = b.im; return *this;}
};
Data Structures Lab Handouts 7
int main()
{
Complex a(1.0,1.0);
Complex *b = new Complex(5.0);
Complex c(0,0);
cout << "a real = " << a.Real() << “ a imaginary = “ << a.Imag() << endl;
cout << "b real = " << b->Real() << “ b imaginary = “ << b->Imag() << endl;
c = a + (*b);
cout << "c real = " << c.Real() << “ c imaginary = “ << c.Imag() << endl;
delete b;
return 0;
}
Exercise:
Add a function to multiply two complex numbers using operator overloading.
Data Structures Lab Handouts 8
Function Templates
Function templates are special functions that can operate with generic types. This allows
us to create a function template whose functionality can be adapted to more than one type
without repeating the entire code for each type.
In C++ this can be achieved using template parameters. A template parameter is a special
kind of parameter that can be used to pass a type as argument: just like regular function
parameters can be used to pass values to a function, template parameters allow to pass also
types to a function. These function templates can use these parameters as if they were any
other regular type.
The format for declaring function templates with type parameters is:
template <class identifier> function_declaration;
Example:
// function template
#include <iostream>
using namespace std;
template <class T>
T GetMax (T a, T b)
{
T result;
result = (a>b)? a : b;
return (result);
}
int main () {
int i=5, j=6, k;
long l=10, m=5, n;
k=GetMax<int>(i, j);
n=GetMax<long>(l, m);
cout << k << endl;
cout << n << endl;
return 0;
}
Data Structures Lab Handouts 9
Class Templates
We also have the possibility to write class templates, so that a class can have members that
use template parameters as types. For example:
template <class T>
class mypair
{
T values [2];
public:
mypair (T first, T second)
{
values[0]=first; values[1]=second;
}
};
This class serves to store two elements of any valid type. For example, if we wanted to
declare an object of this class to store two integer values of type int with the values 115
and 36 we would write:
mypair<int> myobject (115, 36);
this same class would also be used to create an object to store any other type:
mypair<double> myfloats (3.0, 2.18);
Data Structures Lab Handouts 10
Class Template Example 1
#include <iostream>
using namespace std;
template <class T>
class mypair
{
T a, b;
public:
mypair (T first, T second)
{a=first; b=second;}
T getmax ();
};
template <class T>
T mypair<T>::getmax ()
{
T retval;
retval = a>b? a : b;
return retval;
}
int main ()
{
mypair <int> myobject (100, 75);
cout << myobject.getmax();
return 0;
}
Exercise:
Add a function to compute minimum of two numbers in the above class.
Data Structures Lab Handouts 11
Class Template Example 2
#include <iostream>
using namespace std;
template <class T, int N>
class mysequence
{
T memblock [N];
public:
void setmember (int x, T value);
T getmember (int x);
};
template <class T, int N>
void mysequence<T,N>::setmember (int x, T value)
{
memblock[x]=value;
}
template <class T, int N>
T mysequence<T, N>::getmember (int x)
{
return memblock[x];
}
int main ()
{
mysequence <int,5> myints;
mysequence <double,5> myfloats;
myints.setmember (0,100);
myfloats.setmember (3, 3.1416);
cout << myints.getmember(0) << '\n';
cout << myfloats.getmember(3) << '\n';
return 0;
}
Data Structures Lab Handouts 12
File Input/Output
#include <fstream> // C++ file I/O
Files are classified as containing either text (i.e. characters) or binary data
May read and write numbers from/to text files: C++ does the necessary translations
Character Input with fstream
#include <fstream>
ifstream infile; // define infile
infile.open( “MyData” ); // open “MyData” file
if( !infile )
cout << “Can’t open ” << “MyData” << endl;
infile >> chr; // read character from “MyData” file into chr
infile.close( ); // close “MyData” file
Useful Functions for Character Input
infile.ignore( n ); // skip next n input characters
chr = infile.get( ); // same as infile >> chr
while( infile.get( ) != ‘\n’ ) ... // loop until end of line
while( infile.get( ) != EOF ) ... // loop until end of file
while( infile >> chr ) ... // loop until end of file
Data Structures Lab Handouts 13
Character Output with fstream
#include <fstream>
ofstream outfile( “MyOut” ); // define & open outfile
outfile << chr; // write chr to “MyOut” file
outfile.put( chr ); // same as outfile << chr
outfile.close( ); // close “MyOut” file
Numeric I/O with Text File and fstream
If numeric data is read to/written from a variable of numeric type, then >> translates the
data into the appropriate numeric representation
Example:
If “MyData” file contains
5280 2.718 3.141592653
Then
int ftPerMile; float e; double pi;
infile >> ftPerMile >> e >> pi;
stores input as int, float, and double
Data Structures Lab Handouts 14
Example: To count number of characters in a text file.
#include <iostream>
#include <fstream>
using namespace std;
int main(void)
{
ofstream outFile;
outFile.open("fout.txt");
ifstream inFile("fin.txt");
char ch;
int count = 0;
while(inFile.get(ch))
{
outFile << ch;
count++;
}
outFile << "\n\n Character count = " << count << endl;
inFile.close();
outFile.close();
return 0;
}
Data Structures Lab Handouts 15
Lab Exercise 1.1
a) Declare a class named House for a real estate locator service. The following information
should be included:
Owner: (a string of up to 20 characters)
Address: (a string of up to 20 characters)
Bedrooms: (an integer)
Price (floating point)
b) Declare available to be an array of 100 objects of class House.
c) Write a function to read values into the members of an object of House.
d) Write a driver program to test the data structures and the functions you have developed.
The driver program should read in house entries into the available array. After the code
for entering the data, you should write code to output the data that you have entered to
verify that it is correct.
Your program should look like this:
Enter Owner : M. Khan
Enter Address : G-9, Islamabad
Number of Bedrooms ? : 4
Price : 4500000
Enter another house? N
The output should look like:
Owner Address Bedrooms Price
M. Khan G-9, Islamabad 4 4500000
Data Structures Lab Handouts 16
Extra Credit:
The real estate company is very happy with the program that was developed in the earlier
to track their listings. Now they want to add some features to the processing.
Additional features:
- Search for a house that meets a potential buyer's specifications for the following:
# The price is not more than a specified amount
# The size is not less than a specified number of bedrooms
# The house with lowest price
# The largest house (with maximum number of bedrooms)
# In a given city
# With best ratio price/size
# The user may enter a "?" to indicate no preference.
- Print all the entries that meet the buyer’s need.
Data Structures Lab Handouts 17
Lab Exercise 1.2
Assume that a file contains the midterm1, midterm2 and final exam scores and names of
students of a class. Write a C++ program to read the input file and produce an output file
containing the original and average scores for each student. Suppose that the weights of
the exams are as follows:
midterm1 – 25%
midterm2 – 25%
final – 50%.
The average score of a student is calculated using the formula:
FINMTMT 5.0225.0125.0 !!
Solution:
#include <iostream>
#include <fstream>
using namespace std;
int main ( )
{ char name[10];
float mt1, mt2, final, avg;
ifstream fin ; //Create file input stream object
ofstream fout ; //Create file output stream object
fin.open ( "input.dat") ; //Open input file
fout.open ( "output.dat"); //Open output file
while (!fin.eof()) //Read data from input file
{
fin >> name >> mt1 >> mt2 >> final;
avg = 0.25*mt1 + 0.25*mt2 + 0.5*final ;
fout << name << '\t' << avg << endl ; //Write result to output file
}
fin.close ( ) ; //Close input file
fout.close ( ) ; //Close output file }
Data Structures Lab Handouts 18
Exercise 1.3
You will write a student grades "database" program. It will read data of students from a
file and will let the user perform various operations on the data. You will have to store the
student data in an array of objects.
Input:
The input file will look like:
4
3
Hassan Khan 99 87 90
Sara Nazir 90 98 99
Ali Zaidi 55 43 0
Raza Ahmad 100 100 100
That is:
number of students
number of grades (per student)
Student name grade grade ... grade
Student name grade grade ... grade
Data structure:
You will store all the information in an array of "student" objects. You may use the
following class definition:
class student {
private:
char name[30];
int lab[10];
float average;
public:
.
.
.
};
Data Structures Lab Handouts 19
Your program should work as follows:
# Ask the user for the filename and open the file.
# Read in the input from the file and store it in the student array.
# Compute and store an average for every student.
# Go into a menu loop giving the user the following options:
1. Print all user names, all grades, and averages.
2. Find a student and print his/her information.
3. Quit.
# For option 1 the user doesn't have to give you any extra information.
# For option 2, finding a student, your program must ask the user for the name of the
student he/she wishes to find; read in the name; perform a sequential search for that
name; and if found, print all that student's info.
Data Structures Lab Handouts 20
Lab 2
Implementation of Stack
Stack ADT Operations
Initialize -- Sets stack to an empty state.
IsEmpty -- Determines whether the stack is currently empty.
IsFull -- Determines whether the stack is currently full.
Push (ItemType newItem) -- Adds newItem to the top of the stack.
Pop (ItemType& item) -- Removes the item at the top of the stack and returns it in item.
Implementation of Stack Using Static Array
//----------------------------------------------------------
// SPECIFICATION FILE (stack.h)
//----------------------------------------------------------
#define MAX_ITEMS 100
typedef int ItemType;
class Stack {
public:
Stack ( ); // Default constructor.
int IsEmpty( ) const;
int IsFull( ) const;
void Push( ItemType newItem );
void Pop( ItemType& item ); // item is a copy of removed element.
private:
int top;
ItemType items[MAX_ITEMS]; // array of ItemType
};
Data Structures Lab Handouts 21
//-------------------------------------------------------
// IMPLEMENTATION FILE (stack.cpp)
//------------------------------------------------------
// Private data members of class:
// int top;
// ItemType items[MAX_ITEMS];
//-------------------------------------------------------
#include “stack.h”
Stack::Stack ( ) // Default Constructor
{
top = -1;
}
//----------------------------------------------------------
int Stack::IsEmpty( ) const
{
return ( top == -1 );
}
//----------------------------------------------------------
int Stack::IsFull( ) const
{
return ( top == MAX_ITEMS-1 );
}
//----------------------------------------------------------
void Stack::Push ( ItemType newItem )
{
if (IsFull())
{
cout << “Stack Overflow” << endl;
exit(1);
}
top++;
items[top] = newItem;
}
Data Structures Lab Handouts 22
//----------------------------------------------------------
void Stack::Pop ( ItemType& item )
{
if (IsEmpty())
{
cout << “Stack Underflow” << endl;
exit(1);
}
item = items[top];
top--;
}
//----------------------------------------------------------
// DRIVER FILE (driver.cpp)
//----------------------------------------------------------
#include <iostream>
#include <stdlib.h>
#include “stack.cpp”
using namespace std;
int main()
{
Stack s;
int item;
for (int i = 0; i < 20; i++)
s.Push(i);
for (i = 0; i < 20; i++)
{ s.Pop(item);
cout << item << endl;
}
return 0;
}
Data Structures Lab Handouts 23
Dynamic Implementation of Stack
Stack Using Class Template and Dynamic Array
# The construct that allows us to create a class of undetermined type is called a template.
# A class template allows the compiler to generate multiple versions of a class type by
using type parameters.
# The formal parameter appears in the class template definition, and the actual parameter
appears in the client code. Both are enclosed in pointed brackets, < >.
template<class ItemType>
class Stack {
public:
Stack ( );
Stack ( int max ); // PARAMETERIZED CONSTRUCTOR
~Stack ( ) ; // DESTRUCTOR . . .
int IsEmpty( ) const;
int IsFull( ) const;
void Push( ItemType newItem );
void Pop( ItemType& item );
private:
int top;
int maxStack;
ItemType* items; // DYNAMIC ARRAY IMPLEMENTATION
};
Data Structures Lab Handouts 24
//-----------------------------------------------------------------------------
// CLASS TEMPLATE IMPLEMENTATION FILE (stack.cpp)
//-------------------------------------------------------------------------------
#include “stack.h”
template<class ItemType>
Stack<ItemType>::Stack( ) //DEFAULT CONSTRUCTOR
{
maxStack = 500;
top = -1;
items = new ItemType[500]; // dynamically allocates array
}
template<class ItemType>
Stack<ItemType>::Stack( int max ) // PARAMETERIZED
{
maxStack = max;
top = -1;
items = new ItemType[max]; // dynamically allocates array
}
template<class ItemType>
Stack<ItemType>::~Stack( )
{
delete [ ] items; // deallocates array
}
template<class ItemType>
int Stack<ItemType>::IsEmpty( )
{
return (top == - 1);
}
template<class ItemType>
int Stack<ItemType>::IsFull( )
{
return (top == maxStack - 1);
}
Data Structures Lab Handouts 25
template <class ItemType>
void Stack<ItemType>::Push (ItemType newItem )
{
if (IsFull())
{ cout << “Stack Overflow” << endl;
exit(1);
}
top++;
items[top] = newItem;
}
template<class ItemType>
void Stack<ItemType>::Pop (ItemType& item )
{
if (IsEmpty())
{ cout << “Stack Underflow” << endl;
exit(1);
}
item = items[top];
top--;
}
//----------------Driver Program ------Using Class Template--------------------------------
#include <iostream>
#include “stack.cpp”
using namespace std;
int main ()
{
Stack<int> IntStack;
Stack<float> FloatStack;
int data;
float val;
IntStack.Push(35);
FloatStack.Push(3.1415927);
IntStack.Pop(data);
cout << data << endl;
FloatStack.Pop(val);
cout << val << endl;
return 0; }
Data Structures Lab Handouts 26
Exercise 2
Use the Stack class to solve the following problems:
Infix to Postfix Conversion
The input for this problem is an infix expression (with or without parenthesis). The
operand should be single letter digits and valid operators are +, -, * and /. The output
is the postfix version of the expression.
Postfix Evaluation
Evaluate a valid postfix expression and display the result.
Data Structures Lab Handouts 27
Lab 3
Recursion
Recursive Functions
A recursive function is one that calls itself.
Example 1: Calculating a Factorial
Factorials are often used in statistical calculations. The factorial of n, written as n! is equal
to the product of n(n-1)(n-2)...(1). For example 4! is equal to 4 × 3 × 2 × 1 = 24. There is
an obvious way to do this calculation using a loop, but we can also do it recursively.
Let's consider the definition of a factorial in a slightly different way:
# if n = 0, n! is equal to 1.
# if n > 0, n! is equal to n × ((n-1)!)
An implementation of recursive factorial function
#include <iostream>
#include <conio.h>
using namespace std;
int fact(int n)
{ if (n == 0)
return 1;
else
return n * fact(n - 1);
}
int main( )
{
cout << fact(5) << endl;
getch();
return 0;
}
Data Structures Lab Handouts 28
Example 2: Reversing the String
This function takes a series of characters and outputs them in reverse order.
#include <iostream>
#include <conio.h>
using namespace std;
void rev( )
{ char ch;
cin.get(ch);
if (ch != '\n')
{ rev();
cout.put(ch);
}
}
int main( )
{
rev();
getch();
return 0;
}
Example 3: Computing the Power
int Power(int X, int N)
{
if( N == 0 )
return 1;
else
return Power( X, N-1) * X;
}
Data Structures Lab Handouts 29
Example 4: Computing the Ackermann Function
int Ackermann(int m, int n)
{
if(m==0)
return n+1;
else if (m>0 && n==0)
return Ackermann(m-1,1);
else if (m>0 && n>0)
return Ackermann( m-1, Ackermann(m, n-1));
}
Exercise 3:
o Write a function in C++ using Recursion to print numbers from n to 0.
o Write a function in C++ using Recursion to compute binomial coefficients C(n, k)
using the recursive definition:
C(n,n) = 1
C(n,0) = 1
C(n,k) = C(n-1, k-1) + C(n-1,k) for (0<k<n) and n>1
o Write a function in C++ using Recursion to check if a number n is prime. (You have
to check whether n is divisible by any number below n)
Data Structures Lab Handouts 30
Lab 4
Implementation of Queue
Queue ADT Operations
- Initialize -- Sets queue to an empty state.
- IsEmpty -- Determines whether the queue is currently empty.
- IsFull -- Determines whether the queue is currently full.
- Insert (ItemType newItem) -- Adds newItem to the rear of the queue.
- Remove (ItemType& item) -- Removes the item at the front of the queue and returns it
in item.
Implementation of Queue Using Circular Arrays
Given
# an array Items[0:N-1] consisting of N items
# two indices Front and Rear, that designate positions in the Items array
We can use the following assignments to increment the indices so that they always wrap
around after falling off the high end of the array.
front = (front + 1) % N
rear = (rear + 1) % N
//--------------------------------------------------------
// CLASS DEFINITION FOR QUEUE
//--------------------------------------------------------
#define maxQue 100
typedef int ItemType;
class Queue
{
private:
ItemType items[maxQue];
int front, rear, count;
public:
Queue ();
int IsEmpty ();
int IsFull ();
void Insert (ItemType newItem);
void Remove (ItemType &item);
};
Data Structures Lab Handouts 31
Queue::Queue ()
{
count = 0;
front = 0;
rear = 0;
}
int Queue::IsEmpty ()
{
return (count == 0);
}
int Queue::IsFull ()
{
return (count == maxQue);
}
void Queue::Insert (ItemType newItem)
{
if (IsFull())
cout << "Over Flow";
else
{ items[rear] = newItem;
rear = (rear + 1) % maxQue;
++count;
}
}
void Queue::Remove (ItemType &item)
{
if (IsEmpty())
cout << "Under Flow";
else
{ item = Items[front];
front = (front + 1) % maxQue;
--count;
}
}
Exercise:
Write a driver program to insert 10 numbers in a queue and then remove and print the
numbers.
Data Structures Lab Handouts 32
Dynamic Implementation of Queue
Queue Using Template and Dynamic Array
//-----------------------------------------------------------------------
// CLASS TEMPLATE DEFINITION FOR QUEUE
//-----------------------------------------------------------------------
template<class ItemType>
class Que {
public:
Que( );
Que( int max ); // PARAMETERIZED CONSTRUCTOR
~Que( ) ; // DESTRUCTOR . . .
int IsFull( ) const;
int IsEmpty( ) const;
void Insert( ItemType newItem );
void Remove( ItemType& item );
privat
int front;
int rear;
int maxQue;
int count;
ItemType* items; // DYNAMIC ARRAY IMPLEMENTATION
};
//-----------------------------------------------------------------------
// CLASS TEMPLATE IMPLEMENTATION
//-----------------------------------------------------------------------
template<class ItemType>
Que<ItemType>::Que() // Default Constructor
{
maxQue = 501;
front = 0;
rear = 0;
count = 0;
items = new ItemType[maxQue]; // dynamically allocates
}
Data Structures Lab Handouts 33
template<class ItemType>
Que<ItemType>::Que( int max )
// PARAMETERIZED Constructor
{
maxQue = max + 1;
front = 0;
rear = 0;
count = 0;
items = new ItemType[maxQue]; // dynamically allocates
}
template<class ItemType>
Que<ItemType>::~Que( )
{
delete [ ] items; // deallocates array
}
template<class ItemType>
int Que<ItemType>::IsEmpty( ) const
{
return (count == 0);
}
template<class ItemType>
int Que<ItemType>::IsFull( ) const
{
return ( count == maxQue );
}
template<class ItemType>
void Que<ItemType>::Insert( ItemType newItem )
{
if (IsFull())
cout << "Over Flow";
else
{ items[rear] = newItem;
rear = (rear + 1) % maxQue;
++count;
}
}
Data Structures Lab Handouts 34
template<class ItemType>
void Que<ItemType>::Remove( ItemType& item )
{
if (IsEmpty())
cout << "Under Flow";
else
{ item = items[front];
front = (front + 1) % maxQue;
--count;
}
}
Write a driver program to insert 10 numbers in a queue and then remove and print the
numbers.
Exercise 4
Suppose a deque is represented by an array of N elements. The two ends of the deque are
denoted as left and right and elements always extend from left to right. Using this model of
a deque write four routines insertLeft, removeLeft, insertRight and removeRight to
insert/remove an element to/from the deque from left and right ends. Make sure to check
for overflow and underflow conditions.
Data Structures Lab Handouts 35
Lab 5
Implementation of Priority Queue
Sometimes it is not enough just do FIFO ordering. We may want to give some items a
higher priority than other items. These should be serviced before lower priority even if
they arrived later. Such a data structure is called a priority Queue.
Two major ways to implement a priority queue are:
–insert items in a sorted order and always remove the front
–insert in unordered order and search list on remove
–either way, time is same
•either adding data takes time and removing is quick, or
•adding data is quick and removing takes time
Use the Queue class to implement the following Priority Queue ADT to handle 10
different priority levels.
The Priority Queue ADT
A Priority Queue, PQ, is a finite collection of items of type T on which following
operations are defined:
1. Initialize the priority queue, PQ, to be the empty priority queue.
2. Determine whether or not the priority queue, PQ, is empty.
3. Determine whether or not the priority queue, PQ, is full.
4. If PQ is not full, insert a new item, X, into the priority queue, PQ, according to its
priority level.
5. If PQ is not empty, remove from the priority queue, PQ, an item, X, of highest priority
in PQ.
Data Structures Lab Handouts 36
Lab 6
Implementation of Linked List
//-----------------------------------------------------------------------
// CLASS TEMPLATE DEFINITION FOR LINKED LIST
//---------------------------------------------------------------------
#include <iostream>
#include<conio.h>
using namespace std;
template<class ItemType>
class List
{
protected:
struct node {
ItemType info;
struct node *next;
};
typedef struct node *NODEPTR;
NODEPTR listptr;
public:
List();
~List();
ItemType emptyList();
void insertafter(ItemType oldvalue, ItemType newvalue);
void deleteItem(ItemType oldvalue);
void push(ItemType newvalue);
ItemType pop();
};
Data Structures Lab Handouts 37
//--------------------------------------------------------
// CLASS TEMPLATE IMPLEMENTATION
//--------------------------------------------------------
// Default Constructor that initializes a newly created list to empty list.
template<class ItemType>
List<ItemType>::List()
{
listptr = 0;
}
// Destructor traverses the nodes of a list, freeing them one by one.
template<class ItemType>
List<ItemType>::~List()
{
NODEPTR p, q;
if (emptyList())
exit(0);
for (p = listptr, q = p->next; p!=0; p = q, q = p->next)
delete p;
}
// searches for the first occurance of oldvalue in the list and inserts a new node with value
newvalue following the node containing oldvalue.
template<class ItemType>
void List<ItemType>::insertafter(ItemType oldvalue, ItemType newvalue)
{
NODEPTR p, q;
for (p = listptr; p != 0 && p->info != oldvalue; p = p->next)
;
if (p == 0)
{ cout << " ERROR: value sought is not in the list.";
exit(1);
}
q = new node;
q->info = newvalue;
q->next = p->next;
p->next = q;
}
Data Structures Lab Handouts 38
// Determines if the list is empty.
template<class ItemType>
ItemType List<ItemType>::emptyList()
{
return (listptr == 0);
}
// push(newvalue) adds a new node with a given value to the front of the list.//
template<class ItemType>
void List<ItemType>::push(ItemType newvalue)
{
NODEPTR p;
p = new node;
p->info = newvalue;
p->next = listptr;
listptr = p;
}
// deletes the first node containing the value oldvalue from the list.
template<class ItemType>
void List<ItemType>::deleteItem(ItemType oldvalue)
{
NODEPTR p, q;
for (q = 0, p = listptr; p != 0 && p->info != oldvalue; q = p, p = p->next)
;
if (p == 0)
{ cout << " ERROR: value sought is not in the list.";
exit(1);
}
if (q == 0) listptr = p->next;
else q->next = p->next;
delete p;
}
Data Structures Lab Handouts 39
// pop deletes the first node of the list and returns its contents. //
template<class ItemType>
ItemType List<ItemType>::pop()
{
NODEPTR p;
ItemType x;
if (emptyList())
{ cout << " ERROR: the list is empty.";
exit(1);
}
p = listptr;
listptr = p->next;
x = p->info;
delete p;
return x;
}
int main()
{
List<int> l;
l.push(87);
cout << l.pop()<<endl;
getch();
return 0;
}
Exercise 6.1
Write a menu driven program to test the linked list class.
Data Structures Lab Handouts 40
Exercise 6.2
Assume the following specifications of a node of linked structure and the class
struct Node
{
int info; Node* next;
};
class LinkedStr
{
private:
Node* ptr;
public:
// Constructor. Initiallize ptr to NULL.
LinkedStr();
// Destructor. Remove all the nodes from dynamic memory
~LinkedStr();
// Create a linked structure of length len pointed to by ptr.
// The values of the info part are input from the keyboard
void makeStr(int len);
// Display all the elements of the linked structure pointed to by ptr on the screen.
void displayStr();
// Remove the first element of the linked structure pointed to by ptr.
// If the structure is empty, do nothing
void removeFirst();
// Remove the first element of the linked structure pointed to by ptr.
// If the structure is empty, do nothing
void removeLast();
// Remove the first element of the linked structure with an info field equal to k.
// If no such element or the list is empty, do nothing
void remove(int k); };
Write the implementation of the class LinkedStr. Write a driver program to test the
implementation.
Data Structures Lab Handouts 41
Lab 7
Application of Linked List
Polynomial may be represented as a linked list as follows: for every term in the
polynomial there is one entry in the linked list consisting of the term's coefficient and
degree. The entries are ordered according to ASCENDING values of degree; zero-
coefficient terms are not stored. For example, the following polynomial (the symbol '^' is
used to mean 'raised to the power'): 4x^5 - 2x^3 + 2x +3 can be represented as the linked
list of terms: (3,0) -> (2,1) -> (-2,3) -> (4,5) where each term is a (coefficient, degree)
pair. Write a C++ class called Polynomial with the following functionality:
# Read the polynomials from a file.
# Addition of two polynomials.
# Multiplication of two polynomials.
# Evaluation of a polynomial at a given point.
Sample Output:
Enter the name of the polynomial file => ptest1
4.0x^5 + -2.0x^3 + 2.0x + 3.0
1. ADD polynomial
2. MULTIPLY polynomial
3. EVALUATE polynomial
4. QUIT
Enter choice # => 1
Enter the file containing the polynomial to add => ptest2
8.0x^4 + 4.0x^3 + -3.0x + 9.0
Sum: 4.0x^5 + 8.0x^4 + 2.0x^3 + -1.0x + 12.0
1. ADD polynomial
2. MULTIPLY polynomial
3. EVALUATE polynomial
4. QUIT
Enter choice # => 2
Enter the file containing the polynomial to multiply => ptest2
8.0x^4 + 4.0x^3 + -3.0x + 9.0
Product: 32.0x^9 + 16.0x^8 + -16.0x^7 + -20.0x^6 + 52.0x^5 + 38.0x^4 + -6.0x^3 + -
6.0x^2 + 9.0x + 27.0
Data Structures Lab Handouts 42
Lab 8
Implementation of Binary Trees
ADT of Binary Tree
ADT BinaryTree
{
Objects:
A finite set of nodes either empty or consisting of a root node, left BinaryTree and
right BinaryTree.
Operations:
BinaryTree ();
// Creates an empty BinaryTree
BinaryTree (ElementType info);
// Creates a single node BinaryTree with information info
BinaryTree (BinaryTree lbt, ElementType info, BinaryTree rbt);
// Creates a Binarytree whose left subtree is lbt, whose right subtree is rbt,
// and whose root node contain info.
Boolean IsEmpty();
// If number of elements in the BinaryTree is 0 return TRUE,
// otherwise return FALSE.
BinaryTree LChild();
// If IsEmpty(), return error, else return left subtree of *this
ElementType Data();
// If IsEmpty(), return error, else return data in the root node of *this
BinaryTree RChild();
// If IsEmpty(), return error, else return right subtree of *this
};
Data Structures Lab Handouts 43
Implicit Static Array Representaion
The n nodes of an almost complete binary tree can be numbered from 1 to n, so that the
number assigned to a left son is twice the number assigned to its father, and number
assigned to a right son is one more than twice the number assigned to its father.
In C++, arrays start from 0; therefore we'll number the nodes from 0 to n-1. The left son of
node at position p is at position 2p+1 and right son is at 2p+2. The root of the tree is at
position 0.
Node Representation
# define NUMNODES 500
struct TreeNode
{
int info;
int left, right, father;
};
TreeNode BT[NUMNODES];
Data Structures Lab Handouts 44
Dynamic Representation
struct Tree Node
{
int info;
TeeNode *left, *right, *father;
};
typedef TreeNode *NODEPTR;
If a tree is always traversed from top to bottom, father field is unnecessary.
The maketree() function, which allocates a node and sets it as the root of a single-node
binary tree may be written as:
NODEPTR maketree (int x)
{
NODEPTR p =new TreeNode;
p $ info = x;
p $ left = NULL;
p $ right = NULL;
return (p); }
The function setleft (p,x) sets a node with contents x as the left son of node(p).
void setleft (NODEPTR p, int x)
{
if (p == NULL)
cout << “Void Insertion”;
else if (p $ left != NULL)
cout << “Invalid Insertion”;
else
p $ left = maketree (x);
}
Data Structures Lab Handouts 45
Binary Tree Traversals in C++
Three C++ routines pretrav, intrav, and posttrav are given below. The parameter to each
routine is the pointer to the root node of a binary tree.
void pretrav (NODEPTR tree)
{
if (tree != NULL)
{
cout << tree $ info; /* visit the root */
pretrav (tree $ left);
pretrav (tree $ right);
}}
void intrav (NODEPTR tree)
{
if (tree != NULL)
{
intrav (tree $ left);
cout << tree $ info;
intrav (tree $ right);
}
}
void posttrav (NODEPTR tree)
{
if (tree != NULL)
{
posttrav (tree $ left);
posttrav (tree $ right);
cout << tree $ info;
}}
Data Structures Lab Handouts 46
Lab 9
Implementation of Binary Search Trees
#include <fstream>
using namespace std;
template< class ItemType >
struct TreeNode {
ItemType info; // Data member
TreeNode<ItemType>* left; // Pointer to left child
TreeNode<ItemType>* right; // Pointer to right child
};
template< class ItemType >
// BINARY SEARCH TREE SPECIFICATION
class TreeType {
public:
TreeType ( ); // constructor
~TreeType ( ); // destructor
bool IsEmpty ( ) const;
bool IsFull ( ) const;
int NumberOfNodes ( ) const;
void InsertItem ( ItemType item );
void DeleteItem (ItemType item );
void RetrieveItem ( ItemType& item, bool& found );
void PrintTree (ofstream& outFile) ;
void PrintHelper ( TreeNode<ItemType>* ptr, ofstream& outFile ) ;
void InsertHelper ( TreeNode<ItemType>*& ptr, ItemType item ) ;
void RetrieveHelper ( TreeNode<ItemType>* ptr, ItemType& item, bool& found ) ;
void DestroyHelper ( TreeNode<ItemType>* ptr ) ;
private:
TreeNode<ItemType>* root;
};
Data Structures Lab Handouts 47
// BINARY SEARCH TREE IMPLEMENTATION
// OF MEMBER FUNCTIONS AND THEIR HELPER FUNCTIONS
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template< class ItemType >
TreeType<ItemType> :: TreeType ( ) // constructor
{
root = NULL ;
}
template< class ItemType >
bool TreeType<ItemType> :: IsEmpty( ) const
{
return ( root == NULL ) ;
}
template< class ItemType >
void TreeType<ItemType> :: RetrieveItem ( ItemType& item, bool& found )
{
RetrieveHelper ( root, item, found ) ;
}
template< class ItemType >
void TreeType<ItemType> :: RetrieveHelper ( TreeNode<ItemType>* ptr,
ItemType& item, bool& found)
{ if ( ptr == NULL )
found = false ; else if ( item < ptr->info ) // GO LEFT
RetrieveHelper( ptr->left , item, found ) ;
else if ( item > ptr->info ) // GO RIGHT
RetrieveHelper( ptr->right , item, found ) ;
else
{ item = ptr->info ;
found = true ; }
}
template< class ItemType >
void TreeType<ItemType> :: InsertItem ( ItemType item )
{
InsertHelper ( root, item ) ;
}
Data Structures Lab Handouts 48
template< class ItemType >
void TreeType<ItemType> :: InsertHelper ( TreeNode<ItemType>*& ptr, ItemType
item )
{ if ( ptr == NULL )
{ // INSERT item HERE AS LEAF
ptr = new TreeNode<ItemType> ;
ptr->right = NULL ;
ptr->left = NULL ;
ptr->info = item ;
}
else if ( item < ptr->info ) // GO LEFT
InsertHelper( ptr->left , item ) ;
else if ( item > ptr->info ) // GO RIGHT
InsertHelper( ptr->right , item ) ;
}
template< class ItemType >
void TreeType<ItemType> :: PrintTree ( ofstream& outFile )
{
PrintHelper ( root, outFile ) ;
}
template< class ItemType >
void TreeType<ItemType> :: PrintHelper ( TreeNode<ItemType>* ptr, ofstream&
outFile )
{ if ( ptr != NULL )
{ PrintHelper( ptr->left , outFile ) ; // Print left subtree
outFile << ptr->info ;
PrintHelper( ptr->right, outFile ) ; // Print right subtree
}
}
template< class ItemType >
TreeType<ItemType> :: ~TreeType ( ) // DESTRUCTOR
{
DestroyHelper ( root ) ;
}
Data Structures Lab Handouts 49
template< class ItemType >
void TreeType<ItemType> :: DestroyHelper ( TreeNode<ItemType>* ptr )
// Post: All nodes of the tree pointed to by ptr are deallocated. { if ( ptr != NULL )
{
DestroyHelper ( ptr->left ) ;
DestroyHelper ( ptr->right ) ;
delete ptr ; }
}
// Driver Program
int main ()
{
TreeType <int> tree;
ofstream out("tree.txt");
int item = 1;
bool flag = false;
for(int i = 0; i < 10; i++)
tree.InsertItem(i);
tree.PrintTree(out);
tree.RetrieveItem(item, flag);
cout << flag << endl;
return 0;
}
Data Structures Lab Handouts 50
Lab 10
Implementation of Graphs
C++ Representation of Graphs
Suppose that the number of vertices in the graph is constant: that is, edges may be
added or deleted but vertices may not.
# A graph with 50 vertices could then be declared as follows:
#define MAXVERTEXS 50
struct vertex
{
/* information associated with each vertex */
};
struct edge
{
int adj;
/* information associated with each edge */
};
class Graph
{
private:
struct vertex vertices[MAXVERTEXS];
struct edge edges[MAXVERTEXS][MAXVERTEXS];
……
…….
};
Graph g;
Data Structures Lab Handouts 51
# Each vertex of the graph is represented by an integer between 0 and MAXVERTEXS-1
and the array field vertices represents the appropriate information assigned to each
vertex.
# The array field edges is a two-dimensional array representing every possible ordered
pair of vertices.
# The value of g.edges[i][j].adj is either TRUE or FALSE depending on whether or not
vertex j is adjacent to vertex i.
# The two-dimensional array g.edges[][].adj is called an adjacency matrix. In the case of
a weighted graph, each edge can also be assigned information.
# Frequently the vertices of a graph are numbered from 0 to MAXVERTEXS-1 and no
information is assigned to them. Also, we may be interested in the existence of edges
but not in any weights or other information about them. In such cases the graph could
be declared simply by
int adj[MAXVERTEXS][MAXVERTEXS];
# In effect, the graph is totally described by its adjacency matrix. We present the code for
the primitive operations just described in the case where a graph is described by its
adjacency matrix.
join (int adj[][MAXVERTEXS], int vertex1, int vertex2)
{
/* add an edge from vertex1 to vertex2 */
adj[vertex1][vertex2] = TRUE;
}
remv (int adj[][MAXVERTEXS], int vertex1, int vertex2)
{
/* delete edge from vertex1 to vertex2 if one exists */
adj[vertex1][vertex2] = FALSE;
}
adjacent (int adj[][MAXVERTEXS], int vertex1, int vertex2)
{
return ((adj[vertex1][vertex2]==TRUE) ? TRUE : FALSE);
}
Data Structures Lab Handouts 52
C++ Representation of Weighted Graphs
A weighted graph with a fixed number of vertices may be declared by
struct edge
{
int adj;
int weight; };
struct edge g[MAXVERTEXS][MAXVERTEXS];
# The routine joinwt, which adds an edge from vertex1 to vertex2 with a given weight
wt, may be coded as follows:
void joinwt (struct edge g[] [MAXVERTEXS], int vertex1, int vertex2, int wt)
{
g[vertex1][vertex2].adj = TRUE;
g[vertex1][vertex2].weight = wt;
}
Exercise 10:Implement in C++ a class for a Weighted Graph using adjacency matrix representation.
Data Structures Lab Handouts 53
Lab 11
Application of Graphs
Exercise 11: Implement Breadth-First and Depth-First search algorithms for a graph.
Depth-First Search
# We begin by visiting the start vertex v. Next an unvisited vertex w adjacent to v is
selected, and a depth-first search from w is initiated.
# When a vertex u is reached such that all its adjacent vertices have been visited, we back
up to the last vertex visited that has an unvisited w adjacent to it and initiates a depth-
first search from w.
Depth-First-Search
{
Boolean visited[n];
// initially, no vertex has been visited
for (i = 0; i < n; i++)
visited[i] = FALSE;
// start search at vertex 0
DFS (0);
}
DFS (v)
// Visit all previously unvisited vertices that are reachable from vertex v
{
visited[v] = TRUE;
for (each vertex w adjacent to v)
if ( !visited[w])
DFS(w);
}
Data Structures Lab Handouts 54
Breadth-First Search
# In a breadth-first search, we begin by visiting the start vertex v. Next all unvisited
vertices adjacent to v are visited.
# Unvisited vertices adjacent to these newly visited vertices are then visited, and so on.
BFS(v)
// A BFS of the graph is carried out starting at vertex v.
// visited[i] is set to TRUE when v is visited. The algorithm uses a queue.
{
Boolean visited[n];
Queue q;
// initially, no vertex has been visited
for (i = 0; i < n; i++)
visited[i] = FALSE;
visited[v] = TRUE;
q.insert(v); // add vertex v to the queue
while (!q.IsEmpty())
{
v = q.delete();
for (all vertex w adjacent to v)
{ if ( !visited[w])
{ q.insert(w);
visited[w] = TRUE;
}
}
}
}
Exercise 11:
Implement the Dijkstra’s Shortest Path Algorithm to generate shortest paths for a given
directed graph.
Data Structures Lab Handouts 55
Lab 12-13
Using Standard Template Library (STL)
Overview
The Standard Library is a fundamental part of the C++ Standard. It provides C++
programmers with a comprehensive set of efficiently implemented tools and facilities that
can be used for most types of applications.
The Standard Template Library, or STL, is a C++ library of container classes, algorithms,
and iterators; it provides many of the basic algorithms and data structures of computer
science.
The STL is a generic library, meaning that its components are heavily parameterized:
almost every component in the STL is a template.
1 - GETTING STARTED
There are three components that make up STL. These are containers, algorithms, and
iterators. Each will be discussed below.
1. Containers. Containers embody the data structures supported by STL. It
accomplishes this by defining a template class for each of these data structures
There are functions in the classes that allow the efficient manipulation of its
elements. The following is a list of the containers.
1. vector - allows us to define dynamic arrays.
2. deque - doubly ended queues.
3. queue - supports a queue. Officially not a container - it is an adapter, but we
can think of it as a container.
4. list - allows us to create linked lists.
5. stack - implements a pushdown stack.
6. maps and multimaps - allows us to create sorted tree structures. This gives us
quick access to data stored in table form. The data may be accessed using a
key.
Data Structures Lab Handouts 56
7. set and multi-set - allows us to organize a set of data in a tree structure.
Note: Most often used are vectors and maps.
2. Algorithms. There are a set of algorithms supplied to manipulate data in
containers. Sort, lower bound (a binary search) and replace are examples of
algorithms. A good rule: if the container contains a function that does the same
thing as a function in the algorithms, use the function in the container class.
3. Iterators. Iterators are a fancy word for pointers. They are pointers relative to
containers. Because of the structure of the various containers they are not always as
powerful as the standard C++ pointers.
Example 1:
Let's consider a simple example, one where we wish to create a set of integers and then
shuffle them into random order:
#include <vector>
#include <algorithm>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
vector<int> v;
for (int i = 0; i < 25; i++)
v.push_back(i);
random_shuffle(v.begin(), v.end());
for (int j = 0; j < 25; j++)
cout << v[j] << " ";
cout << endl;
getch();
return 0;
}
When run, this program produces output like:
6 11 9 23 18 12 17 24 20 15 4 22 10 5 1 19 13 3 14 16 0 8 21 2 7
Data Structures Lab Handouts 57
2 - VECTORS, LISTS, DEQUES, STACK
STL has different types of containers that are available for holding data, namely vectors,
lists, and deques.
# A vector is like a smart array. You can use [] to efficiently access any element in the
vector, and the vector grows on demand. But inserting into the middle of a vector is
expensive, because elements must be moved down, and growing the vector is costly
because it must be copied to another vector internally.
# A list is like a doubly-linked list that you've used before. Insertion or splicing of
subsequences is very efficient at any point in the list, and the list doesn't have to be
copied out. But looking up an arbitrary element is slow.
# A deque classically stands for "double-ended queue", but in STL means a combination
of a vector and a list. Indexing of arbitrary elements is supported, as are list operations
like efficiently popping the front item off a list.
Example 2.1:
#include <list>
#include <algorithm>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
list<int> v;
for (int i = 0; i < 25; i++)
v.push_back(i);
for (int j = 0; j < 25; j++) {
cout << v.front() << " ";
v.pop_front();
}
cout << endl;
getch();
return 0;
}
Data Structures Lab Handouts 58
Example 2.2:
#include <algorithm>
#include <iostream>
#include <deque>
#include <conio.h>
using namespace std;
int main()
{
deque<int> v;
for (int i = 0; i < 25; i++)
v.push_back(i);
random_shuffle(v.begin(), v.end());
for (int j = 0; j < 25; j++) {
cout << v.front() << " ";
v.pop_front();
}
cout << endl;
getch();
return 0;
}
Data Structures Lab Handouts 59
Example 2.3:
One more worth mentioning data structure is stack. In STL a stack is based on a vector,
deque, or list. An example of stack usage is:
#include <iostream>
#include <stack>
#include <list>
#include <conio.h>
using namespace std;
int main()
{
stack<int, list<int> > stk;
for (int i = 1; i <= 10; i++)
stk.push(i);
while (!stk.empty()) {
cout << stk.top() << endl;
stk.pop();
}
getch();
return 0;
}
We declare the stack, specifying the underlying type (int), and the sort of list used to
represent the stack (list<int>).
Data Structures Lab Handouts 60
3 - BIT SETS
Another STL data structure is bit sets, offering space-efficient support for sets of bits.
Example 3:
#include <iostream>
#include <bitset>
#include <conio.h>
using namespace std;
int main()
{
bitset<16> b1("1011011110001011");
bitset<16> b2;
b2 = ~b1;
for (int i = b2.size() - 1; i >= 0; i--)
cout << b2[i];
cout << endl;
getch();
return 0;
}
Data Structures Lab Handouts 61
4 – ITERATORS
Iterators in STL are mechanisms for accessing data elements in containers and for cycling
through lists of elements.
Example 4:
#include <algorithm>
#include <vector>
#include <iostream>
#include <conio.h>
using namespace std;
const int N = 100;
int main()
{
vector<int> iv(N);
iv[50] = 37;
vector<int>::iterator iter = find(iv.begin(), iv.end(), 37);
if (iter == iv.end())
cout << "not found\n";
else
cout << "found at " << iter - iv.begin() << "\n";
getch();
return 0;
}
Data Structures Lab Handouts 62
5 - OPERATING ON SETS
STL also contains some algorithms for operating on ordered sets of data, illustrated by a
simple example:
Example 5:
#include <iostream>
#include <algorithm>
#include <vector>
#include <conio.h>
using namespace std;
int set1[] = {1, 2, 3};
int set2[] = {2, 3, 4};
vector<int> set3(10);
int main()
{
vector<int>::iterator first = set3.begin();
vector<int>::iterator last =
set_union(set1, set1 + 3, set2, set2 + 3, first);
while (first != last) {
cout << *first << " ";
first++;
}
cout << endl;
getch();
return 0;
}
Data Structures Lab Handouts 63
6 – FILLING
The fill() function fills a data structure with a specified value:
Example 6:
#include <algorithm>
#include <iostream>
#include <conio.h>
using namespace std;
int vec1[10];
int vec2[10];
int main()
{
fill(vec1, vec1 + 10, -1);
for (int i = 0; i < 10; i++)
cout << vec1[i] << " ";
cout << endl;
fill_n(vec2, 5, -1);
for (int j = 0; j < 10; j++)
cout << vec2[j] << " ";
cout << endl;
getch();
return 0;
}
fill() fills according to the specified iterator range, while fill_n() fills a specified number of
locations based on a starting iterator and a count. The results of running this program are:
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 0 0 0 0 0
Data Structures Lab Handouts 64
7 – ACCUMULATING
Another simple algorithm that STL makes available is accumulation, for example
summing a set of numeric values. An example of this would be:
Example 7:
#include <iostream>
#include <numeric>
#include <conio.h>
using namespace std;
int vec[] = {1, 2, 3, 4, 5};
int main()
{
int sum = accumulate(vec, vec + 5, 0);
cout << sum << endl;
int prod = accumulate(vec, vec + 5, 1, times<int>());
cout << prod << endl;
getch();
return 0;
}
In this example, we specify iterators for a vector of integers, along with an initial value (0)
for doing the summation.
By default, the "+" operator is applied to the values in turn. Other operators can be used,
for example "*" in the second example. In this case the starting value is 1 rather than 0.
Data Structures Lab Handouts 65
Lab 14-15
Implementation of Sorting Techniques
The main objective of this lab is to compare the efficiency of different sorting
techniques we have studied in the course.
Implement the following sorting techniques and count number of comparisons and
exchanges.
1) Bubble Sort
2) Selection Sort
3) Insertion Sort
4) Heap Sort
# Run all the above techniques for the following values of N. Generate input data
randomly and vary the input size N as below:
N = 10, 100, 1000, 5000, 10000, 20000, 50000
# Present your results in tabular and graphical (line graph) form. The tabulated output
should have the following form:
Extra Credit Task:
Compute the actual execution time by reading the system clock.
N Bubble Sort Selection Sort Insertion Sort Heap Sort
Comp. Exch. Comp. Comp
.
Exch. Exch. Comp. Exch.
10
100
1000
5000
10000
20000
50000
Data Structures Lab Handouts 66
Bubble Sort
void Bubble( int x[], int n)
{
int hold, j, pass;
int switched = TRUE;
for (pass = 0; pass < n-1 && switched == TRUE; pass++)
{ // outer loop controls the number of passes
switched = FALSE;
for ( j = 0; j < n-pass-1; j++)
{
// inner loop controls each individual pass
if (x[j] > x [j+1]) // elements out of order
{
switched = TRUE;
hold = x[j]; // interchange j and j+1
x[j] = x [j+1];
x[j+1] = hold;
} // end if
} // end inner for loop
} // end outer for loop
} // end Bubble
Data Structures Lab Handouts 67
Insertion Sort
insertionsort (int x[], int n)
{
int j, k, y;
/* initially x[0] may be thought of as a sorted file of one element. After each
repetition of the following loop, the elements x[0] through x[k] are in order */
for (k=1; k<n; k++)
{
/* insert x[k] into sorted file */
y = x[k];
/* move down all elements greater than y */
for (j=k-1; j>=0 && y<x[j]; j++)
x[j+1] = x[j];
/* insert y at proper position */
x[j+1] = y;
}
}
Selection Sort
void Selectionsort(int x[], int n)
{
int key;
for(int a=0; a < n; a++)
{ key=a;
for(int b=a+1; b < n; b++)
{
if(x[b] < x[key]) key=b;
}
if (key > a)
{ int temp = x[a];
x[a] = x[key];
x[key] = temp;
}
}
}
Heap Sort Use STL to implement Heap sort.
Data Structures Lab Handouts 68
Sorting using STL
We will now start discussing some of the actual STL algorithms that can be applied to data
structures. One of these is sorting.
Example:
Consider a simple example of a String class, and a vector of Strings:
#include <vector>
#include <algorithm>
#include <iostream>
#include <assert>
#include <string>
#include <conio.h>
using namespace std;
class String {
char* str;
public:
String()
{
str = 0;
}
String(char* s)
{
str = strdup(s);
assert(str);
}
int operator<(const String& s) const
{
return strcmp(str, s.str) < 0;
}
operator char*()
{
return str;
}
};
Data Structures Lab Handouts 69
char* list[] = {"epsilon", "omega", "theta", "rho",
"alpha", "beta", "phi", "gamma", "delta"};
const int N = sizeof(list) / sizeof(char*);
int main()
{
int i, j;
vector<String> v;
for (i = 0; i < N; i++)
v.push_back(String(list[i]));
random_shuffle(v.begin(), v.end());
for (j = 0; j < N; j++)
cout << v[j] << " ";
cout << endl;
sort(v.begin(), v.end());
for (j = 0; j < N; j++)
cout << v[j] << " ";
cout << endl;
getch();
return 0;
}
Output looks like:
phi delta beta theta omega alpha rho gamma epsilon
alpha beta delta epsilon gamma omega phi rho theta
Data Structures Lab Handouts 70
Computing Execution Time
#include <iostream>
#include <time.h>
#include <conio.h>
using namespace std;
int main ()
{
time_t start,end;
char szInput [25];
double dif;
time (&start);
cout << "Please, enter your name: ";
cin>> szInput;
time (&end);
dif = difftime (end,start);
cout <<"Hi "<< szInput ;
cout << " It took you "<< dif<< " seconds to type your name."<< endl;
getch();
return 0;
}
Data Structures Lab Handouts 71
Lab 16
Implementation of Searching Techniques
The main objective of this lab is to compare the efficiency of different searching
techniques we have studied in the course.
Implement the following searching techniques and count number of comparisons for
successful and unsuccessful search.
1. Sequential Search
2. Binary Search
Sequential Search
int Sequential( int x[], n, key)
{
for (int i = 0; i< n; i++)
if (key == x[i]) return (i);
return (-1);
}
N Sequential Search Binary Search
Successful Unsuccessful Successful Unsuccessful
10
100
1000
5000
10000
20000
50000
Data Structures Lab Handouts 72
Binary Search
int Binary( int x[], n, key)
{
int low = 0;
int hi = n-1;
while (low <= hi)
{
int mid = (low + hi) / 2;
if (key == x[mid])
return (mid);
if (key < x[mid])
hi = mid – 1;
else
low = mid + 1;
}
return –1;
}
Data Structures Lab Handouts 73
Searching using STL: MAPS
A map is something like an associative array or hash table, in that each element consists of
a key and an associated value. A map must have unique keys, whereas with a multimap
keys may be duplicated.
Example:
To see how maps work, let's look at a simple application that counts word frequency.
Words are input one per line and the total count of each is output.
#include <iostream>
#include <string>
#include <map>
#include conio.h>
using namespace std;
int main()
{
typedef map<string, long, less<string> > MAP;
MAP counter;
char buf[256];
while (cin >> buf)
counter[buf]++;
MAP::iterator it = counter.begin();
while (it != counter.end()) {
cout << (*it).first << " " << (*it).second << endl;
it++;
}
getch();
return 0;
}