Chapter 3: Lists, Stacks and Queues • Concept of Abstract Data Type (ADTS) • How to efficiently perform operations on list • Stack ADT and its applications • Queue ADT and its applications
Mar 30, 2015
Chapter 3: Lists, Stacks and Queues
• Concept of Abstract Data Type (ADTS)
• How to efficiently perform operations on list
• Stack ADT and its applications
• Queue ADT and its applications
3.1 Abstract Data Type
• Modular program
• Advantages:
(1) debugging
(2) team work
(3) easy to modify
3.1 Abstract Data Type
• Abstract data typea set of operations
mathematical abstractions
just as integer, boolean
• Basic idea
write once, use many
Any changes are transparent to the other modules
3.2 List ADT
• Review on linked list
• Common errors
memory allocation
segmentation violation
check for NULL pointer
free memory
3.2 List ADT
• Doubly linked list
struct node
{ int Number;
struct node *left;
struct node *right;
}
3.2.1 List ADT: Example1
• Single-variable Polynomials
N
i
iiXAXF
0
)(typedef struct
{ int CoeffArray[MaxDegree+1];
int HighPower
} *polynomial
3.2.1 List ADT: Example 1
• Initialize a polynomial
void ZeroPolynomial(Polynomial Poly)
{ int j;
for (j = 0; j < MaxDegree; j++)
poly->CoeffArray[j] = 0;
Poly->HighPower = 0;
}
3.2.1 List ADT: Example 1
• Add two polynomials
void AddPolynomial(const Polynomial Poly1, const Polynomial Poly2, Polynomial PolySum)
{ int j;
ZeroPolynomial(PolySum);
PolySum->HighPower = Max(Poly1-> HighPower, Poly2 -> HighPower);
for (j=PolySum->HighPower; j>=0; j--)
PolySum->CoeffArray[j] = Poly1-> CoeffArray [j] + Poly2-> CoeffArray[j];
}
3.2.1 List ADT: Example 1
• Multiply two polynomialsvoid MultPolynomial(const Polynomial Poly1, const Polynomial
Poly2, Polynomial PolyProd)
{ int j,k;
ZeroPolynomial(PolyProd);
PolySum->HighPower = Poly1-> HighPower+ Poly2 -> HighPower;
for (j=0; j=Poly1->HighPower; j++)
for (k=0; k=Poly2->HighPower; k++)
PolyProd->CoeffArray[j+k] += Poly1-> CoeffArray [j]* Poly2-> CoeffArray[k];
}
3.2.1 List ADT: Example 1
• Multiply two polynomials: limitation
• Consider the following situationP1(X) = 10 X1000 + 5X14 + 1
P2(X) = 3X1990 - 2X1492 +11X +5
• Most of the time is spent multiplying zeros
3.2.1 List ADT: Example 1
• Multiply two polynomials: better structure
struct node
{ int Coefficient;
int Exponent;
struct node *Next;
}
3.2.1 List ADT: Example 1
• Linked list representation of the previous structure
3.2.2 List ADT: Example 2
• Multilists• A university with 40,000 students and 2,500
subjects needs to generate 2 reports
1. Lists of registration for each class
2. Classes that each student registered.
Implementation: construct 2D array (40Kx2K5) = 100M entries
if each student takes 3 subjects => only 120K entries (~0.1% of 100M) => waste of resources.
3.2.2 List ADT: Example 2
MultilistsMultilists
3.3 Stack ADT
• Stack model
3.3 Stack ADT
• LIFO structure
• Access from the top
• Basic Operations– empty (s)– pop (s) – push (s, i) – top (s)
3.3.1Implementation of stack using Linked List
struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode Stack;
struct Node{ ElementType Element;
PtrToNode Next;
}
3.3.1Implementation of stack using Linked List
int IsEmpty(Stack S);
Stack CreatStack(void);
void DisposeStack(Stack S);
void MakeEmpty(Stack S);
void Push(ElementType X, Stack S);
void Pop(Stack S);
ElementType Top(Stack S);
3.3.1Implementation of stack using Linked List
• Test for an empty stack
int Isempty(Stack S)
{
return (SNext == NULL)
}
3.3.1Implementation of stack using Linked List
• Create an empty stackstack CreatStack(void)
{ Stack S;
S=malloc(sizeof(struct Node));
if (S==NULL)
FatalError(“Out of space!!!”);
MakeEmpty(S)
return(S);
}
void MakeEmpty(Stack S){ if (S==NULL)
printf(“Error message!”);
else
while (!IsEmpty(S))
pop(S)
}
3.3.1Implementation of stack using Linked List
• Push onto a stackvoid Push(ElementType X, Stack S)
{ PtrtoNode TmpCell;
TmpCell = malloc(sizeof(struct Node));
if (TmpCell == NULL)
fatalError(“message”);
else
{ TmpCell Element = X;
TmpCell Next = S Next;
S Next = TmpCell;
}
}
3.3.1Implementation of stack using Linked List
• Return top element in a stack
ElementType Top(Stack S)
{ if (!IsEmpty(S))
return (S Next Element);
Error(“Empty stack”);
return 0;
}
3.3.1Implementation of stack using Linked List
• Pop from a stackvoid Pop(Stack S)
{ PtrToNode FirstCell;
if (ISEmpty(S);
Error (“Empty stack”);
else
{ FirstCell = S Next;
S Next =S Next Next;
free(FirstCell);}
}
3.3.2 Implementation of stack using Array
Struct StackRecord
{
int Capacity;
int TopOfStack;
ElementType *Array;
}
#define STACKSIZE 100
Struct StackRecord
{ int top;
ElementType Array[STACKSIZE];
}
3.3.2 Implementation of stack using Array
• Test for empty stack
empty (stack *ps)
{
return (ps top == -1)
}
3.3.2 Implementation using Array
• Pop top element from stackint pop (stack *ps)
{ int x
if (empty (ps))
printf (“%s\n”, “stack underflow!”);
else
{ x = ps array [ps top];
(ps top)--;
return (x); }
}
3.3.2 Implementation using Array
Push an element onto the stackpush (stack *ps, int x)
{ if (ps top == STACKSIZE – 1)
printf (“%s\n”, “stack overflow!”);
else
{ (ps top)++;
ps items [ps top] = x;
}
}
3.3.3 Variable types of stack elements
#define STACKSIZE 100
#define INTGR 1
#define FLT 2
#define STRING 3
struct stackelement
{
int etype; /* element type */
union
{ int ival;
float fval;
char *pval;
} element; /* end union */
}
3.3.3 Variable Types of Stack Elements
• To access the top elementstruct stack s;
struct stackelement se;
se = s.items [s.top];
switch (se.etype)
{
case INTGR: printf (“%d\n”, se.ival); break;
case FLT: printf (“%d\n”, se.fval); break;
case STRING: printf (“%s\n”, se.pval);
}
3.3.4 Applications
• Balancing Symbols• Make an empty stack. Read characters until end of file.
• If the character is an opening symbol, push it onto stack.
• If it is a closing symbol, then if the stack is empty, report an error. Otherwise, pop the stack.
• If the symbol popped is not the corresponding opening symbol, then report an error.
• At the end of file, if the stack is not empty, report an error.
3.3.4 Applications
• Postfix Expressions
• 4.99+5.99+6.99*1.06 = 19.05 or 18.39
• postfix notation of (4.99*1.06 + 5.99 + 6.99*1.06)
is 4.99 1.06 * 5.99 + 6.99 1.06 * +
• Why do we need postfix notation?
3.3.4 Application: Postfix
• How does postfix work?
• e.g. 6 5 2 3 + 8 * + 3 + *
3.3.4 Application : Postfix
3.3.4 Application : Postfix
3.3.4 Applications
• Converting infix expressions into postfix
• Infix A * B + C * D
• Postfix A B * C D * +
3.3.4 Application: infix postfix
Stack -> Input Postfix StringA A
* * A
* B A B
+ + A B *
+ C A B * C
+ * * A B * C
+ * D A B * C D
pop stack A B * C D * +
3.3.4 Application: infix postfix
opstk = the empty stack;
while (not end of input)
{ symb = next input character;
if (symb is an operand)
add symb in the postfix string;
else
{ while (!empty (opstk) && prcd (stack (opstk), symb))
{ topsymb = pop (opstk);
add topsymb to postfix string;
}
push (opstk, symb);
}
}
3.3.4 Application: infix postfix
/* output any remaining operators */
while (!empty (opstk))
{
topsymb = pop (opstk);
add topsymb to the postfix string;
}
3.3.4 Application: infix postfix
With parentheses
Stack -> Input Postfix String
( (
( A A
( + + A
( + B A B
) A B +
* * A B +
* C A B + C
pop stack A B + C *
3.3.4 Application: infix postfix
• Please refer to infix2postfix.doc for implementation.
3.4 Queue ADT
Ordered collections of data items– Delete item at front of the queue– Insert item at rear of the queue– A FIFO structure
A B C D E
front rear
3.4 Queue ADT
• Basic operations
(1) insert (q, x)
(2) remove (q, x)
(3) empty (q)
3.4 Queue ADT
• Array implementation#define MAXQUEUE 100
struct queue
{
int items [MAXQUEUE];
int front, rear, length;
} q;
3.4 Queue ADT
void insert (q, x)
{
q.length++;
q.rear++;
q.items [q.rear] = x;
}
3.4 Queue ADT
void remove (q, x)
{
x = q.items [q.front];
q.front++;
q.length--;
}
3.4 Queue ADT
• Problem: May run out of rooms
(1) Keep front always at 0 by shifting the contents up the queue, but the computer solution is inefficient
(2) Use a circular queue (wrap around & use a length variable to keep track of the queue length)
3.4 Queue ADT
insert (queue *pq, int x)
{ if ((pq length) == MAXQUEUE) /* check for overflow */
printf (“Queue overflow”);
else
{ (pq length)++; /* make room for a new element */
if ((pq rear) == MAXQUEUE - 1)
pq rear = 0;
else (pq rear)++;
pq items [pq rear] = x;
/* check if queue is originally empty */
if ((pq length) == 1)
pq front = pq rear;
}
}
3.4 Queue ADT
void empty (queue *pq)
{
if ((pq length) == 0)
return (TRUE);
else
return (FALSE);
}
3.4 Queue ADT
void remove (queue *pq)
{ if (empty (pq))
printf (“Queue underflow”);
else
if (pq front == MAXQUEUE - 1)
{ pq front = 0;
return (pq items [MAXQUEUE - 1]);
}
else
{ (pq front)++;
return (pq items [(pq front) - 1]);
}
}
3.4 Applications of Queues
• Print jobs
• Computer networks
• OS
• Real-life waiting lines