EE3490E - Fundamentals of
Embedded Programmings
Chapter 4: Data
Structures & Algorithms
Lecturer: Dr. Hoang Duc Chinh (Hoàng Đức Chính)
Department of Industrial Automation
School of Electrical Engineering
Email: [email protected] ©HDC 2021.1
Content
4.1. Introduction of data structures
4.2. Arrays and dynamic memory management
4.3. Vector structure
4.4. List structure
4.5. Sorting algorithms
4.6. Recursion
4.7. Bitwise operation
4.8. Event-driven programming
Chapter 4: Data Structures & Algorithms © HDC 2021.1 2
4.1 Introduction
Many real-life applications require complex data structures,
basic data type may not be sufficient to represent
Examples:
Student data: name, birthday, hometown, student identification (ID),
etc.
Transfer function: numerator, denominator polynomial
State space model: A, B, C, C matrices
Process (sensing) data: parameter name, measurement range, value,
unit, timestamp, accuracy, threshold, etc.
Graphic object: size, color, line weight, font, etc.
Data structure representation method: define a new data
type using structure (struct, class, union, etc.)
Chapter 4: Data Structures & Algorithms © HDC 2021.1 3
Problem: Represent a set of data
Most of the data belonging to an application are related to
each other it needs to represent a set with structure, e.g.:
Student list: data are in alphabet order
Generic model for a control system: include multiple components
interacting with each other
Process (sensing) data: a data set which carries value of an input at
discrete time, input values are related to output values
Graphic object: a window includes some graphic objects, a schematic
also include a number of graphic objects
In general, data in the same set has the same type, or at least
compatible types
Array is not always suitable
Chapter 4: Data Structures & Algorithms © HDC 2021.1 4
Problem: Manage (a set of) data
Any data set can be represented by properly utilizing
data structure and array
Algorithms (functions) process the data, in order to
manage it efficiently:
Add a new data record into a list, a table, a set, etc.
Delete a record from a list, a table, a set, etc.
Search a record in a list, a table, a set, etc. based on a criteria
Sort a list to meet a criteria
… thêm sửa, xoá, tìm kiếm, sắp xếp, cập nhật,
Chapter 4: Data Structures & Algorithms © HDC 2021.1 5
How to manage data efficiently
Minimize memory usage: “overhead” information is
insignificant when being compared with main data
Fast and convenient access: time taken to add, search or
delete data record should be short
Flexibility: number of data records should not be
limited, does not need to be known in advance, suitable
for small and large scale problem
Efficiency of data management depends on
Data structure class, và struct thường dùng để biểu
diễn một thông tin cụ thể
Algorithms used to add, search, sort, delete data
Chapter 4: Data Structures & Algorithms © HDC 2021.1 6
Common data structures
Array (extended meaning): set of data which can be
accessed by index
List: a data set contains elements each one links to another
and the set can be accessed in sequence đi kèm với interator để duyệt qua
các phtu trong list
Tree: a data set contains elements linked to each other and
can be accessed in sequence from the root
A tree of which each node has at most two children
tree khác (two
với list vì branches) islà là
node tiếp theo có thể
called binary tree nhiều node
còn với list chi có 1 node liền kề
node hiện tại
Map: a data set with sorted elements which can be accessed
fast by using “key”
Queue: a data set with elements sorted in sequence,
elements can be pushed into one end of the queue and
extracted from the other end of the queue, i.e. first-in first-
out list (FIFO)
Chapter 4: Data Structures & Algorithms © HDC 2021.1 7
Common data structures (cont.)
Set: data structure with elements sorted in a certain manner
but can be accessed effectively
Stack: data structure with elements sorted in sequence but
can be accessed from one end, i.e. last-in first-out (LIFO) or
first-in last-out (FILO)
Hash table: data structure with elements sorted with integer
tạo ra 1 key để truy cập phần tử của bảng
codes generated by a special function dữ liệu
Ring buffer (circular buffer): similar to queue that uses a
single, fixed-size buffer as if it were connected end-to-end.
If it is full, it will replace the first element with the new one.
In mathematical calculation and control system: vector,
matrix, polynomial, rational fraction, transfer function, etc.
Chapter 4: Data Structures & Algorithms © HDC 2021.1 8
4.2 Array and dynamic memory
allocation
Data can be represented by using array efficiently:
Read and write data quickly via index or address
Saving memory
Fixed size array: mảng cố định, định sẵn
char buffer[SIZE];
Student student_list[100];
Size of array must be known before compiling, users cannot
enter the number of elements, in another way, this number
cannot be a variable less flexible
Occupy a fixed slot in stack (if it is a local variable) or data
segment (if it is a global variable) inefficient and inflexible
use of memory
Chapter 4: Data Structures & Algorithms © HDC 2021.1 9
Dynamic array
Dynamic array is allocated in the memory as required, during the
run-time
#include <stdlib.h>/* C */
int n = 50;
...
float* p1= (float*) malloc(n*sizeof(float)); /* C */
double* p2= new double[n];// C++ dùng new với c++
A pointer is used to handle a dynamic array, the usage is similar
to a fixed array
p1[0] = 1.0f;
p2[0] = 2.0;
Once it is no longer in use free the allocated memory
free(p1); /* C */
delete [] p2;// C++ sau đó phải giải phóng bộ nhớ với delete
Chapter 4: Data Structures & Algorithms © HDC 2021.1 10
Memory allocation revision phân vùng mã máy:
chứa các câu lệnh
của ctr khi compile
4 memory segments: code segment, data segment,
read only, handle by
stack, heap compile
Code segment (sometime called text segment)
Stores constants and constant types which have been defined
Read-only
Handled by the compiler
Data segment
Used when the program is running
Contains global and static variables (initialized or uninitialized)
Readable and writable
Handled by the compiler
Chapter 4: Data Structures & Algorithms © HDC 2021.1 11
Memory allocation revision (cont.)
Stack vùng nhớ tạm thời cho các biến cục bộ
Temporary memory for local variables (automatic extent)
Data are in sequence based on the rule FILO data lưu lần lượt theo FILO
Data is pushed in when a function is called and it is freed (pop
out) when exiting the function data được đẩy vào khi gọi hàm và giải phóng sau khi
kết thúc hàm
Handled by the compiler
Heap (Free-store)
nhớ được cấp pháp động, cấp phát và giải phóng
Dynamic memory allocation vùng
bởi dev, dữ liệu được lưu trên heap đc cấp phát và giải
phóng bất kỳ thời điểm nào, cơ chế FIFO
Handled by developers (not the compiler)
Managed by standard functions (malloc(), calloc() or
realloc(), free()) in C or operators (new, delete) in
C++
Chapter 4: Data Structures & Algorithms © HDC 2021.1 12
Risks
Developer takes all the responsibility in managing the
dynamic memory
No support from the compiler in handling memory
May cause real-time issues
Storing data in stack is much faster than that in heap
Stack is managed by handling pointer, while using heap
requires internal memory management
It is better to use stack if possible
Chapter 4: Data Structures & Algorithms © HDC 2021.1 13
Allocating and free dynamic memory
C:
malloc(): input argument is the number of byte, return a non-type
pointer (void*) which contain the address of memory block
allocated (in heap), return 0 if failed
free(): input argument is a non-type pointer (void*), free
memory which has the address as provided
pointer_variable = new data_type[number_of_element];
C++:
Operator new[] allocates space for array with data type and number
of elements as definedconintrỏheap, return a pointer with data type, or
sẽ trỏ đến phần đầu tiên của mảng đc cấp phát
return 0 if failed kiểu dữ liệu của các phần tử trong mảng
số lượng phần tử trong mảng
Operator delete[] deallocate the space and its input argument is a
pointer
Operator new[] and delete[] are applicable to allocate and
deallocate space of variables, objects besides arrays
Chapter 4: Data Structures & Algorithms © HDC 2021.1 14
Dynamic memory handling
Functions which handle dynamic memory are provided
by standard library, these are the only method to access
the heap
Allocating memory
void *malloc(size_t size)
int *p = malloc(10 * sizeof(int));
int *p = (int *) malloc(10 * sizeof(int));
Chapter 4: Data Structures & Algorithms © HDC 2021.1 15
malloc()
If malloc() is called successfully, it returns a
pointer which points to the address of the allocated
memory
Other wise it returns NULL
In fact, computers have virtual memory which can be
considered unlimited
It is a good habit to verify the returning value of this
function
Chapter 4: Data Structures & Algorithms © HDC 2021.1 16
free()
free() release the memory segment allocated by
malloc()
The memory is freed and ready for subsequent usage
void free(void *p)
Don’t need type casting (cast) xxx * to void *
int *p = (int *) malloc(10 * sizeof(int));
...
free(p);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 17
calloc()
calloc() is similar to malloc() but the memory is
initialized with zero value (clear allocate)
Its interface is a bit different from malloc()
void *calloc(size_t n, size_t size)
int *p = calloc(10, sizeof(int));
Chapter 4: Data Structures & Algorithms © HDC 2021.1 18
realloc()
realloc() is used to change the memory allocated
by malloc(), calloc(), or realloc()
void *realloc(void *p, size_t size)
Multiple features
If p is NULL, it is the same as malloc()
If it is not done successfully, it returns NULL, the memory is
reserved
If size = 0, it is the same as free(), and returns NULL
Chapter 4: Data Structures & Algorithms © HDC 2021.1 19
More on realloc()
realloc() is used to increase or decrease dynamic
memory
If it increases, the existing elements are unchanged and
the newly added elements have no initial values
If it decreases, the existing elements are the unchanged
However, if the memory space is not sufficient,
realloc() will allocate new memory block and copy the
whole old memory block to the new one, then delete the
old one
This action disables the pointer which point to the old memory
block
Chapter 4: Data Structures & Algorithms © HDC 2021.1 20
Dynamic memory management
Handled by the developer
It includes
Pointer which points to the memory block
Allocating and free memory block
Size of the memory block
Errors may occur in most of the C applications.
Chapter 4: Data Structures & Algorithms © HDC 2021.1 21
Example of wrong usage
char *string_duplicate(char *s)
/* Dynamically allocate a copy of a
string. User must remember to free this
memory. */
{
/* +1 for ’\0’ */
char *p = malloc(strlen(s)+1);
return strcpy(p, s);
}
char *s1;
s1 = string_duplicate("this is a string");
...
free(s1);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 22
Common errors
The pointer points to an undefined value
“memory corruption”
The pointer points to NULL
Program halts
Free a pointer pointing to a memory block which is not
dynamic memory like stack, constant data
Not free memory after using (memory leak).
Access elements which are not in the range of the
allocated array
Chapter 4: Data Structures & Algorithms © HDC 2021.1 23
Good habbits
Each malloc() should be followed by free()
Avoid memory corruption memory leak
Always use malloc() and free() within a function
Always build create() function and then destroy() with
complex objects
Pointer must be declared when starting
Initialized as NULL or an existing value
NULL means “point to nowhere”
Pointer should be set as NULL after being freed
free(NULL) has no meaning (no effect)
Chapter 4: Data Structures & Algorithms © HDC 2021.1 24
Example: Matrix
A matrix with fixed size (3x3), size of matrix can be
defined at compiler time
The following example shows a matrix created as
required by user
double **matrix = create_matrix(2,3);
matrix[0][2] = 5.4;
...
destroy_matrix(matrix);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 25
Example: Matrix (cont.)
double **create_matrix1(int m, int n) {
double **p;
int i;
/* Allocate pointer array. */cấp phát bộ nhớ động cho mảng các con trỏ
p = (double **) malloc(m * sizeof(double*)); cấp phát mảng m con trỏ trỏ
đến từng dòng
/* Allocate rows. */ cấp phát bộ nhớ động cho từng hàng của ma trận
for (i = 0; i < m; ++i)
p[i] = (double *) malloc(n * sizeof(double));
return p; m x 1 dim array dùng con trỏ **p trỏ đến
mỗi con trỏ của mảng p quản lý mảng 1 chiều này
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 26
thực chất chỉ có 1 vde là khi ko đủ bộ nhớ => p là null => không tồn tại p[i] vì vậy khi cố gắng
truy cập con trỏ null => segmentation fault
Example: Matrix (cont.)
- hết bộ nhớ giữa chừng => một số con trỏ p[i] vx đc cấp phát thành công 1 số không do k đủ
bộ nhớ => vẫn trả về được con trỏ p vì vậy phải check mỗi lần gọi hàm malloc() để kiểm tra gía
trị trả về
double **create_matrix2(int m, int n) {
double **p; int i;
assert(m>0 && n>0); sử dụng assert để kiểm tra số hàng và cột là hợp lệ
p = (double **) malloc(m * sizeof(double*));
if (p == NULL) check xem p có null khi bắt đầu cấp phát mảng không
return p;
for (i = 0; i < m; ++i) { /* Allocate rows. */
p[i] = (double *) malloc(n * sizeof(double));
if (p[i] == NULL) check xem p có null khi đang trong quá trình cấp phát không
goto failed; /* Allocation failed */
}
return p;
failed:
for (−−i; i >= 0; −−i)
free(p[i]); /* delete allocated memory.*/
free(p);
return NULL;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 27
Example: Matrix (cont.)
/* Destroy an (m x n) matrix. Notice, the n
variable is not used, it is just there to
assist using the function. */
void destroy_matrix1(double **p, int m, int n) {
int i;
assert(m>0 && n>0);
for (i = 0; i < m; ++i)
free(p[i]);
free(p);
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 28
Example: Matrix (cont.)
phương pháp khác giảm số lần gọi hàm malloc và free
double **create_matrix(int m, int n) {
double **p, *q; nàyKhai báo hai con trỏ p và q. p sẽ là con trỏ chứa địa chỉ của mảng con trỏ (mỗi con trỏ
trỏ đến một hàng của ma trận), và q sẽ là con trỏ đến một mảng hai chiều được "
int i; flatten" (biến đổi thành mảng một chiều).
assert(m>0 && n>0);
p = (double **) malloc(m * sizeof(double*)); cấp pháp bộ nhớ cho p
đủ chỗ để lưu m con trỏ
if (p == NULL) kiểm tra cấp phát bộ nhớ có thành công k mỗi con trỏ trỏ đến 1 hàng
của ma trận
return p;
q = (double *) malloc(m * n * sizeof(double));cấp phát bộ nhớ cho
mảng 1 ch có kích
if (q == NULL) { thước mxn là kt của ma
trận sau khi flatten mảng
free(p); chứa các ptu của ma
return NULL; trận liên tiếp nhau
}
for (i = 0; i < m; ++i, q += n)loop để gán từng con trỏ trong mảng p cho từng đc
trong mảng a sao cho mỗi p[i] trỏ đến 1 hàng của ma
p[i] = q; trận q được tăng lên n sau mỗi vòng lặp để trỏ đến hàn
return p; tiếp theo
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 29
Example: Matrix (cont.)
void destroy_matrix(double **p)
/* Destroy a matrix. Notice, due to the
method by which this matrix was created,
the size of the matrix is not required.*/
{
free(p[0]);
free(p);
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 30
Extendable array
Extend array to improve the disadvantage of fixed-size
array in C
Size of the array is up to requirement. Elements are
added to the end of the array and indexes are updated
automatically
Disadvantages:
The array always occupies memory
Adding new element results in copying all the old ones to new
positions
Thus, a memory block should be allocated instead of
providing each element a memory slot
Chapter 4: Data Structures & Algorithms © HDC 2021.1 31
Extendable array
Method
Each memory block:
newsize = K * oldsize;
Usually, we choose K = 2
Demonstration of realloc() usage
Chapter 4: Data Structures & Algorithms © HDC 2021.1 32
Example: Extendable array
/* Vector access operations. */
int push_back(int item);
int pop_back(void);
int* get_element(int index);
/* Manual resizing operations. */
int get_size(void);
int set_size(int size);
int get_capacity(void);
int set_capacity(int size);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 33
Example: Extendable array (cont.)
#include "vector.h"
#include <stdlib.h>
#include <assert.h>
/* Private interface */
/* initial vector capacity */
static const int StartSize = 1;
/* geometric growth of vector capacity */
static const float GrowthRate = 1.5;
/* pointer to vector elements */
static int *data = NULL;
/* current size of vector */
static int vectorsize = 0;
/* current reserved memory for vector */
static int capacity = 0;
Chapter 4: Data Structures & Algorithms © HDC 2021.1 34
Example: Extendable array (cont.)
/* Add element to back of vector. Return index of new
element if successful, and -1 if fails. */
int push_back(int item) {
/* If out-of-space, allocate more. */
if (vectorsize == capacity) {
int newsize = (capacity == 0) ? StartSize :
(int)(capacity*GrowthRate + 1.0);
int *p = (int *)realloc(data, newsize*sizeof(int));
if (p == NULL)
return -1;
capacity = newsize; /* update data-structure */
data = p;
}
data[vectorsize] = item; /* We have enough room. */
return vectorsize++;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 35
Example: Extendable array (cont.)
/* Return element from back of vector, and remove
it
from the vector. */
int pop_back(void) {
assert(vectorsize > 0);
return data[−−vectorsize];
}
/* Return pointer to the element at the specified
index. */
int* get_element(int index) {
assert(index >= 0 && index < vectorsize);
return data + index;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 36
Example: Extendable array (cont.)
/* Manual size operations. */
int get_size(void) {return vectorsize;}
int get_capacity(void) {return capacity;}
/* Set vector size.
Return 0 if successful, -1 if fails. */
int set_size(int size) {
if (size > capacity) {
int *p = (int *) realloc(data, size*sizeof(int));
if (p == NULL)
return −1;
/* allocate succeeds, update data-structure */
capacity = size;
data = p;
}
vectorsize = size;
return 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 37
Example: Extendable array (cont.)
/* Shrink or grow allocated memory reserve for array.
A size of 0 deletes the array. Return 0 if
successful, -1 if fails. */
int set_capacity(int size) {
if (size != capacity) {
int *p = (int *) realloc(data, size*sizeof(int));
if (p == NULL && size > 0)
return −1;
capacity = size;
data = p;
}
if (size < vectorsize)
vectorsize = size;
return 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 38
Notes
A pointer is used to handle dynamic array, it is not a dynamic array
Allocate and deallocate memory space but not allocate and deallocate a
pointer
Free memory space only once
int* p;
p[0] = 1;// never do it không nên truy cập vào 1 vùng nhớ mà con trỏ chưa được cấp phát trước
đó
new(p);// access violation! không phủ hợp với việc cấp 1 vùng nhớ cho con trỏ p
p = new int[100];// OK cấp phát mảng 100 ptu int gán đc của vùng nhớ cho con trỏ p
p[0] = 1;// OK gán gtri 1 cho ptu dầu tiên của mảg đc trỏ bởi con trỏ p
int* p2=p;// OK gán p cho p2 => p và p2 đều trỏ đến cùng 1 vùng nhớ
delete[] p2;// OK giải phóng bộ nhớ được cấp phát cho mảng bởi con trỏ p2 <=> p
p[0] = 1;// access violation! truy cập vào vùng nhớ đã đc giải phóng
delete[] p;// very bad! vùng nhớ đã được giải phóng trước đó
p = new int[50];// OK, new array
...
Chapter 4: Data Structures & Algorithms © HDC 2021.1 39
Allocate dynamic memory for a single
variable
Purpose: Object can be created dynamically, while the program is
running, such as adding a new student to a list, drawing a new shape in
a schematic, inserting a component in a system, etc.
Syntax:
int* p = new int;
*p = 1;
p[0]= 2;// the same as above
p[1]= 1;// access violation!
int* p2 = new int(1);// with initialization
delete p;
delete p2;
Student* ps= new Student;
ps->code = 1000;
...
delete ps;
A single variable is not an array with one element
Chapter 4: Data Structures & Algorithms © HDC 2021.1 40
Summary on dynamic memory
Efficiency
Memory is allocated as much as it is required and when it is
required while the program is running
Memory is allocated within the free space of the computer
(heap), it depends on only computer memory
Allocated memory can be freed once it is not used anymore
Flexibility
Lifetime of the dynamically allocated memory may be longer
than the lifetime of the object allocated it
It is possible to call a function to allocated memory and another
function to deallocate it
The flexibility may cause memory leak
Chapter 4: Data Structures & Algorithms © HDC 2021.1 41
Example: using dynamic memory
Date* createDateList(int n) {
Date* p = new Date[n];
return p;
}
void main() {
int n;
cout << "Enter the number of your national holidays:";
cin >> n;
Date* date_list= createDateList(n);
for (int i=0; i < n; ++i) {
...
}
for (....) { cout << ....}
delete [] date_list;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 42
Output argument is a pointer
void createDateList(int n, Date* &p) {
p = new Date[n];
}
void main() {
int n;
cout << "Enter the number of your national holidays:";
cin >> n;
Date* date_list;
createDateList(n, date_list);
for (int i=0; i < n; ++i) {
...
}
for (....) { cout<< ....}
delete [] date_list;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 43
4.3 Vector structure
Problem: how to represent a mathematical vector in C/C++
biểu thị một vector toán học trong C/C++
Simple solution: normal dynamic array, but …
Inconvenient use: a user must call allocation and deallocation
functions himself; number of array dimensions need to be included
as well
Unsafe: a small mistake may cause a serious consequence
int n = 10;
double *v1,*v2, d;
v1 = (double*) malloc(n*sizeof(double));
v2 = (double*) malloc(n*sizeof(double));
d = scalarProd(v1,v2,n); // scalar_prod existed
d = v1 * v2;// OOPS!
v1.data[10] = 0;// OOPS!
free(v1);
free(v2);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 44
Vector structure definition
File name: vector.h #indef VECTOR_H
#define VECTOR_H
Data structure:
struct Vector {
double *data; con trỏ đến mảng lưu trữ các phần tử
int nelem; số lượng phần tử của vector
};
Declaration of its basic functions:
Vector createVector(int n, double init);
void destroyVector(Vector);
double getElem(Vector, int i);
void putElem(Vector, int i, double d);
Vector addVector(Vector, Vector);
Vector subVector(Vector, Vector);
double scalarProd(Vector, Vector);
...
#endif // VECTOR_H
Chapter 4: Data Structures & Algorithms © HDC 2021.1 45
Define basic functions
File name: vector.cpp #include <stdio.h>
#include <stdlib.h>
#include "vector.h"
Vector createVector(int n, double init) { hàm tạo vector nhận 2 tham số n và giá trị đầu init
Vector v; khai báo biến 'v' kiểu 'Vector'
v.nelem= n;gán số lượng vector (nelem) = n
v.data= (double*) malloc(n*sizeof(double));cấp phát bộ nhớ cho n phần tử kiểu
double, gán địa chỉ bộ nhớ đó cho con trỏ
while (n--) v.data[n] = init;gán giá trị init cho tất cả 'data' của vector
các giá trị của vector
return v; từ phần tử đầu tiến đến
cuối cùng
}
void destroyVector(Vector v) { giải phóng bộ nhớ đã cấp phát cho các phần tử cẩu vector
free(v.data);
}
double getElem(Vector v, int i) { hàm nhận 1 biến v dạng Vector và 1 biến int i
if (i < v.nelem&& i >= 0) return v.data[i];kiểm tra chỉ số i nằm trong khoảng hợp
lệ từ 0 đến nelem - 1, và trả về phần tử
return 0; ngược lại giá trị i không hợp lệ trả về 0 hoặc giả trị mặc định tại vị trí i
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 46
Define basic functions (cont.)
hàm nhận biến v dạng Vector, biến int i biểu thị vị trí
void putElem(Vector v, int i, double d) {phần tử muốn gán với biến d, và số double d
if (i >=0 && i < v.nelem) v.data[i] = d; kiểm điều kiện chỉ số i hợp lệ, gán giá trị của d cho
phần tử vị trí i
}
Vector addVector(Vector a, Vector b) {hàm nhận 2 biến a và b dạng vector
Vector c = {0,0}; khởi tạo 1 biến C dạng Vector rỗng ban đầu
if (a.nelem== b.nelem) { kiểm tra điều kiện số phần tử Vector a bằng Vector b
c = createVector(a.nelem,0.0);điều kiện thoả mãn khởi tạo Vector c với số phần tử bằng vector a và
các giá trị khởi tạo bằng 0.0
for (inti=0; i < a.nelem; ++i)dùng for loop từ i = 0 đến i = a.nelem -1,
c.data[i] = a.data[i] + b.data[i];công từng phần của vector a và b gán kết quả vào c
}
hàm tích vô hướng:
return c; trả về vector c double scalarProd(Vector a, Vector b) {
} double result = 0.0;
if (a.nelem == b.nelem) {
Vector subVector(Vector a, Vector b) { for (int i = 0; i < a.nelem; ++i)
result += a.data[i] * b.data[i];
Vector c = {0,0}; tương tự với hàm cộng vector
}
return result;
... if(a.nelem == b.nelem){
c = createVector(a.nelem, 0.0); }
return c; for (int i =0; i < a.nelem; ++i)
c.data[i] = a.data[i] - b.data[i];
} }
Chapter 4: Data Structures & Algorithms © HDC 2021.1 47
Usage
#include "vector.h"
void main() {
int n = 10; int n =2;
Vector a, b, c;
a = createVector(2, 0.0);
Vector a, b, c; putElem(a, 1, 2.1);
b = createVector(2, 0.0);
a = createVector(10,1.0); putElem(b, 0, 2.2);
c = addVector(a, b); // c = (2.2, 2.1)
b = createVector(10,2.0);
c = addVector(a,b);
//...
destroyVector(a);
destroyVector(b);
destroyVector(c);
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 48
4.4 List structure
Problem: create a structure to manage dynamic data
efficiently and flexibly, e.g.:
Email
Todo list
Graphical objects in a figure
Dynamic blocks in a simulation model (similar to SIMULINK)
Requirements:
The number of records/elements in the list changes frequently
Add or delete data operations should be fast and simple
Minimize memory usage
Chapter 4: Data Structures & Algorithms © HDC 2021.1 49
Using array?
Number of elements in an array is actually fixed. Memory
space must be known when being allocated, it cannot be
extended or shrunk
If memory space used is less than allocated one wasting
memory
If memory space is full and more elements need to be
added, it is required to reallocate memory space and copy
the whole existing data to the new array time consuming
if the array size is large
If an element which needs to be added/deleted is at the first
position or in the middle of the array, it is required to copy
and shift the rest of the data time consuming
Chapter 4: Data Structures & Algorithms © HDC 2021.1 50
4.4.1 Linked list
pHead
Item A Data A
Item B Data B
Item C Data C
Item X Data X
Item Y 0x00 Data Z
Chapter 4: Data Structures & Algorithms © HDC 2021.1 51
Linked list: Insert data
pHead pHead
pHead Data T Data A
Data A Data B
Data B Data T
Data C Data C
Data X Data X
0x00 Data Z 0x00 Data Z
At the beginning of the list In the middle of the list
Chapter 4: Data Structures & Algorithms © HDC 2021.1 52
Linked list: Delete data
pHead pHead
Data A Data A
Data B Data B
Data C Data C
Data X Data X
0x00 Data Z 0x00 Data Z
At the beginning of the list In the middle of the list
Chapter 4: Data Structures & Algorithms © HDC 2021.1 53
Summary
Advantages:
Flexible usage, allocating memory when needed and
deallocating after using
Add/delete element via pointer; time taken to perform these
task is constant, doesn’t depend on data length or position
Access data in sequence
Disadvantages:
Added element must be allocated dynamic memory
Deleting element requires respected memory space to be freed
If data type is not large, the overhead may be dominant
Searching data is based on linear methods which consume
more time
Chapter 4: Data Structures & Algorithms © HDC 2021.1 54
Example: mail box 1 email cần 2 phần chính: subject - content
#include <string>
using namespace std;
struct MessageItem { đầu tiên cần 1 struct 2 phần chính của email
string subject;
string content;
MessageItem* pNext; con trỏ linked list trỏ đến tin nhắn tiếp theo trong danh sách
};
struct MessageList { struct messagelist
MessageItem* pHead;trỏ đến tin nhắn đầu tiên trong danh sách
}; khi khởi tạo tin nhắn'l' con trỏ pHead trỏ đến
void initMessageList(MessageList& l);nullptr tức là danh sách ban đầu rỗng
void addMessage(MessageList&, const string& sj,
const string& ct);
bool removeMessageBySubject(MessageList&l,
const string& sj);
void removeAllMessages(MessageList&);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 55
Example: mail box (cont.)
#include "List.h"
void initMessageList(MessageList& l) { truyền tham chiếu đến MessageList, MessageList& l là
l.pHead = 0; tham số đầu vào của hàm
}
void addMessage(MessageList& l, const string& sj,
conststring& ct) {3 tham biến đc truyền tham chiếu
MessageItem* pItem = new MessageItem;dùng toán tử thực chất hàm có đầu ra chính mà
pItem->content = ct; gán ct cho content new cp đôg MessageList vì thay đổi nd của đầu vào
pItem->subject = sj; gán si cho subject 1 node này
pItem->pNext = l.pHead;gán pNext of pItem messageitem mới
l.pHead = pItem; trỏ đến nút đầu tiên và con trỏ pItem sẽ trỏ đến nút này
} đặt pItem làm nút đầu tiên trg ds hiên tại(l.pHead)
trg ds
void removeAllMessages(MessageList& l) {
MessageItem *pItem = l.pHead;
while (pItem != 0) {
MessageItem* pItemNext = pItem->pNext;
delete pItem;
pItem = pItemNext;
}
l.pHead = 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 56
Example: mail box (cont.)
bool removeMessageBySubject(MessageList& l,
conststring& sj) {
MessageItem* pItem = l.pHead;
MessageItem* pItemBefore;
while (pItem != 0 && pItem->subject != sj) {
pItemBefore = pItem;
pItem = pItem->pNext;
}
if (pItem != 0) {
if (pItem == l.pHead)
l.pHead = 0;
else
pItemBefore->pNext = pItem->pNext;
delete pItem;
}
return pItem != 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 57
Example: mail box usage (cont.)
#include <iostream>
#include "list.h"
using namespace std;
void main() {
MessageList myMailBox;
initMessageList(myMailBox);
addMessage(myMailBox,"Hi","Welcome, my friend!");
addMessage(myMailBox,"Test","Test my mailbox");
addMessage(myMailBox,"Lecture Notes","Programming Techniques");
removeMessageBySubject(myMailBox,"Test");
MessageItem* pItem = myMailBox.pHead;
while (pItem != 0) {
cout << pItem->subject << ":" << pItem->content << '\n';
pItem = pItem->pNext;
}
char c;
cin >> c;
removeAllMessages(myMailBox);
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 58
Homework
Create a linked-list consisting of public holidays of a
year and description of each day (as string), so that
A new public holiday can be added to the beginning of the list
Search for the description of the day (input argument is a date
including day and month)
Delete a public holiday at the beginning of the list
Delete a public holiday in the middle of the list (input argument
is a date including day and month)
Clear the whole list
Write a program to demonstrate the usage of the above
list
Chapter 4: Data Structures & Algorithms © HDC 2021.1 59
4.4.2 More on lists
Double Link List
Stack
Circular Buffer
Hash table
Chapter 4: Data Structures & Algorithms © HDC 2021.1 60
Double Link 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.
struct List {
int item;
struct List *next;
struct List *prev;
};
Advantages:
A DLL can be traversed in both forward and backward direction
The delete operation in DLL is more efficient
We can quickly insert a new node before a given node
Chapter 4: Data Structures & Algorithms © HDC 2021.1 61
Double Link List example
struct List *insert_after(struct List *node, int item)
{
/* Allocate memory for new node. */
struct List *newnode = (struct List *)
malloc(sizeof(struct List));
if (newnode == NULL)
return NULL; /* allocation failed */
/* If list is not empty, splice new node into list. */
if (node) {
newnode−>next = node−>next;
node−>next = newnode;
}
else
newnode−>next = NULL;
newnode−>item = item;
return newnode;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 62
typedef and Structure
typedef is similar to #define but it is a C keyword
It enables to create a new data type with a new name
typedef int Length;
Length len, maxlen;
Length lengths[50];
typedef simplifies the use of structure in C (but not required
in C++)
typedef struct Point {
int x;
int y;
} Point;
Point pt1, pt2;
Chapter 4: Data Structures & Algorithms © HDC 2021.1 63
typedef and Link List
Example:
typedef struct list_t List;
struct list_t {
int item;
List *next;
};
Main reasons to use typedef
Simplify the complex name
Example of function pointer
typedef int (*PFI)(char *, char *);
PFI pfarray[10];
Self-defined data type make the program easier to read, e.g.: Length
is more intelligible than int).
Chapter 4: Data Structures & Algorithms © HDC 2021.1 64
Usage of typedef
typedef enable to hide the incompatible codes amongst
different microprocessors
E.g.: in a 32 bit computer, we can write:
typedef short INT16;
typedef int INT32;
In a 16 bit computer, they can be written as:
typedef int INT16;
typedef long INT32;
Chapter 4: Data Structures & Algorithms © HDC 2021.1 65
Usage of typedef
typedef enables to write the program compatible
with different data types
typedef int ValueType;
typedef struct List {
ValueType item;
struct List *next;
} List;
List *insert_back(List *node, ValueType item);
List *insert_after(List *node, ValueType item);
This is the most simple form of generic programming.
Chapter 4: Data Structures & Algorithms © HDC 2021.1 66
Stack
Basic Operations
Initializing, using it and then de-initializing the stack
Two primary operations:
push() − Pushing (storing) an element on the stack
pop() − Removing (accessing) an element from the stack
Chapter 4: Data Structures & Algorithms © HDC 2021.1 67
Stack
typedef struct Stack {
double buffer[MAXSIZE]; /* Stack buffer. */
int count; /* Number of elements in stack. */
} Stack;
void push(Stack *s, double item) {
s->buffer[s->count++] = item;
}
double pop(Stack *s) {
return s->buffer[--s->count];
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 68
Circular Buffer
An array with pre-defined size. It is also called “Ring
Buffer”
It returns to the beginning position once it reaches the
last element
It is also a queue but first element will be replaced by a
new one when the queue is full
It is usually used in a real-time control system in which
many processes interacts with the object
Chapter 4: Data Structures & Algorithms © HDC 2021.1 69
Circular Buffer
1
1 2 3
6 7 8 9 3 4 5
6 7 8 9 A B 5
Chapter 4: Data Structures & Algorithms © HDC 2021.1 70
Circular Buffer
Chapter 4: Data Structures & Algorithms © HDC 2021.1 71
Software FIFO Implementation
(UART1 Receive)
Chapter 4: Data Structures & Algorithms © HDC 2021.1 72
Software FIFO Implementation
(UART1 Receive)
Chapter 4: Data Structures & Algorithms © HDC 2021.1 73
Software FIFO Implementation
(UART1 Receive)
Chapter 4: Data Structures & Algorithms © HDC 2021.1 74
Software FIFO Implementation
(UART1 Receive)
Chapter 4: Data Structures & Algorithms © HDC 2021.1 75
Circular Buffer
typedef struct CircBuf_t {
ValueType *array; /* Pointer to array of items */
int size; /* Maximum number of items in buffer */
int nelems; /* Current number of items in buffer */
int front; /* Index to front of buffer */
int back; /* Index to back of buffer */
} CircBuf;
Chapter 4: Data Structures & Algorithms © HDC 2021.1 76
Example
typedef double ValueType;
typedef struct CircBuf_t CircBuf;
/* create-destroy buffer */
CircBuf *create_buffer(int size);
void destroy_buffer(CircBuf *cb);
/* add-remove elements */
int add_item(CircBuf *cb, const ValueType *item);
int get_item(CircBuf *cb, ValueType *item);
/* query state */
int get_nitems(const CircBuf *cb);
int get_size(const CircBuf *cb);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 77
Example
int add_item(CircBuf *cb, const ValueType *item) {
/* Add a new element to front of buffer.
Returns 0 for success, and -1 if buffer is full. */
if (cb−>nelems == cb−>size)
return −1;
cb−>array[cb−>front] = *item;
if (++cb−>front == cb−>size) /* wrap around */
cb−>front = 0;
++cb−>nelems;
return 0;
}
int get_item(CircBuf *cb, ValueType *item) {
/* Remove element from back of buffer, and assign it to *item.
Returns 0 for success, and -1 if buffer is empty. */
if (cb−>nelems == 0)
return −1;
−−cb−>nelems;
*item = cb−>array[cb−>back];
if (++cb−>back == cb−>size) /* wrap around */
cb−>back = 0;
return 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 78
Hash Table
Data is stored in an array format, where each data value
has its own unique index value
Use for fast looking up if we know the index of desired
data
The most common implementation is a data array
combined with link-list
Basic Operations are Search, Insert, Delete
Chapter 4: Data Structures & Algorithms © HDC 2021.1 79
Example
typedef struct Dictionary_t Dictionary;
Dictionary *create_table(void);
void destroy_table(Dictionary *);
int add_word(Dictionary *, const char *key, const char
*defn);
char *find_word(const Dictionary *, const char *key);
void delete_word(Dictionary *, const char *key);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 80
Example
#define HASHSIZE 101
struct Nlist {
char *word; /* search word */
char *defn; /* word definition */
struct Nlist *next; /* pointer to next entry in chain */
};
struct Dictionary t {
/* table is an array of pointers to entries */
struct Nlist *table[HASHSIZE];
};
static unsigned hash_function(const char *str) {
/* Hashing function converts a string to an index within hash table. */
const int HashValue = 31;
unsigned h;
for (h = 0; *str != ’\0’; ++str)
h = *str + HashValue * h;
return h % HASHSIZE;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 81
Example
int add_word(Dictionary *dict, const char *key, const char *defn) {
/* Add new word to table. Replaces old definition if word already exists.
Return 0 if successful, and -1 is fails. */
unsigned i = hash function(key); /* get table index */
struct Nlist *pnode = dict−>table[i];
while (pnode && strcmp(pnode−>word, key) != 0) /* search chain */
pnode = pnode−>next;
if (pnode) { /* match found, replace definition */
char *str = allocate string(defn);
if (str == NULL) /* allocation fails, return fail and keep old defn */
return −1;
free(pnode−>defn);
pnode−>defn = str;
}
else { /* no match, add new entry to head of chain */
pnode = makenode(key, defn);
if (pnode == NULL)
return −1;
pnode−>next = dict−>table[i];
dict−>table[i] = pnode;
}
return 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 82
Example
char *find_word(const Dictionary *dict, const char *key) {
/* Find definition for keyword.
Return NULL if key not found. */
unsigned i = hash function(key); /* get table index */
struct Nlist *pnode = dict−>table[i];
while (pnode && strcmp(pnode−>word, key) != 0)
pnode = pnode−>next; /* search index chain */
if (pnode) /* match found */
return pnode−>defn;
return NULL;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 83
4.5 Sorting algorithms
Objective: rearrange a given array or list elements
according to a comparison operator on the elements.
The comparison operator is used to decide the new
order of element in the respective data structure.
Ascending order: from the smallest to the largest number
Descending order: from the largest number to smallest number
Problem statement:
Input: given an array a of size n: a[0], a[1], …, a[n-1]
Output: a permutation (reordering) of a (a’[0], a’[1], …, a’[n-
1] in such a way that:
• a’[0] <= a’[1] <= ... <= a’[n-1]
Chapter 4: Data Structures & Algorithms © HDC 2021.1 84
Sorting algorithms
A number of applications in reality:
Commercial computing. Government organizations, financial institutions, and
commercial enterprises organize much of this information by sorting it
Search for information. Keeping data in sorted order makes it possible to
efficiently search through it. E.g.: sorting the number of access of websites
using a search engine like Google
String processing algorithms are often based on sorting
As fundamental algorithm to solve more complex problems such as numerical
computations, operations research, optimization, etc.
Early sorting algorithms were proposed in 1950s such as bubble sort,
merge sort, quick sort, etc.; new ones are still being invented
References:
Cormen, Thomas H., and Thomas H. Cormen. 2001. Introduction to algorithms.
Cambridge, Mass: MIT Press.
Robert Sedgewick and Kevin Wayne. 2011. Algorithms (4th. ed.). Addison-
Wesley Professional.
2 algorithms will be introduced: selection sort and merge sort
Chapter 4: Data Structures & Algorithms © HDC 2021.1 85
Sorting algorithms
Input data
0 n-1
a Unsorted
Desired output:
Data has been sorted in certain order
0 n-1
a Sorted array: a[0]<=a[1]<=…<=a[n-1]
Chapter 4: Data Structures & Algorithms © HDC 2021.1 86
4.5.1 Selection sort
Initial state
0 n-1
The smallest numbers The remaining data,
a which have been sorted unsorted
Steps:
Find the smallest number in a[k..n-1]
Swap a[k] and the smallest number we found above
0 n-1
The smallest numbers
a which have been sorted
a[k] x
Chapter 4: Data Structures & Algorithms © HDC 2021.1 87
Find the smallest number
/* Yield location of smallest element
in a[k..n-1] */
/* Assumption: k < n */
/* Returns index of smallest, does not return the
smallest value itself */
int min_loc (int a[], int k, int n) {
/* a[pos] is smallest element found so far */
int j, pos;
pos = k;
for (j = k + 1; j < n; j = j + 1)
if (a[j] < a[pos])
pos = j;
return pos;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 88
Selection sort
/* Sort a[0..n-1] in non-decreasing
order (rearrange
elements in a so that
a[0]<=a[1]<=…<=a[n-1] ) */
int sel_sort (int a[], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 89
Example
Chapter 4: Data Structures & Algorithms © HDC 2021.1 90
Example
Chapter 4: Data Structures & Algorithms © HDC 2021.1 91
Example
Chapter 4: Data Structures & Algorithms © HDC 2021.1 92
Algorithm evaluation
How many iterations do we need to sort n numbers?
Before swapping position, it is needed to check through the
whole unsorted part of the array
The length of unsorted part in the initial array is n
The algorithm repeats n iterations of checking/swapping
Total of steps is proportional to
Conclusion: selection sort is pretty slow with large
arrays
Chapter 4: Data Structures & Algorithms © HDC 2021.1 93
Better algorithm?
Algorithms with complexity of nlogn
Merge sort
Quick sort
When array size grows, time taken to execute
algorithms with complexity of n2 is much higher than
that with nlogn complexity
Chapter 4: Data Structures & Algorithms © HDC 2021.1 94
4.5.2 Merge sort
Basic idea:
Starting with sorted arrays: pointers are at the beginning of the
arrays
Use the pointer to mix the position of each pair of elements
within sorted arrays to make a bigger array with sorted
elements
After merging 2 arrays, we get the desired array eventually
The basic operator is merging
Chapter 4: Data Structures & Algorithms © HDC 2021.1 95
Merge sort
Chapter 4: Data Structures & Algorithms © HDC 2021.1 96
Merge sort
Chapter 4: Data Structures & Algorithms © HDC 2021.1 97
Merge sort
Chapter 4: Data Structures & Algorithms © HDC 2021.1 98
Merge sort
We need n comparisons and copying data n times, thus
the workload is proportional to n
However, this is not yet a sorting algorithm
So how to do?
Chapter 4: Data Structures & Algorithms © HDC 2021.1 99
Merge sort implementation
It is needed to know the position of pointers to merge
the respected arrays together
At the starting point, each element in the array is a
pointer
Merge sort:
Merge each pair of 1-element arrays to be a 2 element array
Merge each pair of 2-element arrays to be a 4 element array
Merge each pair of 4-element arrays to be a 8 element array
And so on until completing
Chapter 4: Data Structures & Algorithms © HDC 2021.1 100
Example
Chapter 4: Data Structures & Algorithms © HDC 2021.1 101
Example
Sorting task is done
Each merging step take a duration proportional to n
How many time do we merge? It is 3 in this example
In general, we need log2n merging steps
When n =8:
Total time consumed is proportional to nlog2n (or
nlogn).
Chapter 4: Data Structures & Algorithms © HDC 2021.1 102
In short
Chapter 4: Data Structures & Algorithms © HDC 2021.1 103
Any approach performed better
than nlogn?
In general, the answer is NO
However, in some special cases, we may do better
E.g.: sorting exam papers based on the scores put the
papers into one of 10 piles with respect to their scores
required time is proportional to n.
The performance of the algorithm can be evaluated via
mathematical calculation without using computer
This specific area in mathematics is approximation theory.
There are a lot of interesting topics to be solved
E.g.: The P versus NP problem: Whether every problem
whose solution can be quickly verified can also be solved
quickly
Chapter 4: Data Structures & Algorithms © HDC 2021.1 104
Efficiency
The resources can be saved
It is usually measured by execution duration and
memory space required
A lot of details in programming has little or no effect on
efficiency
It is often achieved by selecting the right algorithm
and/or data structure
Chapter 4: Data Structures & Algorithms © HDC 2021.1 105
4.5.3 Structure and Array
A structure represent a simple data record, computer
program processes a set of data records
E.g.: student record, staff record, customer record, etc.
In each case, there are a number of variables, thus it
would require to use an array of structure to store data
Chapter 4: Data Structures & Algorithms © HDC 2021.1 106
Example
#define MAX_NAME 40 typedef struct {
typedef struct { int hours, minutes;
char name [MAX_NAME+1]; double seconds;
int id; } time;
double score;
} student_record; typedef struct {
double x, y ;
} point;
Chapter 4: Data Structures & Algorithms © HDC 2021.1 107
Array of structure
Each statement below shows the declaration of an array
in which each element is a structure
point corner_points[10];
time meeting_times[MAX_MEETINGS];
student_record tdh_34[MAX_STUDENTS];
The fields of structure are accessed via the array
element and the field names
cse_142[i].name
corner_points[j+1].x
meeting_times[4].hours
Chapter 4: Data Structures & Algorithms © HDC 2021.1 108
Array of structure
point pentagon[5];
Array of structure pentagon
x
y
pentagon[1] – structure
x
y
x
y pentagon[4].x – a real number
x
y
x
y
Chapter 4: Data Structures & Algorithms © HDC 2021.1 109
Array of structure
student_record class[MAX_STUDENTS];
...
for (i = 0; i < nstudents; i = i + 1)
{
scanf(“%d %d”, &class[i].hw, &class[i].exams);
class[i].grade =
(double) (class[i].hw+class[i].exams) / 50.0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 110
Array element as argument
void draw_line (point p1, point p2) {.....}
...
point pentagon[5];
...
for (i = 0; i < 4; i = i + 1) {
draw_line(pentagon[i], pentagon[i+1]);
}
draw_line(pentagon[4], pentagon[0]);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 111
Revision on passing a value
A structure variable is passed with its value
All the fields of the variable are copied to initialize the
argument
point midpoint (point a; point b) {...}
int main (void) {
point p1, p2, m; /* declare 3 points */
...
m = midpoint(p1, p2);
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 112
Revision on passing an array
An array of element is an array
When the array is used as a parameter in function call,
it needs to be passed by using reference
The reference is actually an alias of the input parameter
int avg (student_rec class_db[MAX_N]) {...}
int main (void) {
student_rec ktlt_k50[MAX_N];
int average;
....
average = avg(ktlt_k50); /*by reference*/
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 113
Sorting an array of structure
David Kathryn Sarah Phil Casey
920915 901028 900317 920914 910607
2.9 4.0 3.9 2.8 3.6
Phil David Casey Sarah Kathryn
920914 920915 910607 900317 901028
2.8 2.9 3.6 3.9 4.0
typedef struct {
char name[MAX_NAME + 1];
int id;
double score;
} StudentRecord;
Chapter 4: Data Structures & Algorithms © HDC 2021.1 114
Revision of selection sort
int min_loc (int a[ ], int k, int n) {
int j, pos; pos = k;
for (j = k + 1; j < n; j = j + 1)
if (a[j] < a[pos])
pos = j;
return pos;
}
void swap (int *x, int *y);
void sel_sort (int a[ ], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 115
Sorting an array of structure
Initially, it is required to identify the field to sort by
E.g.: sort by scores
Change the data type of the array to StudentRecord
Rewrite the code for comparison in min_loc function
Write swap function for StudentRecord
Chapter 4: Data Structures & Algorithms © HDC 2021.1 116
Sorting an array of structure
int min_loc (StudentRecord a[ ], int k, int n) {
int j, pos; pos = k;
for (j = k + 1; j < n; j = j + 1)
if (a[j].score < a[pos].score)
pos = j;
return pos;
}
void swap (StudentRecord *x, StudentRecord *y);
void sel_sort (StudentRecord a[ ], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 117
Sorting by alphabetic order
David Kathryn Sarah Phil Casey
920915 901028 900317 920914 910607
2.9 4.0 3.9 2.8 3.6
Casey David Kathryn Phil Sarah
910607 920915 901028 920914 900317
3.6 2.9 4.0 2.8 3.9
typedef struct {
char name[MAX_NAME + 1];
int id;
double score;
} StudentRecord;
It is required to write a function for comparing two strings
Chapter 4: Data Structures & Algorithms © HDC 2021.1 118
String compare revision
“Alice” < “Bob”
“Dave” < “David”
“Rob” < “Robert”
#include <string.h>
int strcmp(char str1[ ], char str2[ ]);
Returning value is
A negative number if str1 < str2
Zero if str1 = str2
A positive number if str1 > str2
Chapter 4: Data Structures & Algorithms © HDC 2021.1 119
Sorting by alphabetic order
int min_loc (StudentRecord a[ ], int k, int n) {
int j, pos; pos = k;
for (j = k + 1; j < n; j = j + 1)
if (0 > strcmp(a[j].name, a[pos].name))
pos = j;
return pos;
}
void swap (StudentRecord *x, StudentRecord *y);
void sel_sort (StudentRecord a[ ], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 120
Thinking in data structure
If we want to store information of a song in a computer
What kind of information needs to be stored?
How to organize the information?
How to implement in C?
And if
We need information of a CD
Or information of a set of CDs
Chapter 4: Data Structures & Algorithms © HDC 2021.1 121
Insertion sort
/* sort student records a[0..size-1] in */
/* ascending order by score */
void sort (student_record a[ ], int size)
{
int j;
for (j = 1; j < size; j = j + 1)
insert(a, j);
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 122
Insertion sort
/* given that a[0..j-1] is sorted, move a[j]
to the correct location so that that a[0..j]
is sorted by score */
void insert (student_record a[ ], int j) {
int i;
student_record temp;
temp = a[j];
for (i = j; i > 0 &&
a[i-1].score > temp.score; i = i-1) {
a[i] = a[i-1];
}
a[i] = temp;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 123
Insertion sort
/* given that a[0..j-1] is sorted, move a[j] to
the correct location so that that a[0..j] is
sorted by score */
void insert (student_record a[ ], int j) {
int i;
student_record temp;
temp = a[j];
for (i = j; i > 0 &&
strcmp(a[i-1].name, temp.name) > 0;
i = i-1) {
a[i] = a[i-1];
}
a[i] = temp;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 124
4.6. Recursion
It’s possible for a function to call itself. This is termed
recursion
int foo(int x) {
...
y = foo(...);
...
}
Questions:
How recursion works?
• To be discussed
Why do we need recursive functions?
• We will see the motivations
Chapter 4: Data Structures & Algorithms © HDC 2021.1 125
4.6.1 Factorial function
Function name
Parameter/
int factorial(int n) Argument
{
int product, i;
product = 1; Local variables
Type and for (i = n; i > 1; i = i - 1)
returning {
value product = product * i; 0! = 1
} 1! = 1
2! = 1 * 2
return (product);
3! = 1 * 2 * 3
} ...
Chapter 4: Data Structures & Algorithms © HDC 2021.1 126
Factorial function using recursion
The definition of factorial function is recursive itself
0! = 1! = 1; for n > 1, n! = n(n-1)!
int factorial(int n) 0! is 1
{ 1! is 1
int t; n! is n * (n-1)!, for n>1
if (n <= 1)
E.g.: 3! = 3 * 2!
t = 1;
= 3 * 2 * 1!
else =3*2*1
t = n * factorial(n - 1);
return t;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 127
Function revision
It does not take much effort to trace the recursive
function if we remember the background of functions:
Arguments and variables declared in a functions is the local
variable of that function
• They are allocated memory space once the function is called
• The allocated memory is free when exiting the function
Arguments are initialized by copying values of the passing
variables in function call
Chapter 4: Data Structures & Algorithms © HDC 2021.1 128
Factorial function
factorial(4) =
4 * factorial(3) =
4 * 3 * factorial(2) =
4 * 3 * 2 * factorial(1) =
4 * 3 * 2 * 1 = 24
Chapter 4: Data Structures & Algorithms © HDC 2021.1 129
‘y’ or ‘n’ question
char yes_or_no(void)
{
char answer = ‘X’;
while(answer != ‘y’ && answer != ‘n’)
{
printf (“Please enter ‘y’ or ‘n’:”);
scanf (“%c”, &answer);
}
return answer;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 130
Implementation without loop
char yes_or_no(void)
{
char answer;
printf (“Please enter ‘y’ or ‘n’:”);
scanf (“%c”, &answer);
if(answer != ‘y’ && answer != ‘n’)
answer = yes_or_no( );
return answer;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 131
Loop and Recursion
Any algorithm using loop can be replaced by recursion
and vice versa
In some languages, recursion is the only choice
Some algorithms are represented as recursion naturally:
It is not effective if employing recursive function for simple
algorithms/application
Chapter 4: Data Structures & Algorithms © HDC 2021.1 132
When to use recursion
Some cases, the problem can be solved by transforming
to simple cases
Continuously carrying out transformation until a simple
operation which is not recursive is obtained
Chapter 4: Data Structures & Algorithms © HDC 2021.1 133
4.6.2 Towers of Hanoi
Tower of Hanoi is a mathematical puzzle where we
have 3 rods (towers) and n disks.
The objective is to move all the disks to another rod,
Rules to be followed:
1) Only one disk can be moved at a time.
2) Only the "top" disk can be removed
3) No disk may be placed on top of a smaller disk.
1
2
3
A B C
Chapter 4: Data Structures & Algorithms © HDC 2021.1 134
Towers of Hanoi
Following is an animated representation of solving a Tower
of Hanoi puzzle with three disks.
Tower of Hanoi puzzle with n disks can be solved in
minimum 2n−1 steps. This presentation shows that a puzzle
with 3 disks has taken 23 - 1 = 7 steps.
Assume that we have 64 disks, if time taken to move 1 disk
is t [seconds]
Total required time is:
Let :
1 1
2 2 1
13 31 2
A B C
Chapter 4: Data Structures & Algorithms © HDC 2021.1 135
Towers of Hanoi
Move n disks from tower X
to tower Z by using Y as an
intermediate tower
(1) Move (n-1) disks from tower X to
tower Y by using Z as an intermediate
tower as the top disks are smaller
(2) Move disk n (the largest) from X to
Z
(3) Repeat the procedure for the
remaining n-1 disks in tower Y to Z
with the intermediate tower X
Chapter 4: Data Structures & Algorithms © HDC 2021.1 136
4.6.3 Quick sort - Example
Sorting the following integer array
40 20 10 80 100 50 7 30 60
Chapter 4: Data Structures & Algorithms © HDC 2021.1 137
Select the ‘pivot’ element
Choose the element to be compared with: e.g. select the
first element
40 20 10 80 60 50 7 30 100
Chapter 4: Data Structures & Algorithms © HDC 2021.1 138
Divide the array into smaller ones
Given number of elements, dividing the array into 2:
The first array includes elements the pivot one
The other include elements the pivot one
7 20 10 30 40 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]
<= data[pivot] > data[pivot]
Chapter 4: Data Structures & Algorithms © HDC 2021.1 139
Recursion: Quicksort Sub-arrays
7 20 10 30 40 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]
<= data[pivot] > data[pivot]
Chapter 4: Data Structures & Algorithms © HDC 2021.1 140
Quicksort Analysis
Assume that keys are random, uniformly distributed.
What is best case running time?
Recursion:
1. Partition splits array in two sub-arrays of size n/2
2. Quicksort each sub-array
Depth of recursion tree? O(log2n)
Number of accesses in partition? O(n)
7 20 10 30 7 20 10 7 10 20
Chapter 4: Data Structures & Algorithms © HDC 2021.1 141
Quicksort Analysis
Assume that all elements are randomly distributed
Shortest duration: O(n log2n)
How about the worst case scenario?
Chapter 4: Data Structures & Algorithms © HDC 2021.1 142
Quicksort: the worst case
Assumed that all the elements are distributed
ascendingly
pivot_index = 0 2 4 10 12 13 50 57 63 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]
Chapter 4: Data Structures & Algorithms © HDC 2021.1 143
Another approach to choose the
pivot
Select the mean of 3 elements in the array
data[0], data[n/2], and data[n-1].
Use this mean value as the pivot
Chapter 4: Data Structures & Algorithms © HDC 2021.1 144
Optimizing Quicksort
Find the pivot element
If the size is smaller or equal to 3:
One element: do nothing
If there is 2 elements: if(data[first] > data[second]) swap them
If there is 3 elements: homework
Chapter 4: Data Structures & Algorithms © HDC 2021.1 145
Micromouse
Chapter 4: Data Structures & Algorithms © HDC 2021.1 146
Example
/* ‘F’ means finished! 0
‘X’ means blocked 1
‘ ’ means ok to 2
move */ 3
char maze[MAXX][MAXY]; y 4
/* start in yellow */ 5
6
int x =0, y=0;
7
Unless it finds the obstacle, 8
robot can move up, down, F
left, right 9
0 1 2 3 4 5 6 7
Problem: does a route to the x
destination exist?
Chapter 4: Data Structures & Algorithms © HDC 2021.1 147
Simple cases
Assume that robot is at 0
the position (x,y) 1
if maze[x][y] == ‘F’ 2
• then “yes!” 3
if no place to go 4
y
• then “no!” 5
6
7
8
9 a F
0 1 2 3 4 5 6 7
x
Chapter 4: Data Structures & Algorithms © HDC 2021.1 148
Make it simpler
0 0
It is not necessary to go 1 1
through a cell twice 2 2
3 3
4 4 ...
0 5 5
1 6 6
2 7 7
3 8 8
9 F 9 F
4 or
5 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
6
7 0
8 1
9 F 2
0 1 2 3 4 5 6 7 3
4
5
...
6
7
8
9 F
Chapter 4: Data Structures & Algorithms 0 1 2 3 4 5 6 7© HDC 2021.1 149
Supporting function
/* Returns true if <x,y> is a legal move
given the maze, otherwise returns false */
int legal_mv (char m[MAXX ][MAXY], int x, int y)
{
return(x >= 0 && x <= MAXX && y >= 0 &&
y <= MAXY && m[x][y] != ‘X’);
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 150
An elegant solution
/* Returns true if there is a path from <x,y> to an
element of maze containing ‘F’ otherwise returns
false */
int is_path (char m[MAXX][MAXY ], int x, int y) {
if (m [x][y] == ‘F’)
return(TRUE);
else {
m[x][y] = ‘X’;
return((legal_mv(m,x+1,y) && is_path(m,x+1,y)) ||
(legal_mv(m,x-1,y) && is_path(m,x-1,y)) ||
(legal_mv(m,x,y-1) && is_path(m,x,y-1)) ||
(legal_mv(m,x,y+1) && is_path(m,x,y+1)))
}
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 151
Example
is_path(maze, 7, 8) x
0
1
2
3
4
5
6
7
8
9 F
0 1 2 3 4 5 6 7
Chapter 4: Data Structures & Algorithms © HDC 2021.1 152
Example
is_path(maze, 7, 8) x
is_path(maze, 7, 8)
0
1
2
3
4
5
6
7
8
9 F
0 1 2 3 4 5 6 7
Chapter 4: Data Structures & Algorithms © HDC 2021.1 153
Example
is_path(maze, 7, 8) x
is_path(maze, 7, 8)
0
1
2
3
4
is_path(maze, 7, 8) 5
6
7
8
9 F
0 1 2 3 4 5 6 7
Chapter 4: Data Structures & Algorithms © HDC 2021.1 154
Recursion summary
Recursion is one of the programming techniques
Its principle is based on the manner that a function is called and
local variables are used in C
Every time, a function is called, everything has its new copy
It is also an approach to solve problems
It would take time and effort to master this
technique
Recursion is a natural way to work with a
number of data structures
Chapter 4: Data Structures & Algorithms © HDC 2021.1 155
4.7. Bitwise operation
C provides operators
To change each bit individually
To perform operations which are usually available in
Assembler only
The C program with bitwise operation can run in
different OS, however most of these kind of programs
are written to work in specific hardware
Chapter 4: Data Structures & Algorithms © HDC 2021.1 156
Negative numbers
Bit MSB (most significant bit) is 1, the number is
negative
Two’s complement to represent negative number, e.g.:
-22425 as a binary number: 1010 1000 0110 0111
The algorithm:
Subtract 1 from the original number 22425, we get 22424
Convert to binary
0101 0111 1001 1000
Perform 1’s complement by inverting each bit
1010 1000 0110 0111 = -22425
Chapter 4: Data Structures & Algorithms © HDC 2021.1 157
Bitwise operators
6 bitwise operators in C:
& | ^ ~ << >>
These operators are applicable with the data types:
char, short, int, long.
They can be used for floating point arithmetic
5 bit assignment operators
&= |= ^= <<= >>=
Bit assignment operators are similar to arithmetic
assignment operators
z &= x | y;
z = z & (x | y);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 158
Bitwise operators
Attention: developers should not confuse bitwise
operators with logical operators
& | ~ << >>
&& || ! < >
Chapter 4: Data Structures & Algorithms © HDC 2021.1 159
AND &
Perform AND bit-by-bit operation of two integers
E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 & b2;
b1 00011001 25
b2 01001101 & 77
b3 00001001 9
It is used to
Reset bit
Select a bit to verify
Chapter 4: Data Structures & Algorithms © HDC 2021.1 160
OR |
Perform OR bit-by-bit operation of two integers
E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 | b2;
b1 00011001 25
b2 01101010 | 106
b3 01111011 123
It is used to
Set a bit
Chapter 4: Data Structures & Algorithms © HDC 2021.1 161
XOR ^
Perform XOR bit-by-bit operation of two integers
E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 ^ b2;
b1 00011001 25
b2 01001101 ^ 77
b3 01010100 84
It is used to
Set a bit
Chapter 4: Data Structures & Algorithms © HDC 2021.1 162
NOT ~
Perform NOT (1’s complement) operation of an integer
E.g.: b1, b2 are unsigned char numbers
b2 = ~b1;
b1 00011001 25
b2 11100110 230
It is used to
Invert status of a bit or a group of bits
Chapter 4: Data Structures & Algorithms © HDC 2021.1 163
Left shift <<
Perform left shift operation of an integer by a number
of bits specified by the right operand
E.g.: b1, b2 are unsigned char numbers
b2 = b1 << 2;
b1 00011010 26
b2 01101000 104
Attention:
MSB disappears, inserted bit at LSB is always 0
The operator is equivalent to multiplying the number with 2^n:
b2 = b1*4
Chapter 4: Data Structures & Algorithms © HDC 2021.1 164
Right shift >>
A bit more complex: shift the bits of an integer to the
right by a number specified by the right operand
LSB disappears, inserted bit at MSB is
0 if the number is unsigned
1 (arithmetical right shift) hoặc 0 (logical right shift)
signed char x = -75; /* 1011 0101 */
signed char y = x>>2; /* 0010 1101 (logical) */
/* 1110 1101 (arithmetic) */
The result depends on the computer and the OS.
It is 45 with logical right shift and -19 with arithmetical right
shift in the above example.
In fact, right shift is usually applied for unsigned numbers and
it is equivalent to dividing the number by 2^n
Chapter 4: Data Structures & Algorithms © HDC 2021.1 165
2 raised to the n-th power
Bit shift operators are often used in exchange of
multiplication
They are faster than multiply operator
x * 2 x << 1
x / 16 x >> 4
x % 8 x & 7
However, using bit shift operators make the code more
difficult to read
Chapter 4: Data Structures & Algorithms © HDC 2021.1 166
Warning
If bit shift operator is perform by a number larger than
size of (sizeof) the left operand, the result may be
unspecified
Chapter 4: Data Structures & Algorithms © HDC 2021.1 167
Bitwise operators precedence
Precedence of bitwise operators in C:
NOT ~
AND &
XOR ^
OR |
However, () should be used in all cases
Chapter 4: Data Structures & Algorithms © HDC 2021.1 168
Checksum 8 bit
#include <reg51.h> #include <reg51.h>
void main(void) { void main(void) {
unsigned char mydata[] unsigned char mydata[]
={0x25,0x62,0x3F,0x52}; ={0x25,0x62,0x3F,0x52,0xE8};
unsigned char sum=0, x unsigned char shksum=0;
unsigned char chksumbyte; unsigned char x;
for (x=0;x<4;x++) { for (x=0;x<5;x++)
P2=mydata[x]; chksum=chksum+mydata[x];
sum=sum+mydata[x]; if (chksum==0)
P1=sum; P0=‘Good’;
} else
chksumbyte=~sum+1; P0=‘Bad’;
P1=chksumbyte; }
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 169
Checksum 8 bit
#include <reg51.h> Summation:
void main(void) {
unsigned char mydata[]
25H+ 62H+ 3FH+ 52H = 118H
={0x25,0x62,0x3F,0x52}; Two complements of 118H
unsigned char sum=0, x
unsigned char chksumbyte;
is E8H
for (x=0;x<4;x++) {
P2=mydata[x];
sum=sum+mydata[x];
P1=sum;
}
chksumbyte=~sum+1;
P1=chksumbyte;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 170
Checksum 8 bit
Summation: #include <reg51.h>
void main(void) {
25H+ 62H+ 3FH+ 52H = 118H unsigned char mydata[]
Two complements of 118H is ={0x25,0x62,0x3F,0x52,0xE8};
E8H unsigned char shksum=0;
unsigned char x;
Verify the check sum: for (x=0;x<5;x++)
25H+ 62H+ 3FH+ 52H + E8H = 0 chksum=chksum+mydata[x];
if (chksum==0)
P0=‘Good’;
else
P0=‘Bad’;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 171
Bit masking
Bit operators are used for 2 main purposes:
Save memory by storing status flags in one byte
Interface with hardware register
In these 2 cases, it is required the capability of
modifying each bit and check each bit status.
C enables to create macro, which can set, reset (clear)
bit or reverse bit status, named masking
Chapter 4: Data Structures & Algorithms © HDC 2021.1 172
Bit masking
Step 1: Create one integer which represents the status of
each bit or a group of bits
E.g.:
enum {
FIRST = 0x01, /* 0001 binary */
SECND = 0x02, /* 0010 binary */
THIRD = 0x04, /* 0100 binary */
FORTH = 0x08, /* 1000 binary */
ALL = 0x0f /* 1111 binary */
};
Chapter 4: Data Structures & Algorithms © HDC 2021.1 173
Bit masking
In another way:
enum {
FIRST = 1 << 0,
SECND = 1 << 1,
THIRD = 1 << 2,
FORTH = 1 << 3,
ALL = ~(~0 << 4)
};
The last line is used to set/reset a group of bit
1111 1111 /* ~0 */
1111 0000 /* ~0 << 4 */
0000 1111 /* ~(~0 << 4) */
Chapter 4: Data Structures & Algorithms © HDC 2021.1 174
Operations with Bit masking
unsigned flags = 0;
flags |= SECND | THIRD | FORTH; /* (1110). */
flags &= ~(FIRST | THIRD); /* (1010). */
flags ^= (THIRD | FORTH); /* (1100). */
if ((flags & (FIRST | FORTH)) == 0)
flags &= ~ALL; /* (0000). */
Operator | (can be called a pipe ) is used to obtain a combination of bit masks
Operator ~ is used to reverse all the bits (all bits are 1 except the ones with
masks)
Operator |= is used to set bits
Opertor &= is used to reset bits
Opertor ^= is used to flip bits
Opertor & is used to select bits (for checking status).
Chapter 4: Data Structures & Algorithms © HDC 2021.1 175
Macro for each bit
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
#define BitTst(arg,posn) ((arg) & (1L << (posn)))
enum {FIRST, SECND, THIRD};
unsigned flags = 0;
flags = BitSet(flags, FIRST); /* Set first bit. */
flags = BitFlp(flags, THIRD); /* Toggle third bit. */
if (BitTst(flags, SECND) == 0)/* Test second bit. */
flags = 0;
Chapter 4: Data Structures & Algorithms © HDC 2021.1 176
Example
Implement an operation to swap 2 variables using XOR
#define SWAP(a,b) {a^=b; b^=a; a^=b;}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 177
Union revise
Chapter 4: Data Structures & Algorithms © HDC 2021.1 178
Example of Union
Chapter 4: Data Structures & Algorithms © HDC 2021.1 179
Bit Field
Assuming that we have a 32bit register with the above parameters
Chapter 4: Data Structures & Algorithms © HDC 2021.1 180
Bit Field Example
Chapter 4: Data Structures & Algorithms © HDC 2021.1 181
Working with Union
Chapter 4: Data Structures & Algorithms © HDC 2021.1 182
Examples with Union
Chapter 4: Data Structures & Algorithms © HDC 2021.1 183
Portability
Compilers for microcontrollers may consider int as
16bit or 32bit number depending on the
microcontroller
C Compiler may read it:
From left to right
From right to left
Chapter 4: Data Structures & Algorithms © HDC 2021.1 184
Data transfer
Temperature: 25.28 Humidity: 87 Power 111.4W
Chapter 4: Data Structures & Algorithms © HDC 2021.1 185
Sscanf/Sprintf
Chapter 4: Data Structures & Algorithms © HDC 2021.1 186
Example of union usage
Chapter 4: Data Structures & Algorithms © HDC 2021.1 187
Float to IEEE 32bit conversion
(or mantisa)
E.g.:
Chapter 4: Data Structures & Algorithms © HDC 2021.1 188
Float to IEEE 32bit conversion
Chapter 4: Data Structures & Algorithms © HDC 2021.1 189
Convert float to hex and hex to float
Chapter 4: Data Structures & Algorithms © HDC 2021.1 190
4.8 Event-driven programming
Event-driven programming is a programming paradigm
in which the flow of the program is determined by
events such as
Starting the program, initializing variables
Stepping in a loop, waiting for a command or an event
occurring such as mouse clicks, key presses, sensor outputs, or
messages from other programs or threads, timer stop
Event handling subroutines/functions
Getting back to the loop and wait for subsequent
events/commands
Embedded software also follows this paradigm
Chapter 4: Data Structures & Algorithms © HDC 2021.1 191
Example
Read “command” from keyboard and perform
corresponding tasks
Inputs: character from keyboard
a: execute “command A” via function A_handler()
b: execute “command B” via function B_handler()
q: exit the software
Pseudo code of the main loop
Wait for the next command
If a, execute command A
If b, execute command B
If q, exit
Chapter 4: Data Structures & Algorithms © HDC 2021.1 192
Loop control scheme
Repeat until stopping condition matches
Use variable done to verify stopping condition
set done to false
while not done
body statements
if quit command, set done to true
Chapter 4: Data Structures & Algorithms © HDC 2021.1 193
Source code
#define FALSE 0
#define TRUE 1
int main(void) {
char command;
int done;
done = FALSE;
while (!done) {
command = ReadCommand( );
/* Input command from user */
switch (command) {
case ‘a’: A_handler(); /* Execute command A */
break;
case ‘b’: B_handler(); /* Execute command B */
break;
case ‘q’: done = TRUE; /* quit */
break;
default: printf(“Unrecognized command\n”);
}
}
return 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 194
Multithreading
Multithreading is a specialized form of multitasking
which allows the computer to run two or more tasks
concurrently
Two types of multitasking:
Process-based multitasking handles the concurrent execution of
programs.
Thread-based multitasking deals with the concurrent execution
of pieces of the same program.
A multithreaded program contains two or more parts
that can run concurrently. Each part of such a program
is called a thread, and each thread defines a separate
path of execution.
Chapter 4: Data Structures & Algorithms © HDC 2021.1 195
Multithreading
Image courtesy: https://en.wikipedia.org/wiki/Thread_(computing)#/media/File:Multithreaded_process.svg
Chapter 4: Data Structures & Algorithms © HDC 2021.1 196
Multithreading
Chapter 4: Data Structures & Algorithms © HDC 2021.1 197
Function call within a thread
1. Using The Function Object
/</em>/ Define the class for function object
class functionObject_class {
// Overload () operator
void operator()(params)
{
// code to be executed
}
};
// Cr
Chapter 4: Data Structures & Algorithms © HDC 2021.1 198
Function call within a thread
2. Using Function Pointer
void funct_call(params){
//code to be executed
}
std::thread thread_obj(funct_call, params);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 199
Function call within a thread
3. Using A Lambda Expression
// Define a lambda expression
auto f = [](params) {
// code for execution
};
std::thread thread_object(f, params);
Chapter 4: Data Structures & Algorithms © HDC 2021.1 200
Example
#include <iostream> int main() {
#include <thread> // Define a Lambda Expression
using namespace std; auto f = [](int n) {
// function to be used in callable for (int i = 0; i < n; i++)
void func_dummy(int N) { cout << "Thread 3 :: callable => lambda
for (int i = 0; i < N; i++) { expression\n";
cout << "Thread 1 :: callable => };
function pointer\n"; //launch thread using function pointer as
} callable
} thread th1(func_dummy, 2);
// A callable object // launch thread using function object as
class thread_obj { callable
public: thread th2(thread_obj(), 2);
void operator()(int n) { //launch thread using lambda expression
for (int i = 0; i < n; i++) as callable
cout << "Thread 2 :: callable => thread th3(f, 2);
function object\n"; // Wait for thread t1 to finish
} th1.join();
}; // Wait for thread t2 to finish
th2.join();
// Wait for thread t3 to finish
th3.join();
return 0;
}
Chapter 4: Data Structures & Algorithms © HDC 2021.1 201
END OF CHAPTER 4
Chapter 4: Data Structures & Algorithms © HDC 2021.1 202