Basic Data Structures in C Programming
Basic Data Structures in C Programming
2
Variable declaration
• This first program (basic1.c)
#include <stdio.h> has a single variable, this
#include <stdlib.h> variable has a memory cell
address
int main(){ • The second program
int myvar; (basic1-1.c) assigned the
printf("addr myvar %8u\n",&myvar); number 16 to the 4 memory
} cells starting at addr of
myvar
#include <stdio.h> – Now there is data in the next 4
#include <stdlib.h> cells starting at the address of
myvar
int main(){
int myvar;
myvar = 16;
4
Variable assignment
#include <stdio.h> • This program (basic3.c)
#include <stdlib.h> copies the value stored
in memory cells starting
at addr var1 into
memory cells starting at
int main(){ the addr of var2
int var1;
int var2;
var1 = 16;
var2= var1;
printf("addr var1 %8u, value var1 %d, value var2 %d\n",
&var1,var1,var2);
}
5
Example
• This program (basic2.c)
#include <stdio.h> shows that the "type", "int"
#include <stdlib.h> "double", etc, in front of a
int main(){ variable name specifies the
int var1; number of consecutive
double var2; memory cells reserved for
int var3[5]; the variable
printf("addr var1 int %8u\n",&var1); • Print the addr of
printf("addr var2 double %8u\n",&var2); – The first cell of var1
printf("addr var3 array of int %8u\n",&var3); – The first cell of var2
– The first cell of the array var3
6
Array storage
#include <stdio.h> • This program (basic4.c)
#include <stdlib.h> declares 3 variables, two of
int main(){ them are arrays
int var1; • It shows the consecutive
memory cells used by arrays
int array1[3];
int array2[3];
printf("addr var1%8u\n",&var1);
printf("addr array1 %8u\n",&array1);
printf("addr array2 %8u\n",&array2);
7
How computers compute index addresses
#include <stdio.h> • (basic5.c) array1 is the address
#include <stdlib.h> of the memory cell where this
int main(){ data structure starts
int var1; • However, array1 has storage for
3 int
int array1[3];
• In order to store the value stored
int array2[3];
in var1 in array1[2], the
var1 = 16; computer needs to find the addr
array1[2] = var1; of the memory cell where the
third int starts
printf("addr var1 %8u value var1 %d\ • This is array1 + 8
n",&var1,var1);
printf("addr array1 %8u, addr
array1[2] %8u, value array1[2] %d\
n",&array1, &array1[2],array1[2]);
}
8
Pointers
• Memory cells may also store
addresses
• In this case we declare a
variable of type pointer
– int* mypointer;
• The previous declaration said
that the cells starting at addr
mypointer will contain the addr
of a memory cell which is the
beginning of an int
9
Example: pointers
• Print the addr of the memory cells for the var “pointer” and “var1”.
• Print the contain of memory cell “pointer”, empty. Assign the addr of the
memory cell “vars” to the cell of pointer
• Print the contain of memory cell “pointer” and the contain of the addr
stored in memory cell “pointer” (basic6.c)
#include <stdio.h>
#include <stdlib
int main(){
int var1 = 16;
int* pointer;
pointer = &var1;
printf("value stored in the memory cell pointer %8u\n\n",pointer);
printf("value of the addr stored in memory cell pointer %8u\n",*pointer);
} 10
Dynamic memory allocation
int main(){
int var1 = 16; • (basic7.c) array2 is of type
int *array2 = NULL; pointer
• malloc allocate consecutive
printf("first array2 %8u\n",array2); memory cells to the program for
3 integers
array2 = (int*)malloc(3*sizeof(int)); • malloc returns the addr of the
first cell of the consecutive
printf("addr array2 %8u\n",array2); memory cells for the integers
• Print
array2[2] = var1; – The addr of the first cell of array2
– The addr of the first cell of the third
integer in array2 (array2[2])
printf("addr array2 %8u, array2[2]
– The value stored in the array2[2]
%8u, value array2[2] %d\
n",&array2[0],&array2[2],array2[2]);
}
11
ARRAY
12
2.1. Array
• Imagine that we have 100 scores. We need to read them, process them and print
them. We must also keep these 100 scores in memory for the duration of the
program. We can define a hundred variables, each with a different name, as shown
in Figure1.
• But having 100 different names creates other problems. We need 100 references to
read them, 100 references to process them and 100 references to write them. Figure
2 shows a diagram that illustrates this problem.
13
2.1. Array
• An array is a sequenced of elements, normally of the same data type, although some
programming languages accept arrays in which elements are of different types.
• We can refer to the elements in the array as the first element, the second element
and so forth, until we get to the last element.
14
2.1. Array
Basic definitions
• An array is a fixed size sequential collection of elements of identical types.
• Array: a set of pairs (index and value)
– data structure: for each index, there is a value associated with that index.
– representation: implemented by using consecutive memory.
• In C/C++/Java: the element in an array are indexed by the integers 0 to n- 1, where
n is the size of the array
15
Array name versus element name
In an array we have two types of identifiers:
• the name of the array
• the name of each individual element.
The name of the array is the name of the whole structure, while the name of an element
allows us to refer to that element.
Example:
the name of the array is scores, and name of each element is the name of the array
followed by the index, for example, scores[0], scores[1], and so on.
16
Array types in C
C supports two types of arrays:
Fixed Length Arrays : The programmer “hard codes” the length of
the array, which is fixed at run-time.
Variable-Length Arrays : The programmer doesn’t know the
array’s length until run-time.
17
Declaring an one-dimensional array
To declare an array, we need to specify its data type, the array’s identifier and the
size:
• The arraySize can be a constant (for fixed length arrays) or a variable (for
variable-length arrays)
– Example: double A[10];
int n;
double A[n];
18
Declaration example: fixed length array
19
Declaring a one-dimensional array
• We can initialize fixed-length array elements when we
define an array.
• If we initialize fewer values than the length of the array, C
assigns zeroes to the remaining elements.
20
Declaring an Array
So what is actually going on when you set up an array?
Memory:
Each element is held in the next location along in memory
Essentially what the computer is doing is looking at the
FIRST address (which is pointed to by the variable p) and
then just counts along.
21
Accessing Elements
To access an array’s element, we need to provide an integral
value to identify the index we want to access.
• We can do this using a constant: scores[0];
• We can also use a variable:
for(i = 0; i < 9; i++)
scoresSum += scores[i];
22
Example
Write a C program that gives the address of each element of an 1D array:
#include <stdio.h>
int main()
Result in DevC
{ int A[ ] = {5, 10, 12, 15, 4}; (sizeof(int)=4)
int rows=5;
/* print the address of 1D array using pointer */
int *ptr = A;
printf("Address Contents\n");
for (int i=0; i < rows; i++)
printf("%8u %5d\n", ptr+i, *(ptr+i));
}
Row 0 X X X X
Row 1 X X X X
Row r X X X X
c c
elements elements
Example 3 x 4 array:
abcd
efgh
i jkl
Convert into 1D array Y by collecting elements by columns.
Within a column elements are collected from top to bottom.
Columns are collected from left to right.
Thus, we get Y[ ] =
{a, e, i, b, f, j, c, g, k, d, h, l}
Row- and Column-Major Mappings
2D array: r rows, c columns
Example: int a[3][6]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
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
a[2][0]=12 a[2][1]=13 a[2][2]=14 a[2][3]=15 a[2][4]=16 a[2][5]=17
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
0 6 12 1 7 13 2 8 14 3 9 15 4 10 16 5 11 17
Location(a[1][2]) = ?
start_address=6487488
Example row-major order: Memory allocation for 2D array (type int)
start_address=6487488 Location(a[1][2]) = ?
Location(a[1][2]) = ?
start_address=6487488
Example 2: Row- and Column-Major Mappings
2D array: r rows, c columns
Example: int a[3][6]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
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
a[2][0]=12 a[2][1]=13 a[2][2]=14 a[2][3]=15 a[2][4]=16 a[2][5]=17
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
0 6 12 1 7 13 2 8 14 3 9 15 4 10 16 5 11 17
Mapping (location):
Location(A[i][j]) = Location(A[0][0])+ i*4+j
Assume I declare a 2-dimensional array int A[2]
[7]={1,2,3,4,5,6,7,8,9,10,11,12,13,14}. Let also assume that an "int" is
4 bytes long.
11.
38
Operations on the array
• The common operations on arrays are searching, insertion, deletion,
retrieval and traversal.
Example: Given an array S consists of n integers: S[0], S[1], …, S[n-1]
– Search operation: search a value whether appears in the array S or not
function Search(S,value) returns true if value 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 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.
Inserting an element into an array
• Assume we need to insert 8 into an array already be sorted in ascending order:
1 3 3 7 12 14 17 19 22 30
• 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
1 3 3 7 8 12 14 17 19 22 30
• Moving all elements of the array is a slow operation (requires linear time O(n)
where n is the size of array)
Deleting an element from an array
• 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 ?
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.
Represent Matrices based on arrays
• m x n matrix is a table with m rows and n columns, but numbering begins at 1
rather than 0.
• M(i,j) denotes the element in row i and column j.
• Common matrix operations
– transpose
– addition
– Multiplication
15/15 8/36
sparse matrix
data structure?
Sparse Matrix
(1) Represented by a two-dimensional array (e.g. int M[6][6];)
• Sparse matrix wastes space.
(2) Each element is characterized by <row, col, value>.
• The terms in A should be ordered based on <row, col>
col1 col2 col3 col4 col5 col6 row col value
row1 15 0 0 22 0 15 A [0] 1 1 15 A[0][0] = 1;
row2
0 11 3 0 0 0 [1] 1 4 22
A[0][1] = 1;
A[0][2] = 15
row3 0 0 0 6 0 0 [2] 1 6 -15
[3] 2 2 11
row4 0 0 0 0 0 0 [4] 2 3 3
row5 91 0 0 0 0 0 [5] 3 4 -6 A[5][0] = 3;
[6] 5 1 91
A[5][1] = 4;
row6 0 0 28 0 0 0 6*6 A[5][2] = -6;
[7] 6 2 28
/* Array representation of sparse matrix
//[ ][0] represents row
//[ ][1] represents col
//[ ][2] represents value */
int MAX = 8; //number of elements != 0 in sparse matrix
int A[MAX][3];
Diagonal Matrix
1000
0200
0030
0004
• An n x n matrix in which all nonzero terms are on the diagonal.
• M(i, j) is on diagonal iff i = j
• number of diagonal elements in an n x n matrix is n
• non diagonal elements are zero
• Store diagonal only vs n2 whole:
• int M[5];
• int M[5][5];
Triangular Matrix
100 0
230 0
456 0
7 8 9 10
• An n x n matrix in which all nonzero terms are either on or below the diagonal.
– M(i,j) is part of lower triangle iff i >= j
• Number of elements in lower triangle is
1 + 2 + … + n = n(n+1)/2
• Store n2 whole vs only the lower triangle:
• Store n2 whole:
• Use 2D array A[n][n]
• Store only the lower triangle by:
• Option 1: Map lower triangular into a 1D array
• Option 2: Irregular 2D array
Option 1: Map Lower Triangular Array into a 1D array
Use row-major order, but omit terms that are not part
of the lower triangle.
1 100 0
2 3 230 0
456 0
4 5 6
7 8 9 10
7 8 9 l0
Irregular 2-D array: the length of rows is not required to be the same.
Creating and Using Irregular 2D Arrays
// STEP 1: declare a two-dimensional array variable
int ** iArray = new int*[numberOfRows];
OR:
int ** iArray;
malloc(iArray, numberOfRows*sizeof(*iArray));
//STEP 2: allocate the desired number of rows
// now allocate space for elements in each row
for (int i = 0; i < numberOfRows; i++)
iArray[i] = new int [length[i]];
OR:
for (int i = 0; i < numberOfRows; i++)
malloc(iArray[i], length[i]*sizeof(int));
// STEP 3: use the array like any regular array:
iArray[2][3] = 5;
iArray[4][6] = iArray[2][3]+2;
iArray[1][1] += 3;
Contents
2.1. Array
2.2. Record
2.3. Linked List
2.4. Stack
2.5. Queue
52
Record
• A record is an array where the elements have different types
• In C, the declaration of a variable of type record starts with the reserved
word “struct”
• Then the type and the name of the fields in the record are defined
• Finally, the name of the variable record is given
• To assign a value to a field of a record, we must first name the record and
then the field (record1.c)
int main(){
struct {
int num;
int deno;
}fraction;
[Link] = 13;
[Link] = 17;
printf("num %d, deno %d\n", [Link], [Link]);
} 53
Records: consecutive memory cells
• Show that record is made of consecutive memory cells like for
arrays (record2.c)
• The difference is the fields have different types and names
• In a program we refer to those fields using names but actually the
computer find the addr of cells in those fields in the same way as for
arrays
• To find the addr of field x
– Addr of the first cell of the record + number of bytes used by all the
fields before x (number of bytes depend on the type of each field)
int main(){
struct {
int num;
int deno;
}fraction;
printf("addr fraction %8u, addr num %8u, addr deno %8u\
n",&fraction,&[Link],&[Link]);
54
}
A second example of record (record3.c)
int main(){
struct {
int id;
char* name; /*string of characters*/
char grade;
}student;
printf("addr student %8u, addr id %8u, addr name %8u, addr grade %8u\
n",&student,&[Link],&[Link],&[Link]);
[Link] = 2021;
[Link] = "Big-X";
[Link]= 'A';
55
An array of records
• Print the addr of the first cell of each record (record4.c)
• Print the addr of the second and third field of each record
• Assig values to different fields and different records and print the assigned values
int main(){
struct {
int id;
char* name;
char grade;
}student[3];
printf("addr of student records, student[0] %8u, student[1] %8u, student[2] %8u\n\
n",&student[0],student[1],student[2]);
printf("addr of fields in student[0], name %8u, grade %8u\n\n",&student[0].name,&student[0].grade);
printf("addr of fields in student[1], name %8u, grade %8u\n\n",&student[1].name,&student[1].grade);
printf("addr of fields in student[2], name %8u, grade %8u\n\n",&student[2].name,&student[2].grade);
student[0].id = 2021;
student[1].name = "Big-X";
student[2].grade= 'A’;
printf("id %d, name %s, grade %c\n",student[0].id, student[1].name, student[2].grade);
}
56
Typedef & dynamic memory allocation for rec
• Now student is a type (not a variable), does not have a memory addr (record5.c)
• Minh is a pointer, will store the addr of the first cell of a record of type student
• malloc allocate memory cells for a data structure of type student
• Print the addrs of Minh and the fields in the record. Assign values to the fields and print those values
• Since Minh is a pointer, we must reference the fields of the object to which it points using “->”
int main(){
typedef struct {
int id;
char* name;
char grade;
}student;
student* Minh;
Minh = (student*)malloc(sizeof(student));
printf("addr Minh %8u addr Minh id %8u, addr Minh name %8u, addr Minh grade %8u\n\
n",&Minh,&Minh->id,&Minh->name,&Minh->grade);
Minh->id = 2021;
Minh->name = "Minh";
Minh->grade= 'A';
printf("id %d, name %s, grade %c\n",Minh->id, Minh->name, Minh->grade);
} 57
2.2. Record
• A record is a collection of related elements, possibly of different types, having a
single name.
• Each element in a record is called a field:
– A field has a type and exists in memory.
– Fields can be assigned values, which in turn can be accessed for selection or
manipulation.
• Example: Figure below contains two examples of records.
– The first example: fraction has two fields: numerator and denominator, both of
which are integers.
– The second example: student has three fields (id, name, grade) made up of three
different types.
58
2.2. Record
• Example:
struct {
int numerator;
int denominator;
} fraction;
[Link] = 13;
[Link] = 17;
59
Record name vs. field name
Just like in an array, we have two types of identifier in a record:
• the name of the record, and
• the name of each individual field inside the record.
The name of the record is the name of the whole structure, while the name of each field
allows us to refer to that field.
Example: in the student record:
• the name of the record is student,
• the name of the fields are [Link], [Link] and [Link].
Most programming languages use a period (.) to separate the name of the structure
(record) from the name of its components (fields).
60
Comparison of records and arrays
We can compare an array with a record. This helps us to understand when we should
use an array and when to use a record:
• An array defines a combination of elements, while a record defines the identifiable
parts of an element.
• For example, an array can define a class of students (40 students), but a record
defines different attributes of a student, such as id, name or grade.
• Array of records: If we need to define a combination of elements and at the same
time some attributes of each element, we can use an array of records. For example,
in a class of 30 students, we can have an array of 30 records, each record
representing a student.
61
Figure 1. Array of records
Contents
2.1. Array
2.2. Record
2.3. Linked List
2.4. Stack
2.5. Queue
62
2.3. Linked list
• Singly linked list
10 8 20
head
10 8 20
head
head
10 8 20
Create the first record of type node
• Define a type record name node. The second field is a pointer to an object of type
node
• Declare a variable “head” that is a pointer to an object of type node
• Then dynamically allocate memory for a record of type node. The addr of the first cell
of this object is stored in head
• Print the addr of head, of fields data and next (linklist1.c)
int main(){
typedef struct {
int data;
struct node* next;
}node;
node* head;
head = (node*)malloc(sizeof(node));
printf("addr head %8u addr head data %8u, addr head next %8u\n\n",head,&head-
>data,&head->next);
}
64
Create a second record of type node
• (linklist2.c)
int main(){
typedef struct {
int data;
struct node* next;
}node;
node* head;
node* secondNode;
head = (node*)malloc(sizeof(node));
secondNode = (node*)malloc(sizeof(node));
printf("addr head %8u addr head data %8u, addr head next %8u\n\n",head,&head-
>data,&head->next);
printf("addr secondNode %8u addr secondNode data %8u, addr secondNode next
%8u\n\n",secondNode,&secondNode->data,&secondNode->next);
65
Create a link list of 2 nodes
• A link list of two nodes is generated (linklist3.c)
• Assign memory addresses for two object of type node
• Connect the first node to the second one: head->next = secondNode;
• i.e., place the addr of the second node into the next field of the first node
• The link list starts with the head pointer which points to the addr of the first node
• The link list ends with the next pointer of secondNode which is NULL
node* head;
node* secondNode;
head = (node*)malloc(sizeof(node));
secondNode = (node*)malloc(sizeof(node));
head->data = 1;
head->next = secondNode;
secondNode->data = 2;
secondNode->next = NULL;
} 66
Add a third node to the link list (linklist4.c)
node* head;
node* secondNode;
node* thirdNode;
head = (node*)malloc(sizeof(node));
secondNode = (node*)malloc(sizeof(node));
thirdNode = (node*)malloc(sizeof(node));
head->data = 1;
head->next = secondNode;
secondNode->data = 2;
secondNode->next = thirdNode;
thirdNode->data = 3;
thirdNode->next = NULL;
67
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.
• Example: Figure shows a singly linked list contains four nodes:
10 8 20
head
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.
• Example: Figure shows a singly linked list contains four nodes:
list
Declare singly linked list in C programming language
..
• List of integer numbers:
7 17 4 24
• List of students with data: student’s ID, grade of math and physics
Need to declare:
– the type of data in the node first,
– 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
DECLARE SINGLY LINKED LIST
typedef struct {
..... Define the type of data of the node
}NodeType;
typedef struct {
NodeType data; Define the singly linked list
struct node* next;
}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)
• 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
Example1: List of students with data: id of student, marks of 2 subjects: math, physics
typedef struct{
char id[15]; Define the type of data of the node
float math, physics;
}student; data
typedef struct {
student data; next
struct node* next; id math physics
}node;
node* head; A node
DECLARE SINGLY LINKED LIST
typedef struct {
..... Define the type of data of the node
}NodeType;
typedef struct {
NodeType data; Define the singly linked list
struct node* next;
}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)
• 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
Example2: List of integer numbers
7 17 4 24
typedef struct {
int data; “int” is the type of node, so do not need to use
struct node* next; “typedef….NodeType” to define the type
}node;
node* head;
data
A node
DECLARE SINGLY LINKED LIST
typedef struct {
..... Define the type of data of the node
}NodeType;
typedef struct {
NodeType data; Define the singly linked list
struct node* next;
}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)
• 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
Example 3: List of contacts with data: name and phone number
typedef struct{
char name[15]; Define the type of data of the node
char phone[20];
}contact; data
typedef struct {
contact data; next
struct node* next; name phonenumber
}node;
node* head; A node
Important elements of singly linked list
• head: store the address of the first node in the linked list
• NULL: value of the pointer of the last node in the linked list
• cur: the pointer stored the address of current node
cur
head (or root)
NULL
• Allocate memory for a new node pointed by the pointer newNode in the list:
node *newNode = (node *) malloc(sizeof(node));
• Access to the data of the node pointed by pointer newNode :
newNode->data
• Free memory allocated for node pointed by pointer newNode :
free(newNode); newNode
74
Operations on singly linked Lists
• Traverse the singly linked list
• Insert a node into the singly linked list
• Delete a node from the singly linked list
• Search data in the singly linked list
Operations on singly linked Lists
• Traverse the singly linked list
• Insert a node into the singly linked list
• Delete a node from the singly linked list
• Search data in the singly linked list
Traversing a singly linked list
for ( cur = head; cur != NULL; cur = cur->next )
showData_Of_Current_Node( cur->data );
cur
head NULL
• Change the value of the pointer cur
• Finish to browse the list when the NULL value is encountered
cur
77
head NULL
Exercise 1
• A sequence of integers is stored by a singly linked list.
typedef struct Node{
int data;
struct Node *next;
}Node;
Node *head;
head
1 2 3
NULL
78
head secon third
d
1 2 3
NULL
cur
Data = 1
Data = 2
Data = 3
79
Operations on singly linked lists
• Traverse the singly linked list
• Insert a node into the singly linked list
• Delete a node from the singly linked list
• Search data in the singly linked list
Operations on singly linked list: Insertion
Insert a new node :
• At the beginning of the list
• After the position pointed by the pointer cur
• Before the position pointed by the pointer cur
• At the end of the list
cur
head
…
Operations on singly linked list: Insertion
Insert a new node:
• At the beginning of the list
<create a new node new_node>;
new_node ->next = head;
head= new_node;
head
…
node *Insert_ToHead(node *head, NodeType X)
{ node *new_node;
new_node = (node *) malloc(sizeof(node));
new_node->data = X;
new_nod new_node->next = head;
head=new_node;
e return head;
}
82
Operations on singly linked list: Insertion
Insert a new node :
• At the beginning of the list
• After the position pointed by the pointer cur
• Before the position pointed by the pointer cur
• At the end of the list
cur
head
…
Operations on singly linked list: Insertion
• Insert a new node after the node pointed by the pointer cur:
<create a new node new_node>;
new_node ->next = cur->next;
cur->next = new_node;
cur
head
new_nod 84
Operations on singly linked list: Insertion
• Insert a new node after the node pointed by the pointer cur:
<create a new node new_node>;
new_node ->next = cur->next;
cur->next = new_node;
Write a function to insert a node with data = X (having the type «NodeType » after the
node pointed by the pointer cur. The function returns the address of the new node:
85
Operations on singly linked list: Insertion
• Insert a new node after the node pointed by the pointer cur:
<create a new node new_node>; ?? Empty list
new_node ->next = cur->next;
cur->next = new_node;
// wrong implementation:
cur->next = new_node;
new_node ->next = cur->next;
cur
head
new_nod 86
Operations on singly linked list: Insertion
• Insert a new node after the node pointed by the pointer cur:
<create a new node new_node>;
?? Empty list
new_node ->next = cur->next;
cur->next = new_node;
87
Operations on singly linked list: Insertion
Insert a new node :
• At the beginning of the list
• After the position pointed by the pointer cur
• Before the position pointed by the pointer cur
• At the end of the list
cur
head
…
Operations on singly linked list: Insertion
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
prev->next = new_node;
new_node>next = cur; ?? cur is the first node in the list
prev cur
head
…
Insert a new 89
node:
Operations on singly linked list: Insertion
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
prev->next = new_node;
new_node->next = cur; ?? cur is the first node in the list
90
Operations on singly linked list: Insertion
Insert a new node: head
• At the beginning
• After the node pointed by cur
• Before the node pointed by cur
…
• At the end of the list
<create a new node new_node>;
if (head == NULL) { /* list does not have any node yet*/
head = new_node;
}
else {
//move the pointer to the end of the list:
node *last =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, NodeType X)
{ node *new_node;
new_node = (node *) malloc(sizeof(node));
new_node->data = X;
if (head == NULL) head = new_node;
else
{
.… Complexity is node *last;
last=head;
while (last->next != NULL) // move to the last node
last = last->next;
last->next = new_node;
}
return head; 91
}
Operations on singly linked Lists
• Traverse the singly linked list
• Insert a node into the singly linked list
• Delete a node from the singly linked list
• Search data in the singly linked list
Operations on singly linked lists: Deletion
• Delete a node
• Delete all nodes of the list
Operations on singly linked lists: Deletion
Delete a node:
• The first node of the list
head
≡del
94
Delete the first node of the list
• Delete the node del that is currently the first node of the list:
head = del->next;
free(del);
del
head NULL
95
Delete the node in the middle/end 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
free(del); //delete node del to free memory
prev del
head
prev del
head
NULL
96
Delete the node at the middle/end of the list
Delete node del that is currently the middle/last node of the list:
prev del
head
…
97
Delete the node at the middle/end of the list
Delete node del that is currently the middle/last node of the list:
prev del
head
…
98
Delete a node pointed by the pointer del
Write the function node *Delete_Node(node *head, node *del)
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:
del = head ;
while (del != NULL)
{
head = head->next;
free(del);
del = head;
}
Traverse elements one by one from the head till the end
head
1 2 3
del
10
1
Freeing all nodes of a list
del = head ;
while (del != NULL)
{
head = head->next;
free(del);
del = head;
}
head
2 3
del
10
2
Freeing all nodes of a list
del = head ;
while (del != NULL)
{
head = head->next;
free(del);
del = head;
}
head
2 3
del
10
3
Freeing all nodes of a list
del = head ;
while (del != NULL)
{
head = head->next;
free(del);
del = head;
}
head
3 NULL
del
10
4
Freeing all nodes of a list
Write the function node* deleteList(node* head)
to delete all the node in the list having the first node pointed by the pointer head
The function returns the pointer head after deletion
node* deleteList(node* head)
{
node *del = head ;
while (del != NULL)
{
head = head->next;
free(del);
del = head;
}
return head;
}
Check whether the singly linked list is empty or not
Write the function int IsEmpty(node *head)
to check whether the singly linked list is empty or not (the pointer head pointed to the
first node of the list).
The function returns 1 if the list is empty; 0 otherwise
Insertions and Deletions are inefficient: Elements Insertions and Deletions are efficient: No shifting
are usually shifted
No memory waste if the array is full or almost Extra storage needed for references; however
full; otherwise may result in much memory uses exactly as much memory as it needs
waste.
Sequential access is faster because of greater Sequential access is slow because of low locality
locality of references [Reason: Elements in of references [Reason: Elements not in
contiguous memory locations] contiguous memory locations]
2.3. Linked list
• Singly linked list
10 8 20
head
10 8 20
head
tail
Doubly 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
tail
10 8 20
head tail
typdedef struct {
int number;
struct dllist *next;
struct dllist *prev;
} dllist;
dllist *head, *tail;
Doubly linked list
• Declare doubly linked list store data of students: ID, marks of math and physics
head tail
typedef struct{
char id[15];
float math, physics;
}student;
typedef struct {
student data;
struct ddlist* next;
struct ddlist* prev;
}dllist;
dllist *head, *tail;
DOUBLY LINKED LIST – EXAMPLE
typedef struct {
char data;
struct dblist *prev;
struct dblist *next;
}dblist;
dblist node1, node2, node3;
[Link]=‘a’;
[Link]=‘b’;
[Link]=‘c’;
[Link]=NULL; c
NULL a b NULL
[Link]=node2;
[Link]=node1;
[Link]=node3;
[Link]=node2;
[Link]=NULL; 115
Delete a node pointed by the pointer p
void Delete_Node (ddlist *p){
if (head == NULL) printf(”Empty list”);
else {
if (p==head) head = head->next; //Delete first element
p
head tail
116
Delete a node pointed by the pointer p
void Delete_Node (ddlist *p){
if (head == NULL) printf(”Empty list”);
else {
if (p==head) head = head->next; //Delete first element
p
head tail
117
Delete a node pointed by the pointer p
void Delete_Node (ddlist *p){
if (head == NULL) printf(”Empty list”);
else {
if (p==head) head = head->next; //Delete first element
p
head tail
118
Insert a node after the node pointed by pointer p
void Insert_Node (NodeType X, ddlist *p){
if (head == NULL){ // List is empty
head =(ddlist*)malloc(sizeof(ddlist));
head->data = X;
head->prev =NULL;
head->next =NULL;
}
else{
ddlist *newNode;
newNode=(ddlist*)malloc(sizeof(ddlist));
newNode->data = X;
newNode->next = NULL;
newNode->next = p->next;
newNode->prev=p;
if (p->next!=NULL)
p->next->prev=newNode; 12
p->next = newNode;
}
}
8 5 5
119
p
Exercise 2: Create a double linked list store integer numbers
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
typedef struct {
int number;
struct dllist *next;
struct dllist *prev;
} dllist;
dllist *head, *tail;
120
/* Insert a new node p at the end of the list */
void append_node(dllist *p) {
if(head == NULL)
{
head = p;
p->prev = NULL;
}
else {
tail->next = p;
p->prev = tail;
}
tail = p;
p->next = NULL;
}
/* Insert a new node p after a node pointed by the pointer after */
void insert_node(dllist *p, dllist *after) {
p->next = after->next;
p->prev = after;
if(after->next != NULL)
after->next->prev = p;
else
tail = p;
after->next = p;
}
/* Delete a node pointed by the pointer p */
void delete_node(dllist *p) {
if(p->prev == NULL)
head = p->next;
else p->prev->next = p->next;
if(p->next == NULL)
tail = p->prev;
else p->next->prev = p->prev;
}
int main( ) {
dllist *tempnode; int i;
/* add some numbers to the double linked list */
for(i = 1; i <= 5; i++) {
tempnode = (dllist *)malloc(sizeof(dllist));
tempnode->number = i;
append_node(tempnode);
}
/* print the dll list forward */
printf(" Traverse the dll list forward \n");
for(tempnode = head; tempnode != NULL; tempnode = tempnode->next)
printf("%d\n", tempnode->number);
list
typedef struct {
NodeType data;
struct node * next; Store data
}next;
Circular Doubly Linked Lists
list
typedef struct {
NodeType data;
struct node * prev;
Store data
}node;
Linked Lists of Lists
list
typedef struct
{
int row_number;
struct row_list *link_down;
struct value_list *link_right;
} row_list;
Exercise: Polynomial Addition
Polynomials: defined by a list of coefficients and exponents
- degree of polynomial = the largest exponent in the polynomial
Example:
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.
Operations with polynomials such as: Add two polynomials, Multiply two polynomials, ..., are
thus possible to install simply.
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]
3 0 0 0 0 2 6 0 0 0 4
… 2 … 0 1 0 0 0 A
… 0 … 1 10 3 0 1 B
1000 … 4 3 2 1 0
131
What is a stack?
• A stack is a data structure that only allows items to be inserted and removed at one end
– We call this end the top of the stack
– The other end is called the bottom
• 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)
Operation on stack
• Push: the operation to place a new item at the top of the stack
• Pop: the operation to remove the next item from the top of the stack
M
C C C
R push(M) R item = pop() R
item = M
X X X
A A A
What Are Stacks Used For?
• Real life (Pile of books, Plate trays, etc.)
• More applications related to computer science
– Program execution stack: Most programming languages use a “call stack” to implement
function calling
• When a method is called, its line number and other useful information are pushed
(inserted) on the call stack
• 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
Push(R)
Push(E)
Push(A)
D Push(D)
A
• Read each letter in the word and push it onto the stack
E
R
Example: Reversing a Word
• We can use a stack to reverse the letters in a word.
• How?
• Example: READ
Push(R) Pop(D)
Push(E)
Push(A)
Pop(A)
Pop(E)
DA E R
D Push(D) Pop(R)
A
• Read each letter in the word and push it onto the stack
E • When you reach the end of the word, pop the letters off
R the stack and print them out
Implementing a Stack
• At least two different ways to implement a stack
– array
– linked list
• Which method to use depends on the application
– what advantages and disadvantages does each implementation have?
Stack: Array Implementation
• If an array is used to implement a stack what is a good index for the top item?
– Is it position 0?
– Is it position numItems-1?
• Note that push and pop must both work in O(1) time as stacks are usually
assumed to be extremely fast
• Implementing a stack using an array is fairly easy:
– The bottom of the stack is at S[0]
– The top of the stack is at S[numItems-1]
– push onto the stack at S[numItems]
– pop off of the stack at S[numItems-1]
…
S
0 1 2 numItems N
Stack: Array Implementation
Basic operations: typedef .... Item;
static Item *s;
• void STACKinit(int); static int maxSize;//maximum number of elements that the stack could have
static int numItems; //current number of elements on stack
• int STACKempty(); void STACKinit(int maxSize)
{
• void STACKpush(Item); s = (Item *) malloc(maxSize*sizeof(Item));
• numItems = 0;
Item STACKpop(); }
int STACKempty(){return numItems==0;}
int STACKfull() {return numItems==maxSize;}
…
S
0 1 2 numItems maxSize
maxSize: maximum number of elements in the array
Stack overflow
• The condition resulting from trying to push an element onto a full stack.
if(STACKfull())
STACKpush(item);
Stack underflow
• The condition resulting from trying to pop an empty stack.
if (STACKempty())
STACKpop(item);
Implementing a Stack: using linked list
• Store the items in the stack in a linked list
• The top of the stack is the head node, the bottom of the stack is the end
of the list
• push by adding to the front of the list
• pop by removing from the front of the list
4.1 2.4 8.9 2.3 NULL
top
3.3
3.3 4.1 2.4 8.9 2.3 NULL
4.1
typedef struct {
2.4 top float item;
struct StackNode *next;
8.9 } StackNode;
typedef struct {
2.3 StackNode *top;
}Stack;
Operations
1. Init:
Stack *StackConstruct();
2. Check empty:
int StackEmpty(Stack* s);
3. Check full:
int StackFull(Stack* s);
4. Insert a new item into stack (Push): insert a new item at the top of stack
int StackPush(Stack* s, float* item);
5. Remove an item from stack (Pop): remove and return the item at the top of stack:
float pop(Stack* s);
6. Print out all items of stack
void Disp(Stack* s);
Initialize stack
Stack *StackConstruct() {
Stack *s;
s = (Stack *)malloc(sizeof(Stack));
if (s == NULL) {
return NULL; // No memory
}
s->top = NULL;
return s;
}
147
Push
Need to do the following steps:
(1) Create new node: allocate memory and assign data for new node
(2) Link this new node to the top (head) node
(3) Assign this new node as top (head) node
int StackPush(Stack *s, float item) {
StackNode *node;
node = (StackNode *)malloc(sizeof(StackNode)); //(1)
if (node == NULL) {
StackFull(); return 1; // overflow: out of memory
}
node->item = item; //(1)
node->next = s->top; //(2)
s->top = node; //(3)
return 0;
}
Pop
1. Check whether the stack is empty
2. Memorize address of the current top (head) node
3. Memorize data of the current top (head) node
4. Update the top (head) node: the top (head) node now points to its next node
5. Free the old top (head) node
6. Return data of the old top (head) node
150
switch(ch) {
case 1: printf(“INIT STACK");
stackPtr = StackConstruct(); break;
case 2: printf(“Input float number to insert into stack: ");
scanf("%f",&m);
StackPush(stackPtr, m); break;
case 3: m=StackPop(stackPtr);
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
Implementing a Stack: using linked list
• Advantages:
– always constant time to push or pop an element
– can grow to an infinite size
• Disadvantages
– Difficult to implement
Application 1: Parentheses Matching
Check for balanced parentheses in an expression:
Given an expression, write a program to examine whether the pairs match and the order
is correct of “{“,”}”,”(“,”)”,”[“,”]”.
For example, the program should print true for expression = “[()]{}{[()()]()}” and false
for expression = “[(])”
Algorithm:
1) Declare a character stack S.
2) Now traverse the string expression
a) If the current character is a starting bracket (‘(‘ or ‘{‘ or ‘[‘) then push it to stack.
b) If the current character is a closing bracket (‘)’ or ‘}’ or ‘]’) then pop from stack
and if the popped character is the matching starting bracket then fine else parenthesis
are not balanced.
3) After complete traversal, if there is some starting bracket left in stack then “not
balanced”
Application 2: HTML Tag Matching
In HTML, each <name> has to pair with </name>
<body>
<center>
<h1> The Little Boat </h1>
</center>
The Little Boat
<p> The storm tossed the little
boat like a cheap sneaker in an The storm tossed the little boat
old washing machine. The three like a cheap sneaker in an old
drunken fishermen were used to washing machine. The three
such treatment, of course, but drunken fishermen were used to
not the tree salesman, who even as such treatment, of course, but not
a stowaway now felt that he the tree salesman, who even as
had overpaid for the voyage. </p>
a stowaway now felt that he had
<ol>
<li> Will the salesman die? </li> overpaid for the voyage.
<li> What color is the boat? </li>
<li> And what about Naomi? </li> 1. Will the salesman die?
</ol> 2. What color is the boat?
</body> 3. And what about Naomi?
Application 3: Finding a Path using stack
• Consider the following graph of flights
: city
Z
flight goes from W to S
W S
Y
W S
R P T
X Q
Application 3: Finding a Path using stack
• If it exists, we can find a path from any city C1 to another city C2 using a stack
– place the starting city on the bottom of the stack
• mark it as visited
• pick any arbitrary arrow out of the city
– city cannot be marked as visited
• place that city on the stack
– also mark it as visited
• if that’s the destination, we’re done
• otherwise, pick an arrow out of the city currently at
– next city must not have been visited before
– if there are no legitimate arrows out, pop it off the stack and go back to
the previous city
• repeat this process until the destination is found or all the cities have been
visited
Application 3: Finding a Path using stack
• Consider the following graph of flights
: city
Z
flight goes from W to S
W S
Y
• Want to go from P to Y
– push P on the stack and mark it as visited
W S – pick R as the next city to visit (random select)
• push it on the stack and mark it as visited
– pick X as the next city to visit (only choice)
R P T • push it on the stack and mark it as visited
– no available arrows out of X – pop it
– no more available arrows from R – pop it
X Q – pick W as next city to visit (only choice left)
• push it on the stack and mark it as visited
– pick Y as next city to visit (random select)
• this is the destination – all done
Contents
2.1. Array
2.2. Record
2.3. Linked List
2.4. Stack
2.5. Queue
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.
no changes of order
Example: A line at the supermarket
• What can we do with a queue?
– Enqueue - Add an item to the queue
– Dequeue - Remove an item from the queue
These operations are also called insert and getFront in order to simplify things.
• A queue is called a FIFO (First in-First out) data structure.
Add/ (Remove/Dequeue)
Enqueue
Back/Rear Front/Head
Queue specification
Definitions: (provided by the user)
– maxSize: Max number of items that might be on the queue
– ItemType: Data type of the items on the queue
Operations:
• 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.
• sizeQ(Q); returns the number of elements currently in the queue Q.
FIFO
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) enqueue(Q, E)
Queues
• What are some applications of queues?
– Round-robin scheduling in processors
– Input/Output processing
– Queueing of packets for delivery in networks
Example -
Given the sequence of operations on queue Q as following. Determine the output and the data
on the queue Q after each operation:
In Out
C B A B C
Queue
In Out
C B A B A
Implementing a Queue
• Just like a stack, we can implementing a queue in two ways:
– Using an array
– Using a linked list
Implementing a Queue: using Array
• Using an array to implement a queue is significantly harder than using an array
to implement a stack. Why?
– A stack: we add and remove at the same end,
– A queue: we add to one end and remove from the other.
QUEUE
Array implementation of queues
0 1 2 3 4 5 6
7
Q: 17 23 97 44
front = 0 rear = 3
front = 0 rear = 3
Initial queue: 17 23 97 44
front = 1 rear = 4
0 1 2 3 4 5 6
7
Q: 44 55 11 22 33
rear = 1 front = 5
0 1 2 3 4 5 6
Q: 7
44 55 66 77 88 11 22 33
rear = 4 front = 5
• If we remove all eight items, making the queue completely
empty, it would look like this:
0 1 2 3 4 5 6
7
Q:
rear = 4 front = 5
• Can’t tell whether the queue is full or empty 172
Queues full or empty: solutions
• Solution 1: Keep an additional variable count which
stores the current number of items in the queue
0 1 2 3 4 5 6
7
Q: 44 55 66 77 88 11 22 33
0 1 2 3 4 5 6
7
Q: 44 55 66 77 11 22 33
rear = 3 front = 5
173
Implementation of solution 1:
• Solution 1: Keep an additional variable
0 1 2 3 4 5 6
7
Q: 44 55 66 77 88 11 22 33
rear = 3 front = 4
• Dequeue(Q) : if (rear == front) return ‘queue
is empty’;
else front = (front + 1) % n;
Dequeue Q[front];
• Enqueue(Q,x): if (rear+1 == front) return
‘queue is full’;
else rear = (rear + 1) % n;
Q[rear] = x; 175
Implementing a Queue using Array: Examples
• Q[front]: the first item of the queue
• Circular queue [“wrap around”] • Q[rear]: the last item of the queue
• Add item to the Q (Enqueue): rear+=1;Q[rear]=item;
Example 1: The array used to represent queue has maxSize = 4 • Remove item from Q (Dequeue): remove Q[front];
then front+=1
initialize: Q is empty: front = 0; rear = -1;
enqueue(Q,2) enqueue(Q,3) enqueue(Q,5) dequeue(Q) dequeue(Q) enqueue(Q,10)
rear + 1 == front
rear++; rear++;
Q[rear] = 30; Q[rear] = 50; We can not distinguish between
Q = (5, 10, 20, 30) rear = 2 = front the two cases: EMPTY and
FULL !!!!!
dequeue(Q) dequeue(Q) dequeue(Q) dequeue(Q)
rear == front
Make front point to the element preceding the front element in the queue (one memory
• Q[front+1]:
location the first item of the queue
will be wasted).
• Q[rear]: the last item of the queue
• Add item to the Q (Enqueue): rear+=1; Q[rear]=item
• Remove item from Q (Dequeue): front+=1; then remove Q[front] from queue
Example 4: The array used to represent queue has maxSize = 4
Initialize: front = rear = maxSize – 1 = 3; illustration for solution 1
Queue Q is empty
enqueue(Q, 30) ??
184
Solution 2: Make front point to the element preceding the front element in the queue
(one memory location will be wasted)
enqueue(Q,x) /*inserts item x into the back (rear) of queue Q. If the queue is full before making insertion, then give the
notification about that*/
{
if (isFull(Q)) ERROR(“Queue is FULL”);
else
{ rear ++;
if (rear == maxSize) rear = 0;
Q[rear] = x;
}
}
enqueue(Q,x)
{
if (isFull(Q)) ERROR(“Queue is FULL”);
else
{ rear = (rear + 1) % maxSize;
Q[rear] = x;
}
} 185
Solution 2: Make front point to the element preceding the front element in the queue
(one memory location will be wasted)
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*/
{
if (isEmpty(Q)) ERROR(“Queue is EMPTY”);
else
{ front = (front + 1);
if (front == maxSize) front = 0;
return Q[front];
}
}
dequeue(Q)
{ if (isEmpty(Q)) ERROR(“Queue is EMPTY”);
else
{ front = (front + 1) % maxSize;
return Q[front];
}
} front = front + 1;
=>front = 4 = maxSize
Dequeue (Q)
=> wrap around: front =0
Dequeue Q[front]
Q empty 186
Implementing a Queue: using Array
• Circular queue [“wrap around”]
Solution 2: Make front point to the element preceding the front element in the queue (one
memory location will be wasted).
Solution 3: Make rear point to the element posterior the rear element in the queue (one memory
location will be wasted).
Make front point to the element preceding the front element in the queue (one memory
location will be wasted).
Example 5: illustration for solution 3
Solution 3: Make enqueue(Q, 30)
rear point to the
element posterior of The queue Q is full!!!
? ?
the rear element in What is the condition to
the queue (one determine that the queue
memory location will is full ?
be wasted).
Make front point to rear + 1 == front
the element
Q = (10, 20) Q = (10, 20) Q[rear] = 30; rear++;
preceding the
Q = (10, 20, 30)
front element in the
queue (onedequeue(Q)
dequeue(Q) dequeue(Q)
memory location
will be wasted).
? ? ?
The queue Q is empty!!!
What is the condition for an empty queue ?
rear == front
Make front point to the element preceding the front element in the queue (one memory
location will be wasted).
Example 6: The array used to represent queue has maxSize = 4
Initialize: front = rear = 0; illustration for solution 3
Queue Q is empty
? ?
Q[rear] = 2; Q[rear] = 3; Q[rear] = 5; Dequeue Q[front]
rear++; rear++; rear++; front++;
Q= (2) Q= (2, 3) Q= (2, 3, 5) Q= (3, 5)
? ? enqueue(Q, 30) ??
?
Q= (5, 10, 20) Dequeue Q[front] Dequeue Q[front] Dequeue Q[front]
front++; front++; front++;
=>front = 4 =maxSize Q empty
Q= (10, 20) => wrap around: front =0
Q= (20)
192
Application 1: recognizing palindromes
• A palindrome is a string that reads the same forward and backward.
Example: NOON, DEED, RADAR, MADAM
Able was I ere I saw Elba
• How to recognize a given string is a palindrome or not:
– Step 1: We will put all characters of the string into both a stack and a
queue.
– Step 2: Compare the contents of the stack and the queue character-by-
character to see if they would produce the same string of characters:
• If yes: the given string is a palindrome
• Otherwise: not palindrome
Example 1: Whether “RADAR” is a palindrome or not
Step 1: Put “RADAR” into Queue and Stack:
RADAR R R RADAR
ADAR A A ADAR
DAR D D DAR
AR A A AR
R R R R
empty empty empty empty