0% found this document useful (0 votes)
15 views46 pages

Chap 3

The document outlines a course on Data Structures and Algorithms at Hanoi University of Science and Technology, covering fundamental concepts such as arrays, linked lists, stacks, queues, and their implementations in C. It details the memory allocation for one-dimensional and two-dimensional arrays, including row-major and column-major storage methods. Additionally, it discusses common operations on arrays, including searching, insertion, deletion, retrieval, and traversal.

Uploaded by

Lại An
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)
15 views46 pages

Chap 3

The document outlines a course on Data Structures and Algorithms at Hanoi University of Science and Technology, covering fundamental concepts such as arrays, linked lists, stacks, queues, and their implementations in C. It details the memory allocation for one-dimensional and two-dimensional arrays, including row-major and column-major storage methods. Additionally, it discusses common operations on arrays, including searching, insertion, deletion, retrieval, and traversal.

Uploaded by

Lại An
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/ 46

Hanoi University of Science and Technology

TRƯỜNG ĐẠI HỌCSchool


BÁCH of KHOA
Information and Communications Technology
HÀ NỘI Course outline
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
Chapter 1. Fundamentals
Chapter 2. Algorithmic paradigms
Chapter 3. Basic data structures
Data structures and Algorithms Chapter 4. Tree
Chapter 5. Sorting
Nguyễn Khánh Phương

Computer Science department


Chapter 6. Searching
School of Information and Communication Technology
E-mail: [email protected] Chapter 7. Graph
2

Hanoi University of Science and Technology


TRƯỜNG ĐẠI HỌCSchool
BÁCH of KHOA
Information and Communications Technology
HÀ NỘI What is list ?
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
• Data structures store objects in a linear structure
• Specify the first object of the list
• Each object: has a unique successor

Chapter 3. Basic data structures


. . .

Nguyễn Khánh Phương

Computer Science department


School of Information and Communication Technology
E-mail: [email protected]

NGUYỄN KHÁNH PHƯƠNG 4


CS - SOICT-HUST
Contents Contents
1. Array 1. Array
2. Linked List 2. Linked List
3. Stack 3. Stack
4. Queue 4. Queue

5 6

1. Array 1. Array
• Access elements via indices • Access elements via indices
• Elements are allocated continuously in memory • Elements are allocated continuously in memory
• Insertions and removals need to consolidate elements • Insertions and removals need to consolidate elements

NGUYỄN KHÁNH PHƯƠNG 7 NGUYỄN KHÁNH PHƯƠNG 8


CS - SOICT-HUST CS - SOICT-HUST
1D Array Representation in C Example
Write a C program that gives the address of each element of an 1D array:
#include <stdio.h>
Memory int main()
Result in DevC
{ int A[ ] = {5, 10, 12, 15, 4};
(sizeof(int)=4)
a b c d int rows=5;
/* print the address of 1D array by using pointer */
printf("Address Contents\n");
for (int i=0; i < rows; i++)
start_address printf("%8u %5d\n", &A[i], A[i]);
}
Example: 1-dimensional array x = [a, b, c, d]
• Allocated at contiguous memory locations ptr+i : address of element A[i]
• Location(x[i]) = start_address + W*i *(ptr+i) : content of element A[i] Result in turboC
where (sizeof(int)=2)
– start_address: the address of the first element in the array Memory Location(A[i]) = start_address + W*i
Address Contents
– W: size of each element in the array 5 10 12 15 4 65516 5
65518 10
65520 12
65522 15
NGUYỄN KHÁNH PHƯƠNG 65524 4
CS - SOICT-HUST
start_address=6487536

Two-dimensional array Rows of a 2D Array


• How to declare:
<element-type> <arrayName> [size1][size2];
Example: double a[3][4];
may be shown as a table
a[0][0] a[0][1] a[0][2] a[0][3] row 0
a[1][0] a[1][1] a[1][2] a[1][3] row 1
a[2][0] a[2][1] a[2][2] a[2][3] row 2

• Using the two-dimensional array initializer


Example: int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
• Access to element of array: a[2] [1]; a[0][0] = 1 a[0][1]=2 a[0][2]=3 a[0][3]=4

a[1][0] = 5 a[1][1]=6 a[1][2]=7 a[1][3]=8

a[2][0] = 9 a[2][1]=10 a[2][2]=11 a[2][3]=12 NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST
Columns of a 2D Array Multidimensional Arrays
• Multidimensional arrays are usually implemented by one
dimensional array via either row major order or column
major order. [0] [1] [2] [3]
a[0][0] a[0][1] a[0][2] a[0][3] [0] 1 2 3 4
a[1][0] a[1][1] a[1][2] a[1][3] [1] 5 6 7 8
User’s view
a[2][0] a[2][1] a[2][2] a[2][3]
1 2 3 4 5 6 7 8
Row-major storage
column 0 column 1 column 2 column 3 Row 0 Row 1

1 5 2 6 3 7 4 8 Column-major
NGUYỄN KHÁNH PHƯƠNG Column 0 Column 1 Column 2 Column 3 storage
CS - SOICT-HUST

Row-Major Order (e.g. C/C++, Python by default, Pascal) Column-Major Order (e.g. Matlab, Fortran)
 Row- major order is a method of representing multi-dimensional array in sequential memory. In  In this method, elements of an array are arranged sequentially column by
this method, elements of an array are arranged sequentially row by row. Thus, elements of the first
row occupies the first set of memory locations reserved for the array, elements of the second row
column. Thus, elements of the first column occupies the first set of memory
occupies the next set of memory and so on. locations reserved for the array, elements of the second column occupies the
Elements of Elements of Elements of
….
Elements of
……..
next set of memory and so on.
Row 0 Row 1 Row 2 Row i

Elements of Elements of Elements of Elements of


 Example: int a[4][3] column 0 column 1 column 2
….
column i
……..

in ascending direction of memory address


 Example 3 x 4 array:
a[0][0] a[0][1] a[0][2] abcd
row 1 row 3
efgh
row 0 row 2
 Example 3 x 4 array: a b c d i jkl
efgh
i jkl a e i b f j c g k d h l

a b c d e f g h i j b c Column 0 Column 1 Column 2 Column 3

row 0 row 1 row 2


Locating Element x[i][j]: row-major order Example
 Assume x: Write a C program that gives the address of each element of a 2D array:
 has r rows and c columns (thus, each row has c elements) Result in DevC
#include <stdio.h>
(sizeof(int)=4)
c elements of c elements of c elements of c Elements of int main()
…. ……..
Row 0 Row 1 Row 2 Row r-1 { int a[3] [4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int rows=3, cols =4;
 Locating element x[i][j]: /* print the address of 2D array by using pointer */
int *ptr = a;
 i rows to the left of row i  so i*c elements to the left of x[i][0] printf("Address Contents\n");
 x[i][j] is mapped to position: i*c + j of the 1D array for (int i=0; i < rows; i++)
for (int j=0; j < cols; j++)
 The location of element x[i][j]: printf("%8u %5d\n", &a[i][j], a[i][j]);
Location(x[i][j]) =start_address + W (i*c + j) }

Where
• start_address: the address of the first element (x[0][0]) in the array Memory Location(a[i][j]) = start_address + W*[(i*cols) + j]
• W: is the size of each element 1 2 3 4 5 6 7 8 9 10 11 12
• c: number of columns in the array
• r: number of rows in the array NGUYỄN KHÁNH PHƯƠNG Location(a[1][2]) = ?
CS - SOICT-HUST start_address=6487488

Locating Element x[i][j]: column-major order Example 1: Row- and Column-Major Orders
 Assume x: …..
r Elements r Elements r Elements
…. …….
r Elements 2D array: a[0][0] = 1 a[0][1]=2 a[0][2]=3 a[0][3]=4
of column 0 of column 1 of column 2 of columns i

 has r rows and c columns (thus, each column has r elements) int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; a[1][0] = 5 a[1][1]=6 a[1][2]=7 a[1][3]=8

 Locating element x[i][j]: a[2][0] = 9 a[2][1]=10 a[2][2]=11 a[2][3]=12


 j columns to the left of column j  so j*r elements to the left of x[0][j]
 x[i][j] is mapped to position: j*r + i of the 1D array Memory: row-major order
Location(a[i][j]) = start_address + W*[(i*cols) + j]
 The location of element x[i][j]:
Location(x[i][j]) = start_address + W (j*r + i) 1 2 3 4 5 6 7 8 9 10 11 12

Where
start_address=6487488 Location(a[1][2]) = ?
• start_address: the address of the first element in the array
• W: is the size of each element Memory: column-major order
• c: number of columns in the array Location(a[i][j]) = start_address + W*[(j*rows) + i]
• r: number of rows in the array
1 5 9 2 6 10 3 7 11 4 8 12
Example: array : int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
Location(a[1][2]) = ?
Determine the address of the element a[1][2] if start_address = 6487488 start_address=6487488
Example 2: Row- and Column-Major Orders Example
2D array: r rows, c columns We have stored the two-dimensional array students in memory. The array
Example: int a[3][6]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
is 100 × 4 (100 rows and 4 columns). Show the address of the element
a[0][0]=0 a[0][1]=1 a[0][2]=2 a[0][3]=3 a[0][4]=4 a[0][5]=5
a[1][0]=6 a[1][1]=7 a[1][2]=8 a[1][3]=9 a[1][4]=10 a[1][5]=11
students[5][3] assuming that the element student[0][0] is stored in the
a[2][0]=12 a[2][1]=13 a[2][2]=14 a[2][3]=15 a[2][4]=16 a[2][5]=17 memory location with address 1000 and each element occupies only two
bytes memory location. The computer uses row-major storage.
Memory: row-major order start_address = 1000  Location(a[1][4]) = ? Solution:
c elements of c elements of c elements of c Elements of
…. ……..
Row 0 Row 1 Row 2 Row r

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

6 elements of row 0 6 elements of row 1 6 elements of row 2

Memory: column-major order


r Elements of r Elements of r Elements of r Elements of
…. ……..
column 0 column 1 column 2 column i

0 6 2 1 7 13 2 8 14 3 9 15 4 10 16 5 11 17

3 elements of col 0 3 elements of col 5

1. Array Operations on the array


• Access elements via indices • The common operations on arrays are searching, insertion, deletion,
• Elements are allocated continuously in memory retrieval and traversal.
• Insertions and removals need to consolidate elements Example: Given an array S consists of n integers: S[0], S[1], …, S[n-1]
– Search operation: search a value key whether appears in the array S or not
function Search(S, key) returns true if key appears in S; false otherwise
– Retrieval operation: get the value of the element at index i of the array S
function Retrieve(S, i): returns the value S[i] if 0 <= i <= n-1
– Traversal operation: print the value of all elements in the array S
function PrintArray(S, n)
– Insert operation: insert a value key into the array S
– Delete operation: delete the element at index i of the array S
• Although searching, retrieval and traversal of an array is an easy job,
insertion and deletion is time consuming. The elements need to be
shifted down before insertion and shifted up after deletion.
23 NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST
Inserting an element into an array Deleting an element from an array
• Assume we need to insert 8 into an array already be sorted in ascending order: • In order to delete an element, we need to shift to the left all previous elements

1 3 3 7 8 12 14 17 19 22

1 3 3 7 12 14 17 19 22 30
1 3 3 7 12 14 17 19 22 ?
• We can do it by shifting to the right one cell for all the elements after the mark
– It thus need to remove 30 from the array • Delete operation is a slow operation.
• Regular implementation of this operation is undesirable.
• Delete operation makes the last element free
1 3 3 7 8 12 14 17 19 22
– How we could mark the last element of the array being free?
• Moving all elements of the array is a slow operation (requires linear time O(n) • We need variable to store the size of the array
where n is the size of array) Example: variable size is used to store the size of the array. Before
deletion, size = 10. After deletion, we need to update the value of size:
size = 10 – 1 = 9
NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST CS - SOICT-HUST

Operations on the array Contents


Thinking about the operations discussed in the previous 1. Array
section gives a clue to the application of arrays. If we have a
list in which a lot of insertions and deletions are expected 2. Linked List
after the original list has been created, we should not use an
array. An array is more suitable when the number of 3. Stack
deletions and insertions is small, but a lot of searching and
retrieval activities are expected. 4. Queue
i
An array is a suitable structure when a small number of
insertions and deletions are required, but a lot of
searching and retrieval is needed.
NGUYỄN KHÁNH PHƯƠNG 28
CS - SOICT-HUST
2. Linked list Singly Linked list
• Singly linked list • A singly linked list is a sequences of nodes, each node contains 2 parts: data and
reference (address) to the next node.
10 8 20 • Example: Figure shows a singly linked list contains four nodes:

head

• Doubly linked list

10 8 20
head
• Keeping track of a singly linked list:
• Circular linked list – Must know the pointer to the first element of the list (called start, head, etc.)
– If head is NULL, the singly linked list is empty
head

10 8 20 10 8 20
head
NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST

Singly Linked list Declare singly linked list in C programming language

..
• Before further discussion of singly linked lists, we need to explain the notation we • List of integer numbers:
use in the figures. We show the connection between two nodes using a line. One end
of the line has an arrowhead, the other end has a solid circle. 7 17 4 24
• List of students with data: student’s ID, grade of math and physics

2001 8.5 6.5 2002 7 4.5 … 4001 6.5 9

• List of contacts with data: name, phone number

Crainic 0903210433 Michel 0941341043 … Gendreau 0894312098

Figure. The concept of copying and storing pointers


Memory address  Need to declare:
– the type of data in the node first,
head 3000 5000 2000 – then the singly linked list consists of (1) data of the node, and (2) the pointer to
store the address of the next node in the list
3000 10 5000 8 2000 50 NULL NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST
Declare singly linked list Declare singly linked list
typedef struct { typedef struct {
..... Define the type of data of the node ..... Define the type of data of the node
}NodeType; }NodeType;

typedef struct { typedef struct {


NodeType data; NodeType data;
struct node* next;
Define the singly linked list struct node* next;
Define the singly linked list
}node; }node;
node* head; node* head;
This declaration define node which is a record consisting of 2 fields: This declaration define node which is a record consisting of 2 fields:
• data : stores data of node, has the type NodeType (which was defined in typedef…NodeType, • data : stores data of node, has the type NodeType (which was defined in typedef…NodeType,
and could consist of several attributes) and could consist of several attributes)
• next : the pointer which stores the address of the next node in the list • next : the pointer which stores the address of the next node in the list
Pointer head : store address of the first node in the list Pointer head : store address of the first node in the list
Example1: List of students with data: id of student, marks of 2 subjects: math, physics Example2: List of integer numbers
typedef struct{ 7 17 4 24
char id[15]; Define the type of data of the node typedef struct {
float math, physics; int data;
}student; “int” is the type of node, so do not need to use
data struct node* next; “typedef….NodeType” to define the type
}node;
typedef struct { node* head;
student data; next
struct node* next; id math physics data
}node;
node* head; A node A node

Declare singly linked list Important elements of singly linked list


typedef struct { • head: store the address of the first node in the linked list
..... Define the type of data of the node
}NodeType;
• NULL: value of the pointer of the last node in the linked list
• cur: the pointer stored the address of current node
typedef struct {
NodeType data;
Define the singly linked list cur
struct node* next; head (or root)
}node;
node* head;
This declaration define node which is a record consisting of 2 fields:
• data : stores data of node, has the type NodeType (which was defined in typedef…NodeType,
and could consist of several attributes) NULL
• next : the pointer which stores the address of the next node in the list • Allocate memory for a new node pointed by the pointer newNode in the list:
Pointer head : store address of the first node in the list
Example 3: List of contacts with data: name and phone number node *newNode = (node *) malloc(sizeof(node));
typedef struct{ • Access to the data of the node pointed by pointer newNode :
char name[15];
char phone[20]; Define the type of data of the node
newNode->data (*newNode).data
}contact; data
• Free memory allocated for node pointed by pointer newNode :
typedef struct {
contact data; next free(newNode); newNode
struct node* next; name phonenumber
}node; 36
node* head; A node
Operations on singly linked Lists Assumption
• Traverse the singly linked list typedef struct {
• Insert a node into the singly linked list int data;
• Delete a node from the singly linked list struct Node* next; // pointer to the successor
• Search data in the singly linked list } Node;
Node* head; // pointer to the first element of the list

head

5 9 3 ... 6 4

NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG 38


CS - SOICT-HUST CS - SOICT-HUST

Create a new node Operations on singly linked Lists


• Traverse the singly linked list
• Insert a node into the singly linked list
#include <stdio.h>
typedef struct Node{
• Delete a node from the singly linked list
int data; • Search data in the singly linked list
struct Node* next; // pointer to the successor
}Node;

Node *makeNode(int v) //allocate memory for a new node


{
Node* p = (Node*)malloc(sizeof(Node));
//Node *p = new Node;
p->data = v; p->next = NULL;
return p;
}

39
NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST CS - SOICT-HUST
Traversing a singly linked list: 2nd way Exercise 1
void printList(Node* head) • A sequence of integers is stored by a singly linked list.
{
typedef struct Node{
Node* cur = head;
int data;
for (cur = head; cur != NULL; cur = cur->next) printf(“%d “,cur->data);
struct Node *next;
}
}Node;
Node *head;

void printList(Node* head)


{ a. Create a list stored 3 integers: 1, 2, 3
Node* cur = head; b. Print the list of these 3 integers
while(cur != NULL){
printf(“%d “,cur->data);
cur = cur->next;
}
head
}

1 2 3
NULL
NGUYỄN KHÁNH PHƯƠNG 41 NGUYỄN KHÁNH PHƯƠNG 42
CS - SOICT-HUST CS - SOICT-HUST

Operations on singly linked lists


• Traverse the singly linked list
• Insert a node into the singly linked list
head
• Delete a node from the singly linked list
second third
• Search data in the singly linked list

1 2 3
NULL
cur

Data = 1
Data = 2
Data = 3

NGUYỄN KHÁNH PHƯƠNG 43 NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST CS - SOICT-HUST
Operations on singly linked list: Insertion Operations on singly linked list: Insertion
Insert a new node : Insert a new node:
• At the beginning of the list • At the beginning of the list
<create a new node new_node>;
• After the position pointed by the pointer cur new_node ->next = head;
head= new_node;
• Before the position pointed by the pointer cur
• At the end of the list head


cur
//return the pointer pointed to the first node in the list:
head Node *Insert_ToHead(Node *head, int X)
{
… Node *new_node = makenode(X);
new_node new_node->next = head;
head = new_node;
return head;
}
NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG 46
CS - SOICT-HUST CS - SOICT-HUST

Operations on singly linked list: Insertion Exercise


//return the pointer pointed to the first node in the list: Ask the user to enter an integer n, then enter n integers numbers from the
Node *Insert_ToHead(Node *head, int X) keyboard. Each time an integer is read, insert it at the beginning of a linked list.
Finally, prints on the screen all values stored in that linked list.
{ struct Node {
typedef struct Node{
Node *new_node = makenode(X); int data;
int data;
struct Node *next;
new_node->next = head; struct Node *next;
};
}Node;
head = new_node; struct Node *head;
Node *head;
return head;
void Insert_ToHead(Node** head_ref, int new_data);
}
node *Insert_ToHead(Node *head, int new_data); /*return
the pointer pointed to the first node in the list*/

void Insert_ToHead(Node **head_ref, int X)


{
Node *new_node = makenode(X);
new_node->next = *head;
*head = new_node;
} NGUYỄN KHÁNH PHƯƠNG47 48
CS - SOICT-HUST
Operations on singly linked list: Insertion Operations on singly linked list: Insertion
Insert a new node : • Insert a new node after the node pointed by the pointer cur:
• At the beginning of the list <create a new node new_node>;
new_node ->next = cur->next;
• After the position pointed by the pointer cur cur->next = new_node;
• Before the position pointed by the pointer cur
• At the end of the list

cur
head
cur
head …

NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST new_node NGUYỄN KHÁNH PHƯƠNG 50
CS - SOICT-HUST

Operations on singly linked list: Insertion Operations on singly linked list: Insertion
• Insert a new node after the node pointed by the pointer cur: • Insert a new node after the node pointed by the pointer cur:
<create a new node new_node>; <create a new node new_node>; ?? Empty list
new_node ->next = cur->next; new_node ->next = cur->next;
cur->next = new_node; cur->next = new_node;
// wrong implementation:
Write a function to insert a node with data = X (having the type int after the cur->next = new_node;
node pointed by the pointer cur. The function returns the address of the new node: new_node ->next = cur->next;
cur
Node *Insert_After(Node *cur, int X) head
{
Node *new_node = makenode(X); //(1) …
new_node->next = cur->next; //(2)
cur->next = new_node; //(3)
return new_node;
}

NGUYỄN KHÁNH PHƯƠNG 51


CS - SOICT-HUST new_node NGUYỄN KHÁNH PHƯƠNG 52
CS - SOICT-HUST
Operations on singly linked list: Insertion Operations on singly linked list: Insertion
• Insert a new node after the node pointed by the pointer cur: Insert a new node :
<create a new node new_node>;
?? Empty list • At the beginning of the list
new_node ->next = cur->next;
cur->next = new_node; • After the position pointed by the pointer cur
• Before the position pointed by the pointer cur
<create a new node new_node>; • At the end of the list
if (head == NULL) { /* list does not have any node yet */
head = new_node;
}
else {
new_node ->next = cur->next; Node *Insert_After(Node *cur, int
cur->next = new_node;
X)
cur
{
}
Node *new_node = makenode(X); //(1) head
if (head == NULL) head = new_node;
else { …
new_node->next = cur->next; //(2)
cur->next = new_node; //(3)
}
return new_node;
} 53 NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST

Operations on singly linked list: Insertion Operations on singly linked list: Insertion
Insert a new node before the node pointed by the pointer cur Insert a new node before the node pointed by the pointer cur
<create a new node new_node>; ?? List does not have any node yet <create a new node new_node>; ?? List does not have any node yet
<Determine pointer prev pointed <Determine pointer prev pointed
to the predecessor of cur>; to the predecessor of cur>;
prev->next = new_node; ?? cur is the first node in the list prev->next = new_node; ?? cur is the first node in the list
new_node->next = cur; new_node->next = cur;

<create a new node new_node>;


if (head == NULL) { /* list does not have any node yet */
prev cur head = new_node;
head }
else if (cur == head) { //cur is the first node in the list
head = new_node;
… }
new_node->next = cur;
else {
<Determine pointer prev pointed to the predecessor of cur>;
prev->next = new_node;
new_node->next = cur;
}

Insert a new node: NGUYỄN KHÁNH PHƯƠNG 55 Node *Insert_Before(Node *head, Node *cur, int X) 56
CS - SOICT-HUST
Operations on singly linked list: Insertion Operations on singly linked list: Insertion
Insert a new node before the node pointed by the pointer cur Insert a new node before the node pointed by the pointer cur
<create a new node new_node>; Node *Insert_Before(Node *head, Node *cur, int X)
<Determine pointer prev pointed to the predecessor of cur>;
prev->next = new_node; {
new_node->next = cur; Node *new_node = makenode(X);
if (head == NULL) /* list does not have any node yet */
head = new_node;
node *prev = head; else if (cur == head) { //cur is the first node in the list
while (prev->next != cur) prev = prev->next; head = new_node;
new_node->next = cur;
prev cur }
head else {
Node *prev = head;
… while (prev->next != cur) prev = prev->next;
prev->next = new_node;
new_node->next = cur;
}
return new_node;
Node *Insert_Before(Node *head, Node *cur, int X)
} NGUYỄN KHÁNH PHƯƠNG
57 KHMT – SOICT - ĐHBK HN

Operations on singly linked list: Insertion Operations on singly linked list: Insertion
Insert a new node: head Node *Insert_ToLast(Node *head, int X)

• At the beginning {

• After the node pointed by cur


• Before the node pointed by cur
… Node *new_node = makenode(X);

if (head == NULL) head = new_node;

else {
• At the end of the list
<create a new node new_node>; Node *last = head;
if (head == NULL) { /* list does not have any node yet*/ while (last->next != NULL) last = last->next; //move to the last node
head = new_node;
} last->next = new_node;
else {
//move the pointer to the end of the list: }
node *last =head; return head;
while (last->next != NULL) last = last->next;
//Change the pointer next of the last node: }
last->next = new_node;
} Node *Insert_ToLast(Node *head, int X) void Insert_ToLast(Node **head_ref, int X)

{ {

Node *new_node = makenode(X); Node *new_node = makenode(X);

if (head == NULL) head = new_node; if (*head == NULL) *head = new_node;

else { else {

Node *last = head; Node *last = *head;


Complexity is …. while (last->next != NULL) last = last->next; //move to the last node while (last->next != NULL) last = last->next; //move to the last node

last->next = new_node; last->next = new_node;

} }

return head; }
59 NGUYỄN KHÁNH PHƯƠNG
} KHMT – SOICT - ĐHBK HN
Operations on singly linked Lists Operations on singly linked lists: Deletion
• Traverse the singly linked list • Delete a node
• Insert a node into the singly linked list • Delete all nodes of the list
• Delete a node from the singly linked list
• Search data in the singly linked list

NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST CS - SOICT-HUST

Operations on singly linked lists: Deletion Delete the first node of the list
Delete a node: • Delete the node del that is currently the first node of the list:
• The first node of the list head = del->next;
free(del);
head
≡del
del

• Middle/last node of the list


del head NULL
head

63 NGUYỄN KHÁNH PHƯƠNG 64


CS - SOICT-HUST
Delete the node at the middle/end of the list Delete the node at the middle/end of the list
Delete node del that is currently the middle/last node of the list: Delete node del that is currently the middle/last node of the list:
<Determine the pointer prev pointed to the previous node of del>;
prev->next = del->next; //modify the link <Determine the pointer prev pointed to the previous node of del>;
free(del); //delete node del to free memory prev->next = del->next; //modify the link
free(del); //delete node del to free memory)
prev del
head Node *prev =head;
while (prev->next != del) prev = prev->next;

prev del prev del


head
head
NULL

65 66

Delete a node pointed by the pointer del Operations on singly linked lists: Deletion
Write the function node *Delete_Node(node *head, node *del)
• Delete a node
to delete a node pointed by the pointer “del” of the list with the first node pointed by the pointer “head”.
The function returns the address of the first node in the list after deletion:
• Delete all nodes of the list

Node *Delete_Node(Node *head, Node *del)


{
if (head == del) //del is pointed to the first node of the list:
{
head = del->next;
free(del);
}
else{//del is pointed to the middle/last node of the list
Node *prev = head;
while (prev->next != NULL) prev = prev->next;
prev->next =del->next;
free(del);
}
return head;
NGUYỄN KHÁNH PHƯƠNG 67 NGUYỄN KHÁNH PHƯƠNG
} CS - SOICT-HUST CS - SOICT-HUST
Freeing all nodes of a list Freeing all nodes of a list

del = head ; del = head ;


while (del != NULL) while (del != NULL)
{ {
head = head->next; head = head->next;
free(del); free(del);
del = head; del = head;
} }

Traverse elements one by one from the head till the end
head head

1 2 3 2 3

del del
NGUYỄN KHÁNH PHƯƠNG 69 NGUYỄN KHÁNH PHƯƠNG 70
CS - SOICT-HUST CS - SOICT-HUST

Freeing all nodes of a list Freeing all nodes of a list

del = head ; del = head ;


while (del != NULL) while (del != NULL)
{ {
head = head->next; head = head->next;
free(del); free(del);
del = head; del = head;
} }

head head

2 3 3 NULL

del del
NGUYỄN KHÁNH PHƯƠNG 71 NGUYỄN KHÁNH PHƯƠNG 72
CS - SOICT-HUST CS - SOICT-HUST
Freeing all nodes of a list Check whether the singly linked list is empty or not
Write the function Node* deleteList(Node* head) Write the function int IsEmpty(Node *head)
to delete all the node in the list having the first node pointed by the pointer head to check whether the singly linked list is empty or not (the pointer head pointed to the
The function returns the pointer head after deletion first node of the list).
Node* deleteList(Node* head) The function returns 1 if the list is empty; 0 otherwise
{
Node *del = head ; int IsEmpty(Node *head) {
if (head == NULL)
while (del != NULL) return 1;
{ else return 0;
head = head->next; }
free(del);
del = head;
}
return head;
}

NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST CS - SOICT-HUST

Operations on singly linked Lists Searching


• Traverse the singly linked list • To search for an element, we traverse from head until we locate the object or we reach the end
of the list.
• Insert a node into the singly linked list
Example: Given a linked list consisting of integer numbers. Count the number of nodes with data
• Delete a node from the singly linked list field equal to number x.
• Search data in the singly linked list int countNodes(int x){
typedef struct { int count = 0;
int data; Node* e = head;
struct node* next; while(e != NULL){
}Node; if(e->data == x) count++;
Node* head; e = e->next;
}
return count;
}

int Result1 = countNodes(24);


Result1 = ?
int a =7; Result2 = ?
int Result2 = countNodes(a); NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST
Time Complexity: Singly-linked lists vs. 1D-arrays Singly-linked lists vs. 1D-arrays

Operation ID-Array Complexity Singly-linked list Complexity


ID-array Singly-linked list
Insert at beginning O(n) O(1)
Insert at end O(1) O(1) if the list has tail reference Fixed size: Resizing is expensive Dynamic size
O(n) if the list has no tail reference
Insertions and Deletions are inefficient: Insertions and Deletions are efficient: No
Insert at middle* O(n) O(n) Elements are usually shifted shifting
Delete at beginning O(n) O(1)
Random access i.e., efficient indexing No random access
Delete at end O(1) O(n)
 Not suitable for operations requiring
Delete at middle* O(n): O(n): accessing elements by index such as sorting
O(1) access followed by O(n) O(n) search, followed by O(1) delete
shift
No memory waste if the array is full or almost Extra storage needed for references; however
Search O(n) linear search O(n) full; otherwise may result in much memory uses exactly as much memory as it needs
O(log n) Binary search waste.
Indexing: What is O(1) O(n)
the element at a Sequential access is faster because of greater Sequential access is slow because of low locality
given position k? locality of references [Reason: Elements in of references [Reason: Elements not in
contiguous memory locations] contiguous memory locations]

* middle: neither at the beginning nor at the end

2.3. Linked list Doubly linked list


• Singly linked list • A Doubly Linked List (DLL) contains an extra pointer, typically called previous
pointer, together with next pointer and data which are there in singly linked list

10 8 20 tail
head

• Doubly linked list • 2 special nodes: tail and head


– head has pointer prev = null
10 8 20 – tail has pointer next = null
• Basic operations are considered similar as in the singly linked list
head
tail

NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST
Doubly linked list Doubly linked list
• Declare doubly linked list to store integer numbers: • Declare doubly linked list store data of students: ID, marks of math and physics

10 8 20 2001 8.5 6.5 2002 8 5


… 4002 5.5 9.5

head tail head tail

typedef struct{
typdedef struct dllist { char id[15];
int number; float math, physics;
}student;
struct dllist *next;
typedef struct dllist{
struct dllist *prev; student data;
} dllist; struct ddlist* next;
struct ddlist* prev;
dllist *head, *tail; }dllist;
dllist *head, *tail;
NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST CS - SOICT-HUST

Doubly linked list – Example (C proramming) Doubly linked list – Example (C proramming)
typedef struct dllist { typedef struct dllist {
char data; char data;
struct dllist *prev; struct dllist *prev;
struct dllist *next; struct dllist *next;
}dllist; }dllist;
dllist *node1, *node2, *node3; dllist *node1, *node2, *node3;
node1 = (dllist*)malloc(sizeof(dllist)); node1 = (dllist*)malloc(sizeof(dllist));
node2 = (dllist*)malloc(sizeof(dllist)); node2 = (dllist*)malloc(sizeof(dllist));
node3 = (dllist*)malloc(sizeof(dllist)); node3 = (dllist*)malloc(sizeof(dllist));

node1->data='a'; node1->data='a';
node2->data='b'; node2->data='b';
node3->data='c’; node3->data='c’;
node1->prev=NULL; node1->prev=NULL; a b c
node1->next=node2; node1->next=node2;
node2->prev=node1; node1 node2
node2->prev=node1; node1 node2
node3 node3
node2->next=node3; node2->next=node3;
node3->prev=node2; node3->prev=node2;
node3->next=NULL; node3->next=NULL;
dllist *temp; dllist *temp;
for (temp = node1; temp != NULL; temp = temp->next) for (temp = node1; temp != NULL; temp = temp->next)
printf(“%d ”,temp->data); printf(“%d ”,temp->data);
83 84
Doubly linked list – Example (C proramming) Doubly linked list – Example (C proramming)
typedef struct dllist { typedef struct dllist {
char data; char data;
struct dllist *prev; struct dllist *prev;
struct dllist *next; struct dllist *next;
}dllist; }dllist;
dllist *node1, *node2, *node3; dllist *node1, *node2, *node3;
node1 = (dllist*)malloc(sizeof(dllist)); node1 = (dllist*)malloc(sizeof(dllist));
node2 = (dllist*)malloc(sizeof(dllist)); node2 = (dllist*)malloc(sizeof(dllist));
node3 = (dllist*)malloc(sizeof(dllist)); node3 = (dllist*)malloc(sizeof(dllist));

node1->data='a'; node1->data='a';
node2->data='b'; node2->data='b';
node3->data='c’; node3->data='c’;
node1->prev=NULL; NULL a b c node1->prev=NULL; NULL a b c
node1->next=node2; node1->next=node2;
node2->prev=node1; node1 node2
node2->prev=node1; node1 node2
node3 node3
node2->next=node3; node2->next=node3;
node3->prev=node2; node3->prev=node2;
node3->next=NULL; node3->next=NULL;
dllist *temp; dllist *temp;
for (temp = node1; temp != NULL; temp = temp->next) for (temp = node1; temp != NULL; temp = temp->next)
printf(“%d ”,temp->data); printf(“%d ”,temp->data);
85 86

Doubly linked list – Example (C proramming) Doubly linked list – Example (C++)
typedef struct dllist {
char data;
typedef struct dllist {
struct dllist *prev;
struct dllist *next;
char data;
}dllist; struct dllist *prev;
dllist *node1, *node2, *node3; struct dllist *next;
node1 = (dllist*)malloc(sizeof(dllist)); }dllist;
node2 = (dllist*)malloc(sizeof(dllist)); dllist node1, node2, node3;
node3 = (dllist*)malloc(sizeof(dllist));
node1.data=‘a’;
node1->data='a';
node2.data=‘b’;
node2->data='b';
node3->data='c’;
node3.data=‘c’; NULL a b c NULL

a c node1.prev=NULL;
node1->prev=NULL; NULL b NULL
node1->next=node2; node1.next=node2;
node2->prev=node1; node1 node2
node2.prev=node1;
node3
node2->next=node3; node2.next=node3;
node3->prev=node2; node3.prev=node2;
node3->next=NULL; node3.next=NULL;
dllist *temp;
dblist *temp;
for (temp = node1; temp != NULL; temp = temp->next)
printf(“%d ”,temp->data);
for (temp = node1; temp != NULL; temp = temp->next)
cout<<temp->data<<endl;
87 88
Delete a node pointed by the pointer p Delete a node pointed by the pointer p
void Delete_Node (dllist *p){ void Delete_Node (dllist *p){
if (head == NULL) printf(”Empty list”); if (head == NULL) printf(”Empty list”);
else { else {
if (p==head) head = head->next; //Delete first element if (p==head) head = head->next; //Delete first element
else p->prev->next = p->next; else p->prev->next = p->next;
if (p->next!=NULL) p->next->prev = p->prev; if (p->next!=NULL) p->next->prev = p->prev;
else tail = p->prev; else tail = p->prev;
free(p); free(p);
} }
} }

8 5 12 5 8 5 12 5

p p
head tail head tail
89 90

Delete a node pointed by the pointer p Insert a node after the node pointed by pointer p
void Delete_Node (dllist *p){ void Insert_Node (int X, dllist *p){
if (head == NULL){ // List is empty
if (head == NULL) printf(”Empty list”); head =(ddlist*)malloc(sizeof(ddlist));
else { head->data = X;
head->prev =NULL;
if (p==head) head = head->next; //Delete first element head->next =NULL;
else p->prev->next = p->next; }
else{
if (p->next!=NULL) p->next->prev = p->prev; dllist *newNode;
else tail = p->prev; newNode=(dllist*)malloc(sizeof(dllist));
newNode->data = X;
free(p); newNode->next = NULL;
}
newNode->next = p->next;
} newNode->prev=p;
if (p->next!=NULL) 12
8 5 12 5 p->next->prev=newNode;
p->next = newNode;
}
}

p 8 5 5
head tail 92
91
p
Exercise 2: Create a double linked list store integer numbers
#include <stdio.h> /* Insert a new node p at the end of the list */
#include <stdlib.h> void append_node(dllist *p) {
#include <conio.h> if(head == NULL)
{
typedef struct dllist{ head = p;
int number; p->prev = NULL;
struct dllist *next; }
struct dllist *prev; else {
} dllist; tail->next = p;
dllist *head, *tail; p->prev = tail;
}
/* Insert a new node p at the end of the list */ tail = p;
void append_node(dllist *p); p->next = NULL;
/* Insert a new node p after a node pointed by the pointer after */ }
void insert_node(dllist *p, dllist *after);
/* Delete a node pointed by the pointer p */
void delete_node(dllist *p);

93

/* Insert a new node p after a node pointed by the pointer after */ int main( ) {
void insert_node(dllist *p, dllist *after) { dllist *tempnode; int i;
p->next = after->next; /* add some numbers to the double linked list */
p->prev = after; for(i = 1; i <= 5; i++) {
if(after->next != NULL) tempnode = (dllist *)malloc(sizeof(dllist));
tempnode->number = i;
after->next->prev = p;
append_node(tempnode);
else
}
tail = p;
/* print the dll list forward */
after->next = p;
printf(" Traverse the dll list forward \n");
} for(tempnode = head; tempnode != NULL; tempnode = tempnode->next)
/* Delete a node pointed by the pointer p */ printf("%d\n", tempnode->number);
void delete_node(dllist *p) {
if(p->prev == NULL) /* print the dll list backward */
head = p->next; printf(" Traverse the dll list backward \n");
else p->prev->next = p->next; for(tempnode = tail; tempnode != NULL; tempnode = tempnode->prev)
if(p->next == NULL) printf("%d\n", tempnode->number);
tail = p->prev; /* destroy the dll list */
else p->next->prev = p->prev; while(head != NULL) delete_node(head);
} return 0;
}
Several variants of linked lists Circular linked list
• Some common variants of linked list: head
– Circular Linked Lists
– Circular Doubly Linked Lists
– Linked Lists of Lists 8 5 12 5
• Basic operations on these variants are built similarly to the singly linked list
and the doubly linked list that we consider above.

typedef struct node{


int data;
struct node * next;
}node;

Circular Doubly linked list Linked Lists of Lists


head head

8 5 12 5
Data1 Data2 Data3

typedef struct node{ DataA DataB DataC


int data;
struct node * next;
}node;
Linked list of lists Application – Sparse matrix Exercise: Polynomial Addition
To represent sparse matrix, we could we linked list of list which consisting two lists: Polynomials: defined by a list of coefficients and exponents
- degree of polynomial = the largest exponent in a polynomial
• one list is used to represent the rows and each row contains the list of triples: Column index,
𝑝 𝑥 = 𝑎 𝑥 + 𝑎 𝑥 + ⋯+ 𝑎 𝑥
Value(non – zero element) and address field, for non – zero elements. Example:
For the best performance both lists should be stored in order of ascending keys. Polynomials A(x) = 3x10+2x5+6x4+4
B(x) = x4+10x3+3x2+1
To represent a polynomial, the easiest way is to use array a[i] to store the coefficient of xi.
// Node to represent triples
Operations with polynomials such as: Add two polynomials, Multiply two polynomials, ..., are
typdedef struct value_list
{
thus possible to install simply.
int column_index;
Array a ~A(x) a[10] a[9] a[8] a[7] a[6] a[5] a[4] a[3] a[2] a[1] a[0]
int value;
struct value_list *next; 3 0 0 0 0 2 6 0 0 0 4
}value_list;
Array b ~B(x) b[4] b[3] b[2] b[1] b[0]
typedef struct row_list 1 10 3 0 1
{
int row_number; C(x) = A(x) + B(x) = 3x10+2x5+7x4+3x2+5
struct row_list *link_down;
struct value_list *link_right; c[10] c[9] c[8] c[7] c[6] c[5] c[4] c[3] c[2] c[1] c[0]
Array c
} row_list; ~C(x) =a[10] =a[9] =a[8] =a[7] =a[6] =a[5] =a[4]+b[4] =a[3]+b[3] =a[2]+b[2] =a[1]+b[1] =a[0]+b[0]
=3 =0 =0 =0 =0 =2 =6+1=7 =0+10=10 =0+3=3 =0+0=0 =4+1=5

Exercise: Polynomial Addition Exercise: Polynomial Addition


A(x)=2x1000 + x3 A(x)=2x1000 + x3
B(x)=x4 + 10x3 + 3x2 + 4
B(x)=x4+10x3+3x2+1
Use an array to keep track of the coefficients for all exponents: Use the linked list to keep track of the coefficients with values ≠ 0 and the exponent:

Poly1
… 2 … 0 1 0 0 0 A

… 0 … 1 10 3 0 1 B
2 1000 1 3 NULL

1000 … 4 3 2 1 0
1 4 10 3 3 2 4 0 NULL

A(x) + B(x) = advantage: easy implementation


disadvantage: waste space when sparse Poly2
In the case of sparse polynomial (with many coefficients equal to 0), we could typedef struct Polynom {
represent polynomial by the linked list: We will build a list containing only the int coef;
int exp;
coefficients with the value not equal to zero together with the exponent. struct Polynom *next;
However, it is more complicated to implement the operations. } Polynom;
Polynom *Poly1, *Poly2;
Polynom *PolySum, *node,*ptr,*ptr1,*ptr2; if (ptr1 == NULL) //end of list 1
node = (Polynom *) malloc (sizeof(Polynom)); {
PolySum = node; while(ptr2!= NULL) //copy the remaining of list2 to listResult
ptr1 = Poly1; ptr2 = Poly2; Ptr1
{ node->coef = ptr2->coef;
while (ptr1!=NULL && ptr2!=NULL){ node->exp = ptr2->exp;
ptr = node;
ptr2 = ptr2->next; //update ptr list 2
if (ptr1->exp < ptr2->exp ) {
ptr = node;
node->coef = ptr2->coef;
node->exp = ptr2->exp; Ptr2 node = (Polynom *) malloc (sizeof(Polynom));
ptr2 = ptr2->next; //update ptr list 2 ptr->next = node; //update ptr listResult
} }
else if ( ptr1->exp > ptr2->exp ) }
{ node->coef = ptr1->coef; else if (ptr2==NULL) //end of list 2
node->exp = ptr1->exp; ptr {
ptr1 = ptr1->next; //update ptr list 1 while(ptr1 != NULL) //copy the remaining of list1 to the listResult
} { node->coef = ptr1->coef;
else node->exp = ptr1->exp;
{ node->coef = ptr2->coef + ptr1->coef; ptr1 = ptr1->next; //update ptr list 2
node->exp = ptr2->exp; ptr = node;
ptr1 = ptr1->next; //update ptr list 1 node = (Polynom *)malloc (sizeof(Polynom));
ptr2 = ptr2->next; //update ptr list 2 ptr->next = node; //update ptr listResult
} }
node = (Polynom *) malloc (sizeof(Polynom)); }
ptr->nextp = node; //update ptr listResult ptr->next = NULL;
} //end of while }

Polynom *PolySum, *node,*ptr,*ptr1,*ptr2; Polynom *PolySum, *node,*ptr,*ptr1,*ptr2;


node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
PolySum = node; PolySum = node;
ptr1 = Poly1; ptr2 = Poly2; Ptr1 ptr1 = Poly1; ptr2 = Poly2; Ptr1
while (ptr1!=NULL && ptr2!=NULL){ while (ptr1!=NULL && ptr2!=NULL){
ptr = node; ptr = node;
if (ptr1->exp < ptr2->exp ) { if (ptr1->exp < ptr2->exp ) {
node->coef = ptr2->coef; node->coef = ptr2->coef;
node->exp = ptr2->exp; Ptr2 node->exp = ptr2->exp; Ptr2
ptr2 = ptr2->next; //update ptr list 2 ptr2 = ptr2->next; //update ptr list 2
} }
else if ( ptr1->exp > ptr2->exp ) else if ( ptr1->exp > ptr2->exp ) 2 1000
{ node->coef = ptr1->coef; { node->coef = ptr1->coef;
node->exp = ptr1->exp; ptr node->exp = ptr1->exp; ptr
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1
} }
else else
{ node->coef = ptr2->coef + ptr1->coef; { node->coef = ptr2->coef + ptr1->coef;
node->exp = ptr2->exp; node->exp = ptr2->exp;
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1

}
ptr2 = ptr2->next; //update ptr list 2
illustration }
ptr2 = ptr2->next; //update ptr list 2
illustration
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult
} //end of while } //end of while
Polynom *PolySum, *node,*ptr,*ptr1,*ptr2; Polynom *PolySum, *node,*ptr,*ptr1,*ptr2;
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
PolySum = node; PolySum = node;
ptr1 = Poly1; ptr2 = Poly2; Ptr1 ptr1 = Poly1; ptr2 = Poly2; Ptr1
while (ptr1!=NULL && ptr2!=NULL){ while (ptr1!=NULL && ptr2!=NULL){
ptr = node; ptr = node;
if (ptr1->exp < ptr2->exp ) { if (ptr1->exp < ptr2->exp ) {
node->coef = ptr2->coef; node->coef = ptr2->coef;
node->exp = ptr2->exp; Ptr2 node->exp = ptr2->exp; Ptr2
ptr2 = ptr2->next; //update ptr list 2 ptr2 = ptr2->next; //update ptr list 2
} }
else if ( ptr1->exp > ptr2->exp ) 2 1000 else if ( ptr1->exp > ptr2->exp ) 2 1000
{ node->coef = ptr1->coef; { node->coef = ptr1->coef;
node->exp = ptr1->exp; ptr node->exp = ptr1->exp; ptr
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1
} }
else else
{ node->coef = ptr2->coef + ptr1->coef; { node->coef = ptr2->coef + ptr1->coef;
node->exp = ptr2->exp; node->exp = ptr2->exp;
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1

}
ptr2 = ptr2->next; //update ptr list 2
illustration }
ptr2 = ptr2->next; //update ptr list 2
illustration
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult
} //end of while } //end of while

Polynom *PolySum, *node,*ptr,*ptr1,*ptr2; Polynom *PolySum, *node,*ptr,*ptr1,*ptr2;


node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
PolySum = node; PolySum = node;
ptr1 = Poly1; ptr2 = Poly2; Ptr1 ptr1 = Poly1; ptr2 = Poly2; Ptr1
while (ptr1!=NULL && ptr2!=NULL){ while (ptr1!=NULL && ptr2!=NULL){
ptr = node; ptr = node;
if (ptr1->exp < ptr2->exp ) { if (ptr1->exp < ptr2->exp ) {
node->coef = ptr2->coef; node->coef = ptr2->coef;
node->exp = ptr2->exp; Ptr2 node->exp = ptr2->exp; Ptr2
ptr2 = ptr2->next; //update ptr list 2 ptr2 = ptr2->next; //update ptr list 2
} }
else if ( ptr1->exp > ptr2->exp ) 2 1000 1 4 else if ( ptr1->exp > ptr2->exp ) 2 1000 1 4
{ node->coef = ptr1->coef; { node->coef = ptr1->coef;
node->exp = ptr1->exp; ptr node->exp = ptr1->exp; ptr
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1
} }
else else
{ node->coef = ptr2->coef + ptr1->coef; { node->coef = ptr2->coef + ptr1->coef;
node->exp = ptr2->exp; node->exp = ptr2->exp;
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1

}
ptr2 = ptr2->next; //update ptr list 2
illustration }
ptr2 = ptr2->next; //update ptr list 2
illustration
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult
} //end of while } //end of while
Polynom *PolySum, *node,*ptr,*ptr1,*ptr2; Polynom *PolySum, *node,*ptr,*ptr1,*ptr2;
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
PolySum = node; PolySum = node;
ptr1 = Poly1; ptr2 = Poly2; Ptr1 ptr1 = Poly1; ptr2 = Poly2; Ptr1
while (ptr1!=NULL && ptr2!=NULL){ while (ptr1!=NULL && ptr2!=NULL){
ptr = node; ptr = node;
if (ptr1->exp < ptr2->exp ) { if (ptr1->exp < ptr2->exp ) {
node->coef = ptr2->coef; node->coef = ptr2->coef;
node->exp = ptr2->exp; Ptr2 node->exp = ptr2->exp; Ptr2
ptr2 = ptr2->next; //update ptr list 2 ptr2 = ptr2->next; //update ptr list 2
} }
else if ( ptr1->exp > ptr2->exp ) 2 1000 1 4 else if ( ptr1->exp > ptr2->exp ) 2 1000 1 4 11 3
{ node->coef = ptr1->coef; { node->coef = ptr1->coef;
node->exp = ptr1->exp; ptr node->exp = ptr1->exp; ptr
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1
} }
else else
{ node->coef = ptr2->coef + ptr1->coef; { node->coef = ptr2->coef + ptr1->coef;
node->exp = ptr2->exp; node->exp = ptr2->exp;
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1

}
ptr2 = ptr2->next; //update ptr list 2
illustration }
ptr2 = ptr2->next; //update ptr list 2
illustration
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult
} //end of while } //end of while

Polynom *PolySum, *node,*ptr,*ptr1,*ptr2; Polynom *PolySum, *node,*ptr,*ptr1,*ptr2;


node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
PolySum = node; PolySum = node;
ptr1 = Poly1; ptr2 = Poly2; Ptr1 ptr1 = Poly1; ptr2 = Poly2; Ptr1
while (ptr1!=NULL && ptr2!=NULL){ while (ptr1!=NULL && ptr2!=NULL){
ptr = node; ptr = node;
if (ptr1->exp < ptr2->exp ) { if (ptr1->exp < ptr2->exp ) {
node->coef = ptr2->coef; node->coef = ptr2->coef;
node->exp = ptr2->exp; Ptr2 node->exp = ptr2->exp; Ptr2
ptr2 = ptr2->next; //update ptr list 2 ptr2 = ptr2->next; //update ptr list 2
} }
else if ( ptr1->exp > ptr2->exp ) 2 1000 1 4 11 3 else if ( ptr1->exp > ptr2->exp ) 2 1000 1 4 11 3
{ node->coef = ptr1->coef; { node->coef = ptr1->coef;
node->exp = ptr1->exp; ptr node->exp = ptr1->exp; ptr
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1
} }
else else
{ node->coef = ptr2->coef + ptr1->coef; { node->coef = ptr2->coef + ptr1->coef;
node->exp = ptr2->exp; node->exp = ptr2->exp;
ptr1 = ptr1->next; //update ptr list 1 ptr1 = ptr1->next; //update ptr list 1

}
ptr2 = ptr2->next; //update ptr list 2
illustration }
ptr2 = ptr2->next; //update ptr list 2
illustration
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult
} //end of while } //end of while
if (ptr1 == NULL) //end of list 1 if (ptr1 == NULL) //end of list 1
{ while(ptr2!= NULL) //copy the remaining of list2 to listResult { while(ptr2!= NULL) //copy the remaining of list2 to listResult
Ptr1 Ptr1
{ node->coef = ptr2->coef; { node->coef = ptr2->coef;
node->exp = ptr2->exp; node->exp = ptr2->exp;
ptr2 = ptr2->next; //update ptr list 2 ptr2 = ptr2->next; //update ptr list 2
ptr = node; ptr = node;
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
Ptr2 Ptr2
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult
} }
} 2 1000 1 4 11 3 } 2 1000 1 4 11 3
else if (ptr2==NULL) //end of list 2 else if (ptr2==NULL) //end of list 2
{ ptr { ptr
while(ptr1 != NULL) //copy the remaining of list1 to the listResult while(ptr1 != NULL) //copy the remaining of list1 to the listResult
{ node->coef = ptr1->coef; 3 2 { node->coef = ptr1->coef; 3 2
node->exp = ptr1->exp; node->exp = ptr1->exp;
ptr1 = ptr1->next; //update ptr list 2 ptr1 = ptr1->next; //update ptr list 2
ptr = node; ptr = node;
node = (Polynom *)malloc (sizeof(Polynom)); node = (Polynom *)malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult

}
}
illustration }
}
illustration
ptr->next = NULL; ptr->next = NULL;
} }

if (ptr1 == NULL) //end of list 1 if (ptr1 == NULL) //end of list 1


{ while(ptr2!= NULL) //copy the remaining of list2 to listResult { while(ptr2!= NULL) //copy the remaining of list2 to listResult
Ptr1 Ptr1
{ node->coef = ptr2->coef; { node->coef = ptr2->coef;
node->exp = ptr2->exp; node->exp = ptr2->exp;
ptr2 = ptr2->next; //update ptr list 2 ptr2 = ptr2->next; //update ptr list 2
ptr = node; ptr = node;
node = (Polynom *) malloc (sizeof(Polynom)); node = (Polynom *) malloc (sizeof(Polynom));
Ptr2 Ptr2
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult
} }
} 2 1000 1 4 11 3 } 2 1000 1 4 11 3
else if (ptr2==NULL) //end of list 2 else if (ptr2==NULL) //end of list 2
{ {
while(ptr1 != NULL) //copy the remaining of list1 to the listResult while(ptr1 != NULL) //copy the remaining of list1 to the listResult
{ node->coef = ptr1->coef; 3 2 { node->coef = ptr1->coef; 3 2
node->exp = ptr1->exp; node->exp = ptr1->exp;
ptr1 = ptr1->next; //update ptr list 2 ptr ptr1 = ptr1->next; //update ptr list 2 ptr
ptr = node; ptr = node;
4 0
node = (Polynom *)malloc (sizeof(Polynom)); node = (Polynom *)malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult ptr->next = node; //update ptr listResult

}
}
illustration }
}

ptr->next = NULL; ptr->next = NULL;


} }
illustration
Contents
if (ptr1 == NULL) //end of list 1
{ while(ptr2!= NULL) //copy the remaining of list2 to listResult
Ptr1
{ node->coef = ptr2->coef;
node->exp = ptr2->exp;
ptr2 = ptr2->next;
ptr = node;
//update ptr list 2
1. Array
node = (Polynom *) malloc (sizeof(Polynom));

}
ptr->next = node; //update ptr listResult
Ptr2
2. Linked List
} 2 1000 1 4 11 3
else if (ptr2==NULL)
{
//end of list 2
3. Stack
while(ptr1 != NULL) //copy the remaining of list1 to the listResult
{ node->coef = ptr1->coef;
node->exp = ptr1->exp;
3 2
4. Queue
ptr1 = ptr1->next; //update ptr list 2
ptr = node;
4 0
node = (Polynom *)malloc (sizeof(Polynom));
ptr->next = node; //update ptr listResult
ptr
}
}
NULL
ptr->next = NULL; 1000 3
}
A(x) = 2x + x
B(x) = x4 + 10x3 + 3x2 + 4
Result(x) = 2x1000 + x4 + 11x3 + 3x2 + 4 122

What is a stack? Operation on stack


• A stack is a data structure that only allows items to be inserted and removed at one end • Push: the operation to place a new item at the top of the stack
– We call this end the top of the stack
– The other end is called the bottom
• Pop: the operation to remove the next item from the top of the stack
• Access to other items in the stack is not allowed
• The last element to be added is the first to be removed (LIFO: Last In, First Out)

M
C C C
R push(M) R item = pop() R
item = M
X X X
A A A
What Are Stacks Used For? What Are Stacks Used For?
• Real life (Pile of books, Plate trays, etc.) • More applications related to computer science
• More applications related to computer science – compilers
– Program execution stack: Most programming languages use a “call stack” to implement
function calling
• parsing data between delimiters (brackets)
• When a method is called, its line number and other useful information are pushed • Check: each “(”, “{”, or “[” has to pair with “)”, “}”, or “]”
(inserted) on the call stack Example:
• When a method ends, it is popped (removed) from the call stack and execution
restarts at the indicated line number in the method that is now at the top of the stack
– correct: ( )(( )){([( )])}
– correct: ((( )(( )){([( )])}
1. main pushed onto call stack, before invoking methodA
2. methodA pushed onto call stack, before invoking methodB
– incorrect: )(( )){([( )])}
3. methodB pushed onto call stack, before invoking methodC – incorrect: ({[ ])}
4. methodC pushed onto call stack, invoked then popped out from the
call stack when completes – incorrect: (
5. methodB popped out from call stack when completes.
6. methodA popped out from the call stack when completes. – virtual machines
7. main popped out from the call stack when completes. Program • manipulating numbers
exits.
– pop 2 numbers off stack, do work (such as add)
– Evaluating expressions (e.g. (4/(2-2+3))*(3-4)*2)
– push result back on stack and repeat
– artificial intelligence
• finding a path

Example: Reversing a Word Example: Reversing a Word


• We can use a stack to reverse the letters in a word. • We can use a stack to reverse the letters in a word.
• How? • How?
• Example: READ • Example: READ

Push(R) Push(R) Pop(D)


Push(E)

Push(A)
Push(E)

Push(A)
Pop(A)

Pop(E)
DA E R
D Push(D) D Push(D) Pop(R)
A A
• Read each letter in the word and push it onto the stack • Read each letter in the word and push it onto the stack
E E
• When you reach the end of the word, pop the letters off
R R the stack and print them out
Implementing a Stack Stack: Array Implementation
• At least two different ways to implement a stack: • A stack consists of 4 elements: 3, 5, 7, 9.
– array • If an array is used to implement this stack, what is a good index for
– linked list the top item?
• Which method to use depends on the application – Is it position 0? S[0]=9 S[1]=7 S[2]=5 S[3]=3
– what advantages and disadvantages does each implementation have?
– Is it position 3? S[0]=3 S[1]=5 S[2]=7 S[3]=9

11 Top item

9
Let’s think when we need do operation:
7 - PUSH
- POP
5 The bottom of the stack is at S[0]
3 The top of the stack is at S[3]
Bottom item • pop off of the stack at S[3]
• push onto the stack at S[4]

Stack: Array Implementation Example Stack: Array Implementation


• If an array is used to implement a stack, the index for the top item is Basic operations: static int *s;
numItems-1 (where numItems is the number of items in the stack) • void STACKinit(int);
static int maxSize;//maximum number of elements that the stack could have
static int numItems; //current number of elements on stack
• Note that push and pop must both work in O(1) time as stacks are usually • int STACKempty();
void STACKinit(int maxSize)
{
assumed to be extremely fast • void STACKpush(Item); s = (int *) malloc(maxSize*sizeof(int));
N = 0;
• Implementing a stack using an array is fairly easy: • Item STACKpop(); }
int STACKempty(){return numItems==0;}
– The bottom of the stack is at S[0] int STACKfull() {return numItems==maxSize;}

– The top of the stack is at S[numItems-1]


– push onto the stack at S[numItems]
void STACKpush(int item)
– pop off of the stack at S[numItems-1] {
if (Stackfull()) ERROR(“Stack is full”);
else
{ s[numItems] = item;
numItems++;
}
}
… Item STACKpop()
S {
if (STACKempty()) ERROR(“Stack is empty”)
0 1 2 numItems N else
{
numItems--;
return s[numItems+1];
}
}
Array Implementation Summary
• Advantages Stack overflow
– Easy to implement • The condition resulting from trying to push an element onto a full stack.
– best performance: push and pop can be performed in O(1) time if(STACKfull())
• Disadvantage STACKpush(item);
– fixed size: the size of the array must be initially specified because Stack underflow
• The array size must be known when the array is created and is fixed, so that the right • The condition resulting from trying to pop an empty stack.
amount of memory can be reserved
• Once the array is full no new items can be inserted
if (STACKempty())
• If the maximum size of the stack is not known (or is much larger than the expected STACKpop(item);
size) a dynamic array can be used
– But occasionally push will take O(n) time


S
0 1 2 numItems maxSize
maxSize: maximum number of elements in the array

Implementing a Stack: using linked list Operations


• Store the items in the stack in a linked list 1. Init:
• The top of the stack is the head node, the bottom of the stack is the end Stack *StackConstruct();
of the list 2. Check empty:
• push by adding to the front of the list int StackEmpty(Stack* s);
• pop by removing from the front of the list 3. Check full:
int StackFull(Stack* s);
4.1 2.4 8.9 2.3 NULL
4. Insert a new item into stack (Push): insert a new item at the top of stack
int StackPush(Stack* s, float* item);
top
5. Remove an item from stack (Pop): remove and return the item at the top of stack:
3.3
3.3 4.1 2.4 8.9 2.3 NULL
float pop(Stack* s);
4.1 6. Print out all items of stack
typedef struct StackNode{
2.4 top float item;
void Disp(Stack* s);
struct StackNode *next;
8.9 } StackNode;
typedef struct {
2.3
StackNode *top;
}Stack;
Initialize stack
Stack *StackConstruct() {
Stack *s; /*** Check empty ***/
s = (Stack *)malloc(sizeof(Stack));
if (s == NULL) { int StackEmpty(const Stack *s) {
return NULL; // No memory return (s->top == NULL);
}
s->top = NULL; }
return s;
}

/**** Destroy stack *****/


/*** Check full ***/
void StackDestroy(Stack *s) { int StackFull() {
while (!StackEmpty(s)) {
StackPop(s); printf("\n NO MEMORY! STACK IS FULL");
} return 1;
free(s);
} }
137
138

Display all items in the stack Push


void disp(Stack* s) {
Need to do the following steps:
StackNode* node;
int ct = 0; float m;
(1) Create new node: allocate memory and assign data for new node
printf("\n\n List of all items in the stack \n\n"); (2) Link this new node to the top (head) node
if (StackEmpty(s)) (3) Assign this new node as top (head) node
printf("\n\n >>>>> EMPTY STACK <<<<<\n");
else { int StackPush(Stack *s, float item) {
node = s->top; StackNode *node;
do { node = (StackNode *)malloc(sizeof(StackNode)); //(1)
m = node->item; if (node == NULL) {
printf("%8.3f \n", m); StackFull(); return 1; // overflow: out of memory
node = node->next; }
} while (!(node == NULL)); node->item = item; //(1)
} node->next = s->top; //(2)
} s->top = node; //(3)
return 0;
}
Pop Experimental program
1. Check whether the stack is empty #include <stdio.h>
2. Memorize address of the current top (head) node #include <conio.h>
#include <stdlib.h>
3. Memorize data of the current top (head) node
#include <alloc.h>
4. Update the top (head) node: the top (head) node now points to its next node
// all above functions of stacks are put here
5. Free the old top (head) node int main() {
6. Return data of the old top (head) node int ch,n,i; float m;
Stack* stackPtr;
while(1)
float StackPop(Stack *s) {
{ printf("\n\n======================\n");
float data;
printf(“ STACK TEST PROGRAM \n");
StackNode *node;
printf("======================\n");
if (StackEmpty(s)) //(1)
printf(" 1.Create\n 2.Push\n 3.Pop\n 4.Display\n 5.Exit\n");
return NULL; // Empty Stack, can't pop
printf("----------------------\n");
node = s->top; //(2)
printf(“Input number to select the appropriate operation: ");
data = node->item; //(3)
scanf("%d",&ch); printf("\n\n");
s->top = node->next; //(4)
free(node); //(5)
return item; //(6)
}
142

Implementing a Stack: using linked list


switch(ch) { • Advantages:
case 1: printf(“INIT STACK");
stackPtr = StackConstruct(); break;
– always constant time to push or pop an element
case 2: printf(“Input float number to insert into stack: "); – can grow to an infinite size
scanf("%f",&m); • Disadvantages
StackPush(stackPtr, m); break;
case 3: m=StackPop(stackPtr); – Difficult to implement
if (m != NULL)
printf("\n Data Value of the popped node: %8.3f\n",m);
else {
printf("\n >>> Empty Stack, can't pop <<<\n");}
break;
case 4: disp(stackPtr); break;
case 5: printf("\n Bye! Bye! \n\n");
exit(0); break;
default: printf("Wrong choice");
} //switch
} // end while
} //end main

NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST CS - SOICT-HUST
Library STL in C++: stack Library STL in C++: stack
#include <stack>: a list type where insertion and removal are both Capacity
performed at the end of the list. size() Return the number of elements currently in stack
empty() True/False
Acess to an element
top() Acess to top element of stack

Query
push(x) Insert an element with value x on the top of stack. Size
of stack will be increased by 1
pop() Remove the top element from stack
Example about declaration:
swap(stack s1, stack s2) Swap elements of stack s1 and s2
stack <int> s1; //declare variable stack s1 in which type of each element in s1 is int
• We can not declare stack<int> myStack (5) to initialize a stack with 5
empty elements as in array.
• Similarly, we can not declare stack<int> myStack (5,100) to initialize a
stack consisting of 5 elements with values 100.
NGUYỄN KHÁNH PHƯƠNG 145 NGUYỄN KHÁNH PHƯƠNG 146
CS - SOICT-HUST CS - SOICT-HUST

Application 1: Parentheses Matching Application 1: Parentheses Matching


Check for balanced parentheses in an expression: Algorithm ParenMatch(X,n):
Input: Array X consists of n characters, each character could be either parentheses, variable,
Given an expression string expression, write a program to examine whether the pairs arithmetic operation, number.
and the orders of “{“,”}”,”(“,”)”,”[“,”]” are correct in expression. Output: true if parentheses in an expression are balanced
For example, the program should print true for expression = “[()]{}{[()()]()}” and false S = stack empty;
for expression = “[(])” for i=0 to n-1 do
if (X[i] is a starting bracket)
push(S, X[i]); // starting bracket (‘(‘ or ‘{‘ or ‘[‘) then push it to stack
else
if (X[i] is a closing bracket) // compare X[i] with the one currently on the top of stack
Algorithm: if isEmpty(S)
1) Declare a character stack S. return false {can not find pair of brackets}
2) Now traverse the expression string expression if (pop(S) not pair with bracket stored in X[i])
a) If the current character is a starting bracket (‘(‘ or ‘{‘ or ‘[‘) then push it to stack. return false {error: type of brackets}
b) If the current character is a closing bracket (‘)’ or ‘}’ or ‘]’) then pop from stack if isEmpty(S)
and if the popped character is the matching starting bracket then fine else parenthesis return true {parentheses are balanced}
are not balanced. else return false {there exist a bracket not paired}
3) After complete traversal, if there is some starting bracket left in stack then “not
balanced” NGUYỄN KHÁNH PHƯƠNG NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST CS - SOICT-HUST
Application 2: Calculate the value of an expression Application 2: Calculate the value of an expression
Example: Calculate the value of expression: (4/(2-2+3))*(3-4)*2) Scan the expression from left to right:
Node: Priority order of operations from high to low: • If the current element is Operand: push it into stack S1.
1. Exponent ^ • If the current element if Operator, denote it by OPT:
2. Multiplication Division * / – If stack S2 is empty: push operator OPT into stack S2, that means: Push(S2, OPT)
3. Addition subtraction + - – Else if OPT has higher priority than that of top(S2) then push OPT into stack S2,
that means Push(S2, OPT)
The algorithm use 2 stacks: – Else if OPT has priotiry lower or equal to that of top(S2) then
• Stack S1 stores operands • do Process Until operator OPT has higer priotiy than that of top(S2) OR stack
S1 is empty
• Stack S2 stores operators (+,-,*,/, ^) and opening bracket (
• Push(S2, OPT)
Procedure Process:
• If the current element if opening bracket: then push it into stack S2.
• Do Pop(S1) twice: Pop off 2 values on the top of S1 from S1, denote these 2 values
by A and B • If the current element if closing bracket: then
• Do Pop(S2): Pop off 1 operator on the top of S2 from S2, denote it by OPT. – do Process … Until found the first opening bracket in S2
• Do B OPT A, the result is stored in R – Pop the opening bracket from S2
• Push R into S1: do Push(S1, R) • When finish to scan the expression and Stack S1 is not empty:
NGUYỄN KHÁNH PHƯƠNG – do Process Until Stack S1 is empty NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST CS - SOICT-HUST

Example: Calculate 2 * ( 5 * ( 3 + 6 ) ) / 15 - 2 Example: Calculate 2 * ( 5 * ( 3 + 6 ) ) / 15 - 2


Element Operation Stack S1 Stack S2 Explanation Element Operation Stack S1 Stack S2 Explanation
2 Push 2 into S1 2 Empty 2 Push 2 into S1 2 Empty
* Push * into S2 2 * * Push * into S2 2 *
( Push ( into S2 2 ( * ( Push ( into S2 2 ( *
5 Push 5 into S1 5 2 ( * 5 Push 5 into S1 5 2 ( *
* Push * into S2 5 2 *( * * Push * into S2 5 2 *( *
( Push ( into S2 5 2 ( *( * ( Push ( into S2 5 2 ( *( *
3 Push 3 into S1 3 5 2 ( * ( * 3 Push 3 into S1 3 5 2 ( * ( *
+ Push + into S2 3 5 2 + ( *( * + Push + into S2 3 5 2 + ( *( *
6 Push 6 into S1 6 3 5 2 + ( *( * 6 Push 6 into S1 6 3 5 2 + ( *( *

) Call Process: Do Process until found the


first opening bracket in S2
Pop 6 and 3 from S1 5 2 + ( *( *
Pop + from S2 5 2 ( *( *
Do 3+6=9 5 2 ( *( *
Push 9 into S1 9 5 2 ( *( *
Pop ( from S2 9 5 2 *( *
Example: Calculate 2 * ( 5 * ( 3 + 6 ) ) / 15 - 2 Example: Calculate 2 * ( 5 * ( 3 + 6 ) ) / 15 - 2
Element Operation Stack S1 Stack S2 Explanation Element Operation Stack S1 Stack S2 Explanation
) Call Process: Do Process until found 15 Push 15 into S1 15 90 /
Pop 9 and 5 from S1 2 *( * the first opening - Call Process / “-” has lower priority
Pop * from S2 2 ( * bracket in S2 than “/”, so do Process
Do 5*9=45 2 ( * Pop 15 and 90 from S1
Push 45 into S1 45 2 ( * Pop / from S2
Pop ( from S2 * Do 90/15=6
/ Call Process: / and * have the same Push 6 into S1 6
Pop 45 and 2 from S1 * priority
Pop * from S2 Do Process
Do 2*45=90 - Push - into S2 6 -
Push 90 into S1 90
Push / into S2 /

Example: Calculate 2 * ( 5 * ( 3 + 6 ) ) / 15 - 2 Application 3: Adding two large numbers


Stack S1 Stack S2
Adding
these very large numbers
Element Operation Explanation
- Push - into S2 6 - • Treat numbers as strings of numerals, store the numbers
2 Push 2 into S1 2 6 - corresponding to these numerals on two stacks, and then perform
Call Process
Pop 2 and 6 from S1 EMPTY -
Already finish to scan all addition by popping numbers from the stacks
elements in expression,
but S1 is not empty.
Pop – from S2 EMPTY EMPTY
Therefore, call Process
Do 6-2=4
until S2 is empty
Push 4 into S1 4

1
2 9 4
3 2 3
+ =
7 6 6
8 5 1
8732 + 5629 = 14361
The value of expression = 4
Application 3: Adding two large numbers Contents
• Read the numerals of the first number and store the numbers
Adding very
corresponding large
to them numbers:
on one stack; detail algorithm 1. Array
• Read the numerals of the second number and store the numbers
corresponding to them on another stack;
• carry=0; 2. Linked List
• while at least one stack is not empty
 pop a number from each non-empty stack, add them and carry; 3. Stack
 push the sum (minus 10 if necessary) on the result stack;
 store carry in carry variable;
• push carry on the result stack if it is not zero; 4. Queue
• pop numbers from the result stack and display them

157 158

What is a Queue? Queues


• What is a queue?
– A data structure of ordered items such that items can be inserted only at one end and
removed at the other end.

Front/head Queue Back/rear/tail

Elements exit 1 2 3 4 Elements enter

no changes of order

Example: A line at the supermarket


• What can we do with a queue?
– Enqueue (insert) – Add an item to the queue (also called as insert)
– Dequeue (delete) – Remove an item from the queue (also called as getFront)

• A queue is called a FIFO (First in-First out) data structure.

NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST
Queue Queue specification
• Terms used in Queue are depicted in the following figure: Definitions: (provided by the user)
– maxSize: Max number of items that might be on the queue
Add/ – ItemType: Data type of the items on the queue
(Remove
/Dequeue) Enqueue Operations:
Front/Head Back/Rear • Q = init(); initialize empty queue Q
• isEmpty(Q); returns "true“ if queue Q is empty
• isFull(Q); returns "true“ if Q is full, indicates that we already use the maximum memory for
queue; otherwise returns “false”
• frontQ(Q); returns the item that is in front (head) of queue Q or returns error if queue Q is
empty.
• enqueue(Q,x); inserts item x into the back (rear) of queue Q. If before making insertion, the
queue Q is full, then give the notification about that.
• x = dequeue(Q); deletes the element at the front (head) of the queue Q, then returns x which
is the data of this element. If the queue Q is empty before dequeue, then give the error notification.
• print(Q); gives the list of all elements in the queue Q in the order from the front to the back.
NGUYỄN KHÁNH PHƯƠNG • sizeQ(Q); returns the number of elements currently in the queue Q.
KHMT – SOICT - ĐHBK HN

FIFO Queues everywhere!!!!


Add/ (Remove/Dequeue)
Enqueue
Back/Rear Front/Head

C rear E rear
B rear B C rear C
rear front B
A A A front B front front
front
enqueue(Q, A) enqueue(Q, B) enqueue(Q, C) dequeue(Q, A) enqueue(Q, E)

NGUYỄN KHÁNH PHƯƠNG


CS - SOICT-HUST
Queues Example -
Given the sequence of operations on queue Q as following. Determine the output and the data
on the queue Q after each operation:

• What are some applications of queues? Operation Output Queue Q


– Round-robin scheduling in processors 1 enqueue(5) - (5)
– Input/Output processing 2 enqueue(Q,3) - (5, 3)
– Queueing of packets for delivery in networks 3 dequeue(Q) 5 (3)
4 enqueue(Q,7) - (3, 7)
5 dequeue(Q) 3 (7)
6 front(Q) 7 (7)
7 dequeue(Q) 7 ()
8 dequeue(Q) error ()
9 isEmpty(Q) true ()
10 size(Q) 0 ()
11 enqueue(Q,9) - (9)
12 enqueue(Q,7) - (9, 7)
13 enqueue(Q,3) - (9, 7, 3)
14 enqueue(Q,5) - (9, 7, 3, 5)
9 (7, 3, 5)
NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST 15 dequeue(Q)

Stack Queue

Data structure with Last-In First-Out (LIFO) behavior Data structure with First-In First-Out (FIFO) behavior
In Out

C B A B C In Out

C B A B A
Implementing a Queue Implementing a Queue: using Array
• Just like a stack, we can implementing a queue in two ways: • Using an array to implement a queue is significantly harder than using an array
– Using an array to implement a stack. Why?
– A stack: we add and remove at the same end,
– Using a linked list
– A queue: we add to one end and remove from the other.

QUEUE

Implementing a Queue: using Array Implementing a Queue


There are some options for implementing a queue using an array: • Just like a stack, we can implementing a queue in two ways:
• Option 1: – Using an array
– Enqueue at Q[0] and shift all of the rest of the items in the array down to – Using a linked list
make room.
– Dequeue from Q[numItems-1]

Q
0 1 2 numItems-1 maxSize
Example:
Q
4 3 10 -1 8 9 numItems=6
0 1 2 3 4 5
Q
Enqueue(Q,-2) -2 4 3 10 -1 8 9 numItems=7
0 1 2 3 4 5 6
Q
Dequeue(Q) -2 4 3 10 -1 8 9 numItems=6
0 1 2 3 4 5 6

• Option 2: circular queue [“wrap around”]


Implementing a Queue: using linked list Library STL in C++: queue
• Store the items in the queue in a linked list • #include <queue> a list type where insertion is performed at the
• The top of the queue is the head node, the bottom of the queue is the end of the list end of the list and removal at the top of the list.
• Enqueue by adding a new element to the front of the list
• Dequeue by removing the last element from the list

typedef struct node{


float item;
4.1 2.4 8.9 2.3 NULL
struct node *next; Example of declaration:
}node;
typedef struct { queue <int> q1; //declare queue q1 in which type of each element is int
front rear
node *front, *rear; • Similar to stack, it is not allowed to declare queue<int> myQueue (5) to
}Queue;
initialize 5 empty elements.
Enqueue: 4.1 2.4 8.9 2.3 5.4 NULL
• Similarly, it is not allowed to decalre queue<int> myQueue (5,100) to
initialize 5 elements in queue with value of 100.
front rear

2.4 8.9 2.3 5.4 NULL


Dequeue:
NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST 174
front rear

Library STL in C++: queue Example


Capacity #include <iostream>
#include <queue>
size() Return number of elements in the queue
using namespace std;
empty() True/False int main ()
Access to an element {
queue <int> myqueue;
front() Access to the first element of the queue
int myint;
back() Access to the last element of the queue cout << "Please enter some integers (enter 0 to end):\n";
do {
cin >> myint;
Query myqueue.push (myint);
push(x) Insert a new element of value x at the end of the } while (myint);
queue. Size of queue will be increased by 1 cout << "myqueue contains: ";
pop() Remove the element at the top of queue. Size of while (!myqueue.empty())
queue will be reduced by 1 {
cout << " " << myqueue.front();
swap(queue q1, queue q2) Swap elements of queue q1 and q2 myqueue.pop();
}
return 0;
NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST 175 } 176
Application 1: recognizing palindromes Example 1: Whether “RADAR” is a palindrome or not
• A palindrome is a string that reads the same forward and backward. Step 1: Put “RADAR” into Queue and Stack:
Example: NOON, DEED, RADAR, MADAM
Current Queue Stack
Able was I ere I saw Elba
character (front on the left, (top on the left)
• How to recognize a given string is a palindrome or not:
rear on the right)
– Step 1: We will put all characters of the string into both a stack and a
queue.
R R R
– Step 2: Compare the contents of the stack and the queue character-by- A RA AR
character to see if they would produce the same string of characters:
• If yes: the given string is a palindrome D RAD DAR
• Otherwise: not palindrome
A RADA ADAR
R RADAR RADAR
front rear top
NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST

Example 1: Whether “RADAR” is a palindrome or not Example 2: recognizing palindromes

Able was I ere I saw Elba


Step 2: Delete “RADAR” from Queue and Stack:
• Dequeue until the queue is empty
• Pop the stack until the stack is empty
Queue Front of Top of Stack
(front on the left) Queue Stack (top on the left)

RADAR R R RADAR
ADAR A A ADAR
DAR D D DAR
AR A A AR
R R R R
empty empty empty empty

Conclusion: String "RADAR" is a palindrome


NGUYỄN KHÁNH PHƯƠNG
CS - SOICT-HUST
Application 2: Convert a string of digits into a decimal number
The algorithm is described as following:

// Convert sequence of digits stored in queue Q into decimal number n


// Remove empty space if any
do { dequeue(Q, ch)
} until ( ch != blank)
// ch is now the first digit of the given string
// Calculate n from sequence of digit in the queue
n = 0;
done = false;
do { n = 10 * n + decimal number that ch represents;
if (! isEmpty(Q) )
dequeue(Q,ch)
else
done = true
} until ( done || ch != digit)
// Result: n is the decimal number need to be found
NGUYỄN KHÁNH PHƯƠNG 181
CS - SOICT-HUST

You might also like