0% found this document useful (0 votes)
5 views26 pages

22 01ContiguousStacks

The document provides an overview of stacks and their array-based implementation in C, emphasizing the importance of encapsulation and information hiding in data structures. It defines key concepts such as Abstract Data Types (ADTs) and outlines the operations associated with stacks, including push, pop, and checking for empty or full states. The document also includes code examples to illustrate the implementation and usage of stacks in programming.

Uploaded by

yussufahmed.dev
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views26 pages

22 01ContiguousStacks

The document provides an overview of stacks and their array-based implementation in C, emphasizing the importance of encapsulation and information hiding in data structures. It defines key concepts such as Abstract Data Types (ADTs) and outlines the operations associated with stacks, including push, pop, and checking for empty or full states. The document also includes code examples to illustrate the implementation and usage of stacks in programming.

Uploaded by

yussufahmed.dev
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

CS 214: Data Structures

Stacks and Array-based Implementation

Slide contents follow


Kruse and Leung “Data Structures & Program Design in C”

Prepared by:
Waleed A. Yousef, Ph.D.

© Waleed A. Yousef 2008 1


Introduction: array as a familiar data structure
Implementation level User Level
int MyArr[10]; //Many things
9 happen here.

1- reserving a contiguous space in memory,


so that:
memory size = element size  #elements

2- giving the starting address the name


4
MyArr
MyArr 3
1006 MyArr[3] = 27; //Many things
2
happen here.
1
MyArr 0
1000
1- calculates the location address:
Loc address = MyArr+ 3 * sizeof(int)
= MyArr+ 6
2- Stores 27 in that location.
© Waleed A. Yousef 2008 2
Information hiding (Encapsulation):

- The use of functions. You use the structure at the


“User Level” without caring about the details at the
“Implementation Level”.

- Your program, i.e., the user level, does not change


even if the implementation of the used structure is
changed.

- Your program is clear from the logical point of view.

- Enhancing the Top-Down-Design.


© Waleed A. Yousef 2008 3
Motivation: What and Why Stacks?

Push box Q onto empty stack: Q


|empty stack |

Push box A onto stack: A


Q

Pop a box from stack: A


Q

Pop a box from stack: Q


|empty stack |

© Waleed A. Yousef 2008 4


Push box R onto stack: R
|empty stack |

Push box D onto stack: D


R

Push box M onto stack: M


D
Q

Pop a box from stack: M


D
Q

S
Push box Q onto stack: Q Push box S onto stack: Q
D Q
Q Q

© Waleed A. Yousef 2008 5


Motivation for Stacks as new Data Structures

Assume that we need to read a line of text and write it


back in a reverse order. In general, store some data and
retrieve it in a reverse order.

void ReverseRead(void){
StackEntry item;//StackEntry should be defined as char
Stack stack;
CreateStack(&stack);//Initialize the stack to be empty

while (!StackFull(&stack) && (item = getchar()) != '\n')


Push(item, &stack);//Push each item onto the stack

while (!StackEmpty(&stack)){
Pop(&item, &stack); //Pop an item from the stack.
putchar(item);
}
putchar('\n');
}
© Waleed A. Yousef 2008 6
Again: Information hiding (Encapsulation):

- The use of functions. You use the structure at the


“User Level” without caring about the details at the
“Implementation Level”.

- Your program, i.e., the user level, does not change


even the implementation of the used structure is
changed.

- Your program is clear from the logical point of view.

- Enhancing the Top-Down-Design.


© Waleed A. Yousef 2008 7
Definitions, where every thing should start from!
Definition: type is a set of values and a set of operations on
those values.

Example: We can define a datatype boolean that takes the set


of values {0, 1} together with the operations AND, OR, and NOT.

Example: int, in C, is the set consisting all of the integers


between INT_MIN (-(215  1)) and INT_MAX (215 – 1),
which are defined in the header file limits.h

Definition: A Sequence of length 0 is empty. A sequence of


length n  1 of elements from a set T is an ordered pair (Sn-
1,t) where Sn-1 is a sequence of length n-1 of elements from T,
and t is an element of T.

© Waleed A. Yousef 2008 8


Definition: Abstract Data Type (ADT) is a data type that is
accessed only through an interface (or Accessing mechanism).
We refer to a program that uses an ADT as a client (or user) and
a program that specifies the data type as an implementation
Definition: Stack of elements of type T is a finite sequence of
elements of T together with the following operations:
1.Create the stack, leaving it empty.
2.Determine whether the stack is empty or not.
3.Determine whether the stack is full or not.
4.Find the size of the stack.
5.Push a new entry onto the top of the stack, provided the stack is
not full.
6.Pop the entry off the top of the stack, provided the stack is not
empty.
7.Retrieve the Top entry off the stack, provided the stack is not
empty.
8.Traverse the stack, visiting each entry.
9.Clear the stack to make it empty.
© Waleed A. Yousef 2008 9
Type Definition

typedef struct stack{


int top;
StackEntry entry[MAXSTACK];
}Stack;

MAXSTACK-1 StackEntry and


MAXSTACK should be
defined in the User Level.

For the moment forget


about them. We will
mention later how they
top 0
should be defined.
entry
struct stack  Stack
© Waleed A. Yousef 2008 10
Implementation level User Level
(what really happens) (interface)
void CreateStack(Stack s){ void main(){
s.top=0;
} CreateStack Stack s;

MAXSTACK-1 CreateStack(s);

top -2580 0
entry }
s
When we return:

MAXSTACK-1

top -2580 0
entry
© Waleed A. Yousef 2008 s 11
Implementation level But this way User Level
(what really happens) (interface)
void CreateStack(Stack *ps){ void main(){
ps->top=0;
} Stack s;

CreateStack(&s);
CreateStack
&s }
ps When we return:
The execution time does
not depend on n;
MAXSTACK-1 therefore the complexity
is: (1)
top -2580 0
entry top is the index of the
© Waleed A. Yousef 2008
s first available place. 12
Implementation level User Level
(what really happens) (interface)
void Push(StackEntry e, Stack *ps){
ps->entry[ps->top]=e;
ps->entry[ps->top++]=e;
ps->top++;
}
void main(){
Push StackEntry e;
Stack s;
e &s 
ps CreateStack(&s);

Push(e, &s);
MAXSTACK-1
}
top 0
1 0 e
entry

© Waleed A. Yousef 2008


s 13
/*Pre: The stack is initialized and not full
Post: The element e has been stored at the top of
the stack; and e does not change*/
void Push(StackEntry e, Stack *ps){
ps->entry[ps->top++]=e;
}
The user has to check before calling Push
Other ways (no precondition) are: void main(){
if (ps->top==MAXSTACK) StackEntry e;
printf(“Stack is full”); Stack s;
else ps->entry[ps->top++]=e; 
//but this is not professional CreateStack(&s);

int Push(…){ if (!StackFull(s))
if (ps->top==MAXSTACK) Push(e, &s);
return 0; }
else {
ps->entry[ps->top++]=e; if (!Push(e, &s))
return 1; …
}//This is fine
© Waleed A. Yousef 2008 14
Implementation level User Level
(what really happens) (interface)
int StackFull(Stack *ps){
if (ps->top==MAXSTACK)
return 1;
else return ps->top >= MAXSTACK;
return 0; void main(){
} StackEntry e;
StackFull Stack s;

&s
CreateStack(&s);
ps

if (!StackFull(&s))
Push(e, &s);
MAXSTACK-1 }

top MAXSTACK 0 e It could be: StackFull(s)


entry but this wastes memory and
time of copying.
© Waleed A. Yousef 2008 s 15
Implementation level User Level
(what really happens) (interface)
void Pop(StackEntry *pe, Stack *ps){
ps->top--;
*pe=ps->entry[--ps->top];
*pe=ps->entry[ps->top];
}
void main(){
Pop StackEntry e;
Stack s;
&e &s 
pe ps CreateStack(&s);

Pop(&e, &s);
MAXSTACK-1
}
### top 1
0 0 ###
e entry

© Waleed A. Yousef 2008


s 16
/*Pre: The stack is initialized and not empty
Post: The last element entered is returned*/

void Pop(StackEntry *pe, Stack *ps){


*pe=ps->entry[--ps->top];
}
The user has to check before calling Pop
Other ways (no precondition) are: void main(){
if (ps->top==0) StackEntry e;
printf(“Stack is Empty”); Stack s;
else *pe=ps->entry[--ps->top]; 
//but this is not professional CreateStack(&s);

int Pop(…){ if (!StackEmpty(s))
if (ps->top==0) Pop(&e, &s);
return 0; }
else {
*pe=ps->entry[--ps->top]; if (!Pop(&e, &s))
return 1; …
}//This is fine
© Waleed A. Yousef 2008 17
Implementation level User Level
(what really happens) (interface)
int StackEmpty(Stack *ps){
if (ps->top==0)
return 1;
else return !ps->top;
return 0; void main(){
} StackEntry e;
StackEmpty Stack s;

&s
CreateStack(&s);
ps

if (!StackEmpty(&s))
Pop(&e, &s);
MAXSTACK-1 }

top 0 0 e It could be: StackEmpty(s)


entry but this wastes memory and
time of copying.
© Waleed A. Yousef 2008 s 18
Implementation level User Level
(what really happens) (interface)
//Same preconditions of Pop.
void StackTop(StackEntry *pe, Stack *ps){
*pe=ps->entry[ps->top-1];
} void main(){
StackEntry e;
StackTop Stack s;

&e &s CreateStack(&s);
pe ps 
StackTop(&e, &s);
}
MAXSTACK-1
It could be:
### top 1 0 ### StackTop(&e, s)
e entry but this wastes memor
© Waleed A. Yousef 2008
s and time of copying 19
Implementation level User Level
(what really happens) (interface)
/*Pre: Stack is initialized.
Post: returns how many elements exist.
int StackSize(Stack *ps){
return ps->top; void main(){
} StackEntry e;
StackSize Stack s;
int x;
&s 
ps CreateStack(&s);

x=StackSize(&s);
MAXSTACK-1 }
It could be:
top 1 0 ### StackSize(s)
entry but this wastes memory
© Waleed A. Yousef 2008
s and time of copying 20
Implementation level User Level
(what really happens) (interface)
/*Pre: Stack is initialized.
Post: destroy all elements; stack looks initialized.
void ClearStack(Stack *ps){
ps->top=0; void main(){
} StackEntry e;
ClearStack Stack s;

&s CreateStack(&s);
ps 
ClearStack(&s);
}
MAXSTACK-1 Same code as
CreateStack; why
top 1
0 0 ### new function then?
entry 1- conceptually
2- will see later
© Waleed A. Yousef 2008
s 21
Implementation level
//Precondition: The stack is Initialized
void TraverseStack(Stack *ps, void(*pf)(StackEntry)){
for(int i=ps->top; i>0; i--)
(*pf)(ps->entry[i-1]); User Level:
} how to process each element
pf with a user-defined function
=
&Display void Display(StackEntry e){
printf(“e is: %d\n", e);
}
The code of
Display ps=&s void main(){

Stack s;
MAXSTACK-1
CreateStack(&s);
.
.
top 0 TraverseStack(&s, &Display);
entry }
s //&s only for efficiency as
© Waleed A. Yousef 2008 said before. 22
Exercise: How to write the function StackTop in the user level? (e.g.,
if you do not have the source code of the implementation)

User Level:
void StackTop(StackEntry *pe, Stack *ps){
Pop(pe, ps); /* Why interface, Pre, Post are crucial:
Push(*pe, ps); Pop takes a pointer to the element and a
} pointer to the stack.

Pre: The stack is initialized and not


void main(){ empty
StackEntry e;
Stack s; Post: The last element entered is returned

CreateStack(&s);
 Push takes the element itself and a
StackTop(&e, &s); pointer to the stack
}
Pre: The stack is initialized and not full

Post: The element e has been stored at the


© Waleed A. Yousef 2008 top of the stack; and e does not change*/ 23
void StackTop(StackEntry *pe, Stack *ps){
Pop(pe, ps); StackTop
Push(*pe, ps); &e &s
} pe ps
Push
Pop
###
&e &s
e pe ps

###
e

MAXSTACK-1

top 1
0 0 ###
entry

© Waleed A. Yousef 2008


s 24
StackEntry and MAXSTACK should be defined in the User
Level, because they concern the uer.

Also, they have to be defined in the implementation level, because


they are referenced in Stack.cpp

Therefore, they have to be defined in Stack.h which is included


in both Stack.cpp and the user main file.

So, the main file will compile even if stack.cpp is not compiled
yet. (check the homework; this is detailed in the sheet)

© Waleed A. Yousef 2008 25


/****Stack.h*******/
#define MAXSTACK 100

typedef struct stack{


int top;
StackEntry entry[MAXSTACK];
} Stack;

void Push (StackEntry, Stack *);


void Pop (StackEntry *, Stack *);
int StackEmpty (Stack *);
int StackFull (Stack *);
void CreateStack(Stack *);
void StackTop (StackEntry *, Stack *);
int StackSize (Stack *);
void ClearStack(Stack *);
void TraverseStack(Stack *, void (*)(StackEntry));

© Waleed A. Yousef 2008 26

You might also like