Академический Документы
Профессиональный Документы
Культура Документы
Supratim Biswas
Computer Science & Engineering Department
Indian Institute of Technology, Bombay
Linear Data Structures and Applications
Prerequisite : Familiarity with Programming in C / C++;
basics of algorithms; Material covered in Lecture 1 of this
module
int i = 10;
1. Name
2. Data Type
3. Size in bytes
4. r-value, the read value of the variable/object
5. l - v a l u e , t h e a d d r e s s i n m e m o r y o f
variable/object
6. Scope (visibility)
Pointer Data Type
A data type is defined in terms of a set of values and a
set of operators.
4 L binary || logical OR
Examples :
– what is p ?
– what is *p ?
– what is &p?
Operations on Pointers
A pointer may be assigned to another pointer of
same type.
int i = 0;
int *ip = & i; // legal ?
int k = ip ; // legal ?
unsigned int *uip = ip ; // is it legal ?
int *ip2 = &ip ; // is it legal ?
int **ip3 = &ip ; // is it legal
int *ip4 = i ; // is it legal ?
int * ip - & i
int * ip - & i
We examine D3 next.
Attributes i flag ch s
Name i flag ch s
Type int bool char string
Size 4 bytes 1 byte 1 byte 8
r-value 20 0 # CS 101
l-value 0x7fff1a24 0x7fff1a24bd # 0x7fff1a24bd50
bd58 5f
significant byte)
7 6 5 4 3 2 1 0
00 00 7f ff 1a 24 bd 58
Pointers and Hexadecimal Representation
00 00 7f ff 1a 24 bd 58
Pointers and Hexadecimal Representation
The 5th rowof the table that provides the l-value
attribute of a variable needs some details for its
explanation.
l-value 0x7fff1a24bd58 0x7fff1a24bd5f # 0x7fff1a24bd50
int i = 0;
object i
int i = 0;
int & refi = i;
int j = 10;
refi = j; // same as i = j, i.e., both i and refi
// have 10 as their r-value
refi = &j; // type error - lhs is int & and rhs is
// int* and they are distinct
*refi = j; // *refi is illegal !
....
Reference Type in C++
You may try other means but you just can not
change the binding of refi to i that got established
at the time of declaration of refi.
int main()
{ int x, y;
cout << " Give 2 integers : " ;
cin >> x >> y ; cout << " values before direct
swap " << endl;
cout << " x = " << x << " y = " << y << endl;
swap(x, y );
cout << " values after direct swap " << endl;
cout << " x = " << x << " y = " << y << endl;
Function Arguments as Reference Type
swap_ptr(&x, &y );
cout << " values after poiner swap " << endl;
cout << " x = " << x << " y = " << y << endl;
swap_ref(x, y );
cout << " values after reference swap " << endl;
cout << " x = " << x << " y = " << y << endl;
}
x3 - f(x1, x2)
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
Situation 2: After processing of declarations : variables
are initialised.
type3 f(type y1, type2&y2)
type1 x1 = v1 x1 v1
type2 x2 = v2 x2 v2
type3 x3 = v3 x3 v3
--------
x3 - f(x1, x2)
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
Situation 3: Just before call to f() : parameters are
passed, x1 to y1 by value and x2 to y2 by reference,
y2 has the lvalue of x2.
type1 x1 = v1 x1 v1
type2 x2 = v2 x2 v2 &x2 v1
y2 y1
type3 x3 = v3 x3 v3
--------
x3 - f(x1, x2)
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
Situation 3: Just before call to f() : parameters are
passed, x1 to y1 by value and x2 to y2 by reference,
y2 has the lvalue of x2.
type1 x1 = v1 x1 v1
type2 x2 = v2 x2 v2 &x2 v1
y2 y1
type3 x3 = v3 x3 v3
--------
x3 - f(x1, x2)
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
Situation 4: Just after call to f() : control is passed from
caller to the first statement in the body of callee f() and
execution continues from this point.
type1 x1 = v1 x1 v1
type2 x2 = v2 x2 v2 &x2 v1
y2 y1
type3 x3 = v3 x3 v3
-----------
--------
x3 - f(x1, x2)
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
Situation 5: In the body of f() just after execution of y2
= v4. The value of x2 in the caller changes because of
reference.
type3 f(type y1, type2&y2)
type1 x1 = v1 x1 v1
type2 x2 = v2 x2 v4 &x2 v1
y2 y1
type3 x3 = v3 x3 v3
-----------
--------
x3 - f(x1, x2)
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
Situation 6: Just after execution of return e1 in caller f().
The control is back to the caller and the rhs of call is
complete, the execution resumes to complete the
assignment to lhs.
type3 f(type y1, type2&y2)
type1 x1 = v1 x1 v1
type2 x2 = v2 x2 v4
type3 x3 = v3 x3 v3
-----------
--------
x3 - f(x1, x2)
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
Situation 7: Just after completion of the call statement
in caller. The return value is assigned to x3.
type1 x1 = v1 x1 v1
type2 x2 = v2 x2 v4
----------
type3 x3 = v3 x3 e1
--------
x3 - f(x1, x2)
----------
y2 = v4;
return e1
caller callee
Parameter Passing Mechanisms
by value.
A note on strings and array of strings
A string is given 8 bytes, because of which an array of
size 100 of strings, requires 800 bytes. What is there in
these 8 bytes ?
O n c o m p i l a t i o n a n d exe c u t i o n , t h e o u t p u t
displayed is :
sizeof str : 8
r- v a l u e o f s t r = CS 101 : Computer
Programming & Utilization
length of str : 45
Strings and Reference Type
Attributes of a Variable : All declared objects
possess 5 attributes and in fact more, which shall
be introduced in due course. The five attributes
of the string variable str, as displayed in the
output, are
0x7fff8cb10250
int main(){
int a[] = { 2, 5, 3, 4, 1, 5};
int b[] = { 12, 15, 3, 4, 19, 5};
cout << " maximum is " << max(a, 6) << endl;
cout << " maximum is " << max(b, 6) << endl;
return 0;
}
int main() {
int a[] = { 2, 5, 3, 4, 1, 5};
int b[] = { 12, 15, 3, 4, 19, 5};
char ch[] = {'1', '2', 'a', ';', '!'};
cout << " maximum is " << max(a,6) << endl;
cout << " maximum is " << max(b,6) << endl;
cout << " maximum is " << max(ch, 5) << endl;
return 0;
}
1. N o d e f n i t i o n s o f s u c h a f u n c t i o n i s f o u n d – r e p o r t
appropriate error message. Call is not resolved.
2. Use the signature of the call to find an exact match with a
signature of a concrete function definition from the set of
all definitions of this function available at the call-point.
• In case the signature of call matches exactly with one
definition, the call is resolved to this definition.
• Note that the call cannot exactly match two or more
concrete function definitions because the signatures of
two or more definitions of an overloaded function are
different.
• Also note that template definitons of this function are not
considered in this step.
Compile time Resolution of Function Calls
3. In the event that compiler fails to find an exact match in
step 2, the compiler examines the template definitions
available.
• Derives the value of Type variable T by unifying the two
signatures. If the unification is successful, the template
definition is instantiated to create a concrete function.
• The compiler resolves the call to this created concrete
function. Note that if the unification is not successful or
more than 1 template definition unifies successfully, the
compiler fails to resolve the call.
• The resolution of the call in this step may also be viewed
as an exact match with the definition of the concrete
function used.
• The only difference is that this concrete function did not
exist before the call, is fresh from the mint, generated by
the compiler using the template.
Compile time Resolution of Function Calls
public :
int val;
node * next;
};
Linked Lists
• This introduces a new type to the program, named
as " node". However this declaration does not create
an object and hence does not get any memory
allocated.
bool isempty ()
{ if ( head == 0 ) return true;
else return false;
}
}
Linked List Class Design
• The only data member of an object instance of our
class is a place to save the address of the first element
of the list. The name, head, is used for this purpose.
{ node * p = head;
int count = 0;
return count;
}
Linked List Class Design
• Member function insert() is relatively easy as we insert the
new element at the head of the list. First get memory from
the heap, initialize with the element value.
node *p = new node;
if ( p == 0 )
cerr << " fatal error : no space on heap " << endl;
p->val = elm;
class list {
class node { public:
int val;
node * next;
};
public : node *head;
list() { head = 0;} // constructor
void display ( )
{ node * p = head;
}
Complete design of the linked list class
list concat (list l)
{ list res; int val;
node *curr = head; node *tail = res.head;
if ( curr == 0 ) return res = l;
else
{ while (curr != 0)
{ res = res.append (curr->val);
if ( tail != 0 ) tail = tail->next;
else tail = res.head;
curr = curr->next;
};
tail->next = l.head;
};
return res;
}
Complete design of the linked list class
list append (int elm )
{ // find the last node of list
node *p = new node;
p->val = elm; p->next = 0;
if ( head == 0 ) head = p;
else { node *curr = head; node *prev = head;
while ( curr != 0 )
{ prev = curr; curr = curr->next; };
prev->next = p;
};
return *this;
}
};
Complete design of the linked list class
// A function to use the class design
int main()
{ int num;
list l,m ;
while ( cin >> num)
{ l = l.append(num); m = m.insert(num);}
cout << " length of list l = " << l.length() << endl;
cout << " display of list l follows " << endl;
l.display();
cout << " \nlength of list m = " << m.length() << endl;
cout << " display of list m follows " << endl; m.display();
list merge1;
merge1 = l.concat(m);
cout << " \nlength of list merge1 = " << merge1.length()
<< endl;
cout << " display merged list l and m \n" << endl;
merge1.display();
}
Complete design of the linked list class
For the Input : 7 31 41 13 53
The output is shown in 2 columns below :
val next
int node*
node
Stack as a Linked List
A linked stack would require a single pointer to the stack.
The stack elements, themselves, would be residing on the
heap. An initialized linked stack is visually shown below.
This operation may be denoted by the pseudo code :
stack T;
An empty stack has no elements and hence looks like :
top
null
top
heap
val next
20 val next
-10 null
top
heap
val next
20 null
elm
-10
stack_item *next;
};
Stack as a Linked List
class stack {
stack_item * stack_top; // stack top pointer
stack_item* makenode (item_type item)
{ stack_item *p;
if ( (p = new stack_item) == NULL ) cerr
<< "run out of memory"<< endl;
else { p->info = item; p->next = NULL;
return p; }
}
public :
stack() { stack_top = 0;}
Stack as a Linked List
{ stack_item *p;
p = makenode(item);
if ( p == NULL) cerr << "push not
possible : no node" << endl;
}
Stack as a Linked List
bool isfull()
{ stack_item *p;
if ( (p = new stack_item) == NULL ){ cerr
<< "run out of memory" << endl;
return true; }
else return false;
}
• Output produced is :
Item inserted is Python
Item inserted is Bash
Item inserted is Java
Item inserted is C++
Item inserted is C
Item inserted is CUDA
Item inserted is C#
stack is not full
Stack as a Linked List
Item deleted is C#
Item deleted is C
stack is empty
Template class design for singly linked list
The single linked list realization for a stack of strings may be
extended to create a stack of objects of various types.
// file stack_template_linked.h
// declaration section
template <class T > class stack;
template <class T > class stack_item {
friend class stack <T> ;
private : T info;
stack_item<T> *next;
friend istream& operator>> ( istream & x,
stack_item<T> &s )
{ return x >> s.info; };
friend ostream& operator<< ( ostream & x,
stack_item<T> s )
{ return x << s.info; };
};
Template class design for singly linked list
public :
stack ( ) { tos = 0; }
int main()
{
int i; float item;
stack<float> floatstack;
ifstream inf ("floatfile", ios::in);
ifstream inc ("charfile", ios::in);
cout << " creating a float stack " << endl;
while (inf >> item)
{ floatstack.push(item);
cout << "inserted element is : " <<
floatstack.peek () << endl;
};
Template class design for singly linked list
{ charstack.push(citem);
};
Template class design for singly linked list
}
Template class design for singly linked list
• Try testing with the input :
floatfile : 2.5 -3.1412 130.23 4.0 55
charfile : c @ :& ~ %$
An item may be inserted into the queue from the rear. The
item at the rear of a queue is the youngest item ( insert
operation)
Input strings :
Gaurav Pankaj Apurv Piyush Pratay Shivam Ashish
Output produced :
Give the items to be queued :
inserted Gaurav in Q
inserted Pankaj in Q
inserted Apurv in Q
inserted Piyush in Q
inserted Pratay in Q
inserted Shivam in Q
inserted Ashish in Q
Class Design for a Queue as a circular
linked list
******* testing length after insertion ************
length of q1 = 7