0% found this document useful (0 votes)
12 views67 pages

4

Chapter 4 covers Lists, Stacks, and Queues, focusing on their definitions, implementations, and operations. It discusses the differences between array-based and linked list implementations, including their performance characteristics and memory management. The chapter also introduces the Abstract Data Type (ADT) for lists and provides examples of list operations and applications such as merge sort.

Uploaded by

haidarfaiz979
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)
12 views67 pages

4

Chapter 4 covers Lists, Stacks, and Queues, focusing on their definitions, implementations, and operations. It discusses the differences between array-based and linked list implementations, including their performance characteristics and memory management. The chapter also introduces the Abstract Data Type (ADT) for lists and provides examples of list operations and applications such as merge sort.

Uploaded by

haidarfaiz979
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/ 67

Chap 4.

Lists, Stacks and Queues


Yuhao Yi
College of Computer Science
Sichuan University

https://yhyi15.github.io/teaching/DSA

Modified from Wenzheng Xu’s slides

1
In this Chapter, you will learn

Lists, Stacks, Queues


Separating a logical representation of an
ADT from a physical implementation of a
DS
Asymptotic analysis for simple operations
The Concept and use of dictionaries.

2
Why Lists?

A list is all you need to achieve anything


promised to a computer
The rest are all about improving efficiency
Stacks and Queues: list-like structures
1 List, 2 Stacks, 2 Queues are equally capable
Then why Stacks and Queues?
simple, fewer operations
come in handy in applications
3
Lists
A list is a finite, ordered sequence of data
items.
e.g., a list with five numbers: 10, 9, 7, 20, 8

Important concept: List elements have a


position.
Notation: <a0, a1, …, an-1>
a0 =10, a1 =9, a2 =7, a3 =20, a4 =8

What operations should we implement?


e.g., Insert an item at a particular position
Remove an item
4
List Implementation Concepts

Our list implementation will support the


concept of a current position.

We will do this by defining the list in terms


of left and right partitions.
 Either or both partitions may be empty.

Partitions are separated by a vertical bar.


<20, 23 | 12, 15>

5
List ADT (Abstract Data Type)
template <typename E> class List {
public:
virtual void clear()=0; // clear all items
virtual void insert(E &item)=0;
virtual void append(E &item)=0;
virtual void E remove()=0;
virtual void moveToStart()=0;
virtual void moveToEnd()=0;
virtual void prev()=0;
virtual void next()=0;
virtual int length()=0;
virtual int currPos()=0;
virtual void moveToPos(int pos)=0;
virtual E getValue()=0;
};
6
List ADT Examples

List: <12 | 32, 15>


L.insert(99);
Result: <12 | 99, 32, 15>

Iterate through the whole list:


for (L.moveToStart(); L.currPos()<L.length();
L.next()) {
it = L.getValue();
doSomething(it);
}
7
List Find Function
/** @return True if k is in list L,
false otherwise */
public static boolean
find(List<Integer> & L, int k) {
for (L.moveToStart();
L.currPos()<L.length(); L.next())
if (k == L.getValue()) return true;
return false; // k not found
}

8
Two physical implementations

Array-based lists
Linked lists

9
Represent a list with an array

curr: point to the first node in the right


partition separated by the fence
<|13,12, 20,8, 3>
curr

10
Array-Based List Class (1)
template <typename E>
class Alist : public List<E> {
private:
private E *listArray; //array holding elements
private int maxSize; // max size of list

private int listSize; //number of list items now


private int curr; // position of cur. element
public:
// Constructors
Alist(int size=10) {
maxSize = size;
listSize = curr = 0;
listArray = new E[ maxSize ];
}
11
Array-Based List Class (2)

public ~Alist(){ delete [] listArray;}


public void clear()
{ listSize = curr = 0; }

 Move position functions


public void moveToStart() { curr = 0; }
public void moveToEnd() { curr = listSize; }
public void prev() { if (curr != 0) curr--; }
public void next()
{ if (curr < listSize) curr++; }
public int length() { return listSize; }
public int currPos() { return curr; }

12
Array-Based List Class (3)
public void moveToPos(int pos) {
if( pos < 0 || pos >= listSize){
printf("Position out of range\n");
abort();
}
curr = pos;
}

public E getValue() {
assert( curr >= 0 && curr < listSize);

return listArray[curr];
}

13
Insert an element

An insert operation at position 0

14
Insert
/** Insert "it" at current position */
public void insert(E it) {
// List capacity exceeded
assert(listSize < maxSize );
for (int i=listSize; i>curr; i--)
listArray[i] = listArray[i-1];
listArray[curr] = it;
listSize++;
}

15
Append
public void append(E it) {
// Append "it“ at the end of the list
//List capacity exceeded
assert( listSize < maxSize);
listArray[ listSize ] = it;
listSize++;
}

16
Remove
/** Remove and return the current element */
public E remove() {
if ( curr < 0 || curr >= listSize)
return NULL;
E it = listArray[curr];
for(int i=curr; i<=listSize-2; i++)
listArray[i] = listArray[i+1];
listSize--;
return it;
}

17
Link Class
Dynamic allocation of new list elements.
// Singly-linked list node
template <typename E> class Link {
public:
E element; // Value for this node
Link *next; // Pointer to next node
Link(const E& elemval,
Link* nextval =NULL)
{ element = elemval; next = nextval; }
Link(Link* nextval =NULL)
{ next = nextval; }
};
18
Linked List Position-a naive approach
 Curr points to the first node in the
right partition
 Inserting an element is cumbersome

19
Linked List Position-A smart approach
 Curr points to the last node in the
left partition
 Add a head node
Eliminate special codes in the codes, such
as inserting an item in an empty list

20
The difference between array-based
lists and linked list
 The memory addresses of the
elements in an array list are in
increasing order
Assume that the start address of the
array is 1,000
The addresses of elements 13, 12,
20, 8, 3 are 1,000, 1,004, 1,008,
1,012, and 1,016, respectively
 The addresses of the elements
after current position increases by
4 with an insertion, if an int
varaible takes 4 bytes memory 21
The difference between array-based
lists and linked list (cont.)
 The memory addresses of
the elements in a linked list
have no relationship with
their positions in the list
Allocated by the operating
system
e.g., the memory addresses of
20, 23, 12, 15 are 1,000, 940,
1076, 40
 The addresses of the
elements already in the list
will not change after an 22

insertion
Linked List Class (1)
template <typename E>
class Llist : public List<E> {
private:
Link<E> * head; // pointer to list header
Link<E> * tail; // pointer to last element
Link<E> * curr; // access to current element
int cnt; // size of list
public:
//Constructors
Llist() {
curr = tail = head = new Link<E>(NULL);
cnt = 0;
}

23
Linked List Class (2)
public void clear() {
curr= head->next; //keep the head node
Link<E> *tmp;
while( curr != NULL){
tmp = curr;
curr = curr->next;
delete tmp;
}
head->next = NULL;
curr = tail = head;
cnt = 0;
}

~Llist(){
clear();
delete head; 24
}
Linked List Class (3)
public void moveToStart() { curr = head; }
public void moveToEnd() { curr = tail; }
public int length() { return cnt; }
public void next() {
if (curr != tail) { curr = curr->next; }
}
public E getValue() {
// Nothing to get;
assert(curr->next != NULL);

return curr->next->element;
}

25
Insertion

26
Insert/Append
// Insert "it" at current position
public void insert(E it) {
Link<E> *tmp = new Link<E>(it, curr->next);
curr->next = tmp;
if (tail == curr) tail = curr->next;
cnt++;
}
public void append(E it) {
tail->next = new Link<E>(it, NULL);
tail = tail->next;
cnt++;
}

27
Removal

28
Remove
/** Remove and return current element */
public E remove() {
// if no elements;
assert(curr->next != NULL);
if (tail == curr->next) tail = curr;
// tmp points to the node to be deleted
Link<E> *tmp = curr->next;
E it = tmp->element;
curr->next = tmp->next;
delete tmp;
cnt--;
return it; 29
}
Prev
/** Move curr one step left;
no change if already at front */
public void prev() {
if (curr == head) return;
Link<E> *tmp = head;
// March down list until we find the
// previous element
while (tmp->next != curr)
tmp = tmp->next;
curr = tmp;
}

30
Get/Set Position
/** Return position of the current element */
public int currPos() {
Link<E> *tmp = head;
int i;
for (i=0; tmp != curr; i++)
tmp = tmp->next;
return i;
}
/** Move down list to "pos" position */
public void moveToPos(int pos) {
// if position is out of range;
assert( pos>=0 && pos<cnt);
curr = head;
for(int i=0; i<pos; i++)
curr = curr->next; 31
}
Comparison of Implementations
Array-Based Lists:
 Insertion and deletion are (n).
 Prev and direct access are (1).
 Array must be allocated in advance.
 No overhead if all array positions are full.

Linked Lists:
 Insertion and deletion are (1).
 Prev and direct access are (n).
 Space grows with number of elements.
 Every element requires overhead.
32
Space Comparison
“Break-even” point:

DE = n(P + E);

n = DE
P+E

E: Space for data value.


P: Space for pointer.
n: number of elements in the list
D: Number of elements in array with D>= n 33
Freelist
System new and delete are slow.
Consider there are many interwoven insert
and remove operations
list.insert(10), list.remove(); list.remove();…,
list.insert(20),…

Solution
keep the nodes removed in a free list by
yourself, and do not call the system delete
Allocate a new node from the free list first if
there are some; otherwise, call the system new
Delete all nodes in the free list when we do not
need them
See the textbook for details
34
Doubly Linked Lists
 Two pointers in each node
point to both next and previous nodes

 add a head node and a tail node for


the convenience of coding
 curr: point to the last node in the
left partition by the fence
 The initial state

35
Doubly linked list node
Template <typename E> class DLink{
public:
E element;
DLink* next;
DLink* prev;
//constructors
DLink(const E& it, DLink* p, DLink* n){
element = it;
prev = p; next = n;
}
//constructor
DLink(DLink* p=NULL, DLink* n=NULL){
prev = p;
next = n;
}
};
36
Doubly Linked Insert

37
Doubly Linked Insert
public void insert(E it) {
DLink<E> *tmp = new DLink<E>(it, curr,
curr->next );

curr->next = tmp;

DLink<E> *pNext = tmp->next;


pNext->prev= tmp;

cnt++;
}

38
Doubly Linked Remove

39
Doubly Linked Remove
public E remove() {
if (curr->next == tail) return NULL;

DLink<E> *tmp = curr->next;


E it = tmp->element;

curr->next = tmp->next;
(tmp->next)->prev = curr;

cnt--;
delete tmp;
return it;
}

40
An application of lists -- merge sort

41
Merge Sort

1. If there is only one number in the list, return;


2. Split a list into two sub-lists with almost
equal length
3. Recursively sort the two sub-lists, where
the numbers in each sub-lists are in
increasing order
4. Merge the two sub-lists into one list such
that the number the merged list are in
increasing order 42
How to merge two sorted sub-lists ?

43
Stacks and Queues

Stack
Array-based stack and linked stack
Some applications of stacks
Queue
Array-based queue and linked queue
An application of queues

44
Stacks
LIFO: Last In, First Out

45
Stacks
Notation:
Insert: PUSH
Remove: POP
The accessible element is called TOP.

Restricted form of list: Insert and remove


only at front of list.

46
Stack ADT
// Stack abtract class
template <typename E> class Stack {
public:
void clear();

/** Push an element onto the top of the stack.


@param it Element being pushed onto the stack.*/
public void push(E it);

/** Remove and return top element.


@return The element at the top of the stack.*/
public E pop();

/** @return A copy of the top element. */


public E topValue();

/** @return Number of elements in the stack. */


public int length(); 47

};
Array-Based Stack
// Array-based stack implementation
private:
E *listArray; // Array holding elements
int size; // Maximum size of stack

int top; // Index for top element

Issues:
Which end is the top ?
Array[0] is the bottom and array[top-1] is the top
Where does “top” point to?
The array index for store the next pushed element
What is the cost of the operations?
(1) for each of the three operations 48
Linked Stack
// Linked stack implementation
private:
Link<E>* top; // Pointer to first elem
int size; // Count number of elems
Two operations
Push an element by inserting it at
the beginning of the list
Pop out an element by removing the
first element from the list
What is the cost of the operations?
 (1)
How do space requirements compare to
the array-based stack implementation?
A fixed size array must be declared in the array
stack 49

Overhead for the `next’ field in the linked list


Applications of stacks

1. Determine whether the parentheses in a


string are balanced and properly nested
2. Subroutine calls
3. Depth first search on graphs

50
Application 1 Parentheses test

String `(2+5) * (4+7)’ are balanced and


properly nested
String ` 2+5) * (4+7)’ are not balanced
String `)2+(5* 4)+7(’ are balanced but not
properly nested

51
Algorithm for the parentheses test
Input: Given a string str[] with length n
stack<char> stk;
for ( i=0; i < n; ++i ){
if( str[i] is not a parenthesis) continue;
if str[i] == ‘(‘
push str[i] into stack stk
else{ // str[i] is ‘)’
if the top char on the stack is ‘(‘
pop out the top char
else return not matched
}
}
the string is properly nested iff the stack is52

empty in the end


Application 2 Subroutine calls
Consider the following what funcA will do
functions before it really
void funcA(int a[ ],int n){ calls funcB?
int i = 0; Place parameters,
while( i < n ) { e.g., a[i]
funcB( a[i] );
save return
++i; address, e.g. the
} address for `++i;’
}
Saving the values
void funcB(int number ){ of local variables,
… e.g. i and n 53

}
Subroutine calls-cont.
Subroutine calls are implemented by stacks
Each element in the stack is called as an
activation record, including return address,
parameters, and local variables
Push an element on the stack when calling a
subroutine
Pop out an element when the subroutine
finishes
See the textbook for the example of the
execution of the recursive function 54
Queues
FIFO: First in, First Out
The first arrived person will board on the
bus first

55
Queues

Notation:
Enqueue
Dequeue
First element: Front
Last element: Rear

Restricted form of list: Insert at one end,


remove from the other.

56
Array-based Queue

57
Array-based Queue

The queue `drift’ towards to the end of the


array
Cannot enqueue when rear = (maxSize-1),
even if there are some space left

58
Solution: Circular Queue
 The next index of index (maxSize-1) is 0, which is
(maxSize-1+1)%maxSize, where % is the modulus
operator

59
Circular Queue-cont.

Enqueue
rear = (real+1)%maxSize;
Place the new element at the array with index rear
Dequeue
Serve the first element in the queue, i.e., array[front]
front=(front+1)%maxSize;
Initially
front = 0, rear = maxSize-1;

60
rear
6 7 6 7 front 6 7 front
front
5 0 5 A 0 5 A0
rear
4 1 4 1 4
B 1
C
3 2 3 2 3 2
rear
Empty queue A enqueue B, C enqueue
empty queue:(rear +1)%maxSize = front
6 7 6 7 6 7
5 A 0 5 0 5 0

4 B1 4 B 1 4 1
C front C C
3 2 3 2 front 3 2
rear rear rear
Dequeue A Dequeue B Dequeue C
front 61
6 7 6 7
5 0 5 F G
E H0
4 1 4
D I 1
C C J
2
rear 3 front 3 2 rear
front
Enqueue D,E,F,G,H,I,J

Full queue:(rear+1)%maxSize = front

Cannot distinguish an empty queue and a full queue !


62
Solutions

Solution 1: count how many elements in


the queue
Empty queue if and only if the value of the
counter is 0
Full queue iff the value of the counter is equal
to the size of the array
Solution 2: allocate an array with one
more space for storing no more than n
elements, i.e., the size of the array is n+1
The textbook adopts this solution 63
Linked queue

The implementation is similar to the linked


list, omitted

64
An application of queues

Breadth first search on graphs, which will


be introduced later chapters

65
Conclusion
Array-based lists
Fast random access
Insertion and removal take long time
Linked lists
Slow for random access
Fast insertion and removal
Singled and doubly linked list
The notion of curr
Add head and/or tail nodes for convenient coding
Pay attention to special cases 66
Conclusion-cont.
Stacks
Two implementations, array-based and linked
stacks
Fast operation with time complexity (1)
Queues
Two implementations
Array-based circular queue
The implementation of queue with linked list is easy
Fast operation with time complexity (1)
Wide applications of stacks and queues 67

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy