



















Preview text:
TÀI LIỆU THỰC HÀNH MÔN CẤU TRÚC DỮ LIỆU (Minh họa bằng C++) Trần Thiên Thành tranthienthanh@qnu.edu.vn MỤC LỤC
LỜI NÓI ĐẦU ............................................................................................................... 3
KẾ HOẠCH THỰC HÀNH .......................................................................................... 5
Bài thực hành số 01. KIỂU DỮ LIỆU MẢNG VÀ CON TRỎ .................................... 6
Bài 1. Kiểu dữ liệu cơ bản ......................................................................................... 6
Bài 2. Kiểu dữ liệu mảng ........................................................................................... 7
Bài 3. Kiểu con trỏ ................................................................................................... 11
Bài 4. Mảng động ..................................................................................................... 16
Bài 5 Mảng hai chiều ............................................................................................... 18
Bài thực hành số 02. KIỂU DỮ LIỆU: XÂU KÝ TỰ, TỆP VÀ KIỂU DO NGƯỜI
DÙNG ĐỊNH NGHĨA ............................................................................................................. 23
Bài 1. Danh sách sinh viên ....................................................................................... 28
Bài thực hành số 03. DANH SÁCH TỔ CHỨC BẰNG MẢNG ................................ 33
Bài 1. Danh sách khách hàng ................................................................................... 33
Bài thực hành số 04. DANH SÁCH LIÊN KẾT ĐƠN ................................................ 40
Bài 1. Đa thức (Polynomials) ................................................................................... 40
Bài 2. Vector thưa (Sparse vector). .......................................................................... 46
*Bài 3. Ma trận thưa 1 ............................................................................................. 46
Bài thực hành số 05. DANH SÁCH HAI LIÊN KẾT ................................................. 48
Bài 1. Số nguyên lớn (BigInteger) ........................................................................... 48
Bài 2. Sử dụng lớp list ............................................................................................. 57
**Bài 3. Ma trận thưa .............................................................................................. 58
Bài thực hành số 06. NGĂN XẾP VÀ HÀNG ĐỢI .................................................... 59
Bài 1. Stack .............................................................................................................. 59
Bài 2. Dấu ngoặc trong biểu thức ............................................................................ 59
Bài 3. Queue............................................................................................................. 60
Bài 4. Kết hợp Stack và Queue ................................................................................ 61
Bài 5. Chuyển biểu thức trung tố sang hậu tố .......................................................... 62
Bài 6. Tính giá trị biểu thức hậu tố. ......................................................................... 65
Bài thực hành số 07. CÂY NHỊ PHÂN ....................................................................... 67
Bài 1. Cây gia phả nhị phân ..................................................................................... 68 1
Bài 2. Xây dựng cây nhị phân .................................................................................. 74
Bài thực hành số 08. CÂY TÌM KIẾM NHỊ PHÂN VÀ CÂY CÂN BẰNG .............. 75
Bài 1. Cây từ điển Anh-Việt .................................................................................... 76
Bài 2. Cây cân bằng ................................................................................................. 80
Bài 3. Tập hợp .......................................................................................................... 86
Bài 4. Kiểm tra tính chất cây nhị phân..................................................................... 90
Bài thực hành số 09. CÂY TỔNG QUÁT ................................................................... 92
Bài 1. Cây gia phả .................................................................................................... 92
Bài 2. Cây từ điển tiếng Anh ................................................................................... 97
Bài 3. Cây thư mục ................................................................................................ 100
Bài thực hành số 10. CẤU TRÚC HEAP .................................................................. 101
Bài 1. Hàng đợi ưu tiên bằng Heap ........................................................................ 101
Bài 2. HeapSort ...................................................................................................... 104
Bài 3. Sử dụng hàng đợi ưu tiên trong thư viện C++ ............................................. 106
Bài thực hành số 11. DUYỆT ĐỒ THỊ ...................................................................... 110
Bài 1. Duyệt đồ thị ................................................................................................. 110
Bài 2. Đồ thị biết số điện thoại .............................................................................. 115
Bài thực hành số 12. ĐƯỜNG ĐI VÀ TÍNH LIÊN THÔNG ................................... 116
Bài 1. Đường đi và Liên thông .............................................................................. 116
Bài 3. Đồ thị biết số điện thoại .............................................................................. 124
Bài thực hành số 13. CÂY KHUNG .......................................................................... 125
Bài 1. Cây khung.................................................................................................... 125
Bài 2. Cây khung ngắn nhất ................................................................................... 129
Bài 3. Sử dụng vector cho đồ thị biểu diễn bằng danh sách cạnh. ......................... 131
Bài thực hành số 14. ĐƯỜNG ĐI NGẮN NHẤT ..................................................... 133
Bài 1. Cài đặt thuật toán Dijkstra sử dụng hàng đợi ưu tiên .................................. 133
Bài 2. Cài đặt thuật toán Kruskal bằng hàng đợi ưu tiên ....................................... 136
Bài thực hành số 15. BẢNG BĂM ............................................................................ 137
Bài 1. Bảng băm các sinh viên ............................................................................... 138
Bài 2. Đường bay ................................................................................................... 142
Case study: DU LỊCH VIỆT NAM ........................................................................... 143 2 LỜI NÓI ĐẦU
Tài liệu thực hành môn Cấu trúc dữ liệu được biên soạn với mục tiêu là tài liệu hướng
dẫn và định hướng cho sinh viên thực hành các nội dung kiến thức trong môn học Cấu trúc dữ
liệu. Do đó để đọc và sử dụng tài liệu này hiệu quả cần kèm theo Bài giảng môn Cấu trúc dữ
liệu của cùng tác giả.
Trong tài liệu này tôi minh họa bằng ngôn ngữ lập trình C++ theo cách tiếp cận lập
trình cấu trúc. Các ngôn ngữ lập trình khác như Python, Java sẽ dần được đưa lên Github để
thuận lợi cho các bạn sử dụng các ngôn ngữ lập trình khác.
Các bài thực hành được tổ chức theo kế hoạch giảng dạy môn học Cấu trúc tài liệu trong
15 tuần, mỗi tuần 2 đến 3 giờ thực hành. Do đó tôi chia thành 15 bài để thuận lợi cho việc tổ
chức dạy và học với dự kiến mỗi bài được thực hành trong thời gian một tuần. Tuy vậy, tùy
vào kế hoạch cá nhân các bạn có thể sắp xếp thực hành các bài cho phù hợp. Các bài thực hành
được biên soạn không chỉ cho các bạn thực hành 2-3 giờ mỗi tuần trên phòng thực hành mà
còn một mục tiêu lớn hơn là tài liệu để các bạn tự học trong thời gian không học trên lớp và
đây là thời gian các bạn tự thu xếp cho cá nhân và kết quả tự học có nhiều ý nghĩa trong bối
cảnh cách mạng công nghiệp lần thứ 4 và sự phát triển mạnh mẽ của những ứng dụng trí tuệ
nhân tạo. Do đó để thực hành đầy đủ các bài thực hành này các bạn cần dành thời gian để đọc,
suy nghĩ, đặt câu hỏi trước khi học ở phòng thực hành để nắm được những kiến thức, hình
thành những kỹ năng cơ bản của bài thực hành. Khi thực hành các bạn có thể tham khảo các
tài liệu, tài nguyên trên Internet, ứng dụng AI nhưng tôi vẫn khuyến khích các bạn tự lực làm
vì đây là những kiến thức và kỹ năng rất cơ bản cho người học Công nghệ thông tin.
Cấu trúc bài thực hành đều có mục tiêu của bài thực hành, nội dung thực hành, nhắc lại
kiến thức (nếu cần), hướng dẫn thực hành, câu hỏi, bài thực hành thêm và vận dụng. Các mã
lệnh chương trình được tổ chức thành các chức năng cho dễ hình dung nên khi thực hành các
bạn cần lắp ghép lại một cách hợp lý để chạy được chương trình. Việc chạy được chương trình
là bước đầu tiên để các bạn có thể hiểu kiến thức, hình thành kỹ năng và vận dụng sáng tạo
kiến thức vào các bài toán. Tuy nhiên, việc chạy chương trình chưa đủ mà các bạn cần phải
hiểu từng câu lệnh, từng cách tổ chức dữ liệu, từng thuật toán và ý nghĩa của nó thì mới vận
dụng được vào thực tế.
Nội dung các bài thực hành được xây dựng dựa vào các kiến thức của môn học gồm:
Các kiểu dữ liệu; Cấu trúc danh sách, Ngăn xếp, Hàng đợi; Cấu trúc cây; Cấu trúc đồ thị; Bảng băm.
Thông qua tài liệu này tôi mong các bạn có được một tài liệu cơ bản, ngắn nhằm giúp
các bạn tự học, tự thực hành để hình thành kỹ năng và vận dụng được kiến thức. Qua mỗi bài
thực hành các bạn sẽ hiểu thêm được kiến thức đã học trên lớp, khắc sâu hơn kiến thức đã học
và thấy được sự gần gũi kiến thức với các bài toán thực tế.
Tài liệu này được biên soạn trong bối cảnh ứng dụng AI đang được ứng dụng rộng rãi
đặc biệt là ChatGPT. Để biên soạn tài liệu này tôi đã sử dụng ChatGPT để hỗ trợ viết ra những
hàm theo cách tổ chức của tôi. Cảm ơn OpenAI đã làm ra một sản phẩm tuyệt vời giúp cho con
người trong nhiều việc và sẽ thay đổi nhiều cách thức làm việc trong thời gian tới, kể cả việc dạy và học. 3
Tài liệu được biên soạn trong thời gian ngắn nên chưa đáp ứng được nhu cầu của người
học, đặc biệt là chưa làm nổi bật được việc học thế nào trong bối cảnh các ứng dụng AI ngày
càng ứng dụng rộng rãi. Mọi ý kiến đóng góp cũng như trao đổi về nội dung, hình thức, phương
pháp,… tôi luôn lắng nghe và mong nhận được qua email: tranthienthanh@qnu.edu.vn.
Các mã nguồn của tài liệu được cập nhật trên Github tại địa chỉ:
https://github.com/thanhtranthien/Basic-DataStruct. Các bạn có thể lấy các mã nguồn có trong
tài liệu và các dữ liệu thực hành tại đây.
Quy Nhơn, Xuân Quý Mão 2023 Tác giả Trần Thiên Thành 4
KẾ HOẠCH THỰC HÀNH Tuần Bài Nội dung 1 1
Kiểu dữ liệu cơ sở, mảng, con trỏ 2 2
Kiểu dữ liệu xâu, tệp và kiểu do người dùng định nghĩa 3 3
Danh sách tổ chức bằng mảng 4 4 Danh sách liên kết đơn 5 5 Danh sách hai liên kết 6 6 Ngăn xếp và Hàng đợi 7 7 Cây nhị phân 8 8
Cây tìm kiếm nhị phân và Cây cân bằng 9 9 Cây tổng quát 10 10 Cấu trúc Heap 11 11 Duyệt đồ thị 12 12
Đường đi và Liên thông 13 13
Cây khung, Cây khung ngắn nhất 14 14 Đường đi ngắn nhất 15 15 Bảng băm 5
Bài thực hành số 01. KIỂU DỮ LIỆU MẢNG VÀ CON TRỎ
Mục tiêu: Sử dụng được các kiểu dữ liệu cơ bản trong các ngôn ngữ lập trình như: số
nguyên, số thực, logic, mảng, con trỏ.
Nhắc lại kiến thức:
Kiểu dữ liệu mảng:
+ Mảng là kiểu dữ liệu có cấu trúc gồm một dãy các ô nhớ liên tiếp nhau, có kích thước bằng nhau.
+ Mỗi mảng có một tên biến để thao tác. Trong C++ tên biến mảng là con trỏ đến ô nhớ đầu tiên của mảng. + Khai báo biến mảng:
kiểu tên[số phần tử];
Ví dụ: khai báo biến mảng m gồm 10 ô nhớ kiểu int int m[10];
Thao tác với biến mảng:
+ Thao tác với từng phần tử: tên[vị trí]
Vị trí đầu tiên trong mảng của C là 0.
+ Khai báo và gán giá trị cho mảng: int m[] = {1, 2, 3};
+ Nhập/xuất mảng: nhập/xuất từng phần tử của mảng.
Nội dung thực hành:
Bài 1. Kiểu dữ liệu cơ bản
Viết chương trình khai báo các biến với kiểu dữ liệu cơ bản, gán giá trị và in lên màn hình. #include using namespace std; int main () { // Creating variables
int myNum = 5; // Integer (whole number)
float myFloatNum = 5.99; // Floating point number
double myDoubleNum = 9.98; // Floating point number
char myLetter = 'D'; // Character
bool myBoolean = true; // Boolean
string myString = "Hello"; // String 6 // Print variable values
cout << "int: " << myNum << "\n";
cout << "float: " << myFloatNum << "\n";
cout << "double: " << myDoubleNum << "\n";
cout << "char: " << myLetter << "\n";
cout << "bool: " << myBoolean << "\n";
cout << "string: " << myString << "\n"; return 0; }
Kết quả chạy chương trình:
Bài 2. Kiểu dữ liệu mảng
Viết các hàm nhập, xuất, tìm số lớn nhất của một mảng số nguyên, tạo mảng chứa các
số chẵn từ một mảng cho trước. Viết chương trình sử dụng các hàm trên nhập vào một mảng
số nguyên, in mảng vừa nhập lên màn hình. Tìm số lớn nhất của mảng vừa nhập và in lên màn
hình. Tạo mảng chứa chứa các số chẵn từ mảng vừa nhập và in mảng này lên màn hình.
Chương trình Arr1.cpp dưới đây minh họa các thao tác: + Nhập một mảng + In một mảng
+ Tìm số lớn nhất trong mảng
+ Chương trình thực hiện nhập một mảng, in mảng vừa nhập, tìm số lớn nhất của mảng
vừa nhập và in lên màn hình. #include using namespace std; //Ham nhap mang n so nguyen void inputArr(int a[], int n) {
for(int i = 0; i < n; i++) { 7
cout << "Nhap so thu " << i << ": " ; cin >> a[i]; } } //Ham in mang n so nguyen
void outputArr(int a[], int n) {
for(int i = 0; i < n; i++)
cout << a[i] << " "; cout << endl; }
// Ham tim so lon nhat cua mang a co n so int maxArr(int a[], int n) { int i, max; max = a[0]; for(i = 1; i < n; i++)
if(max < a[i]) max = a[i]; return max; } // Ham main int main() { int x[10], m; inputArr(x, 5);
cout << "Mang da nhap: "; outputArr(x, 5); m = maxArr(x, 5);
cout << "So lon nhat cua mang la: " << m << endl; return 0; }
Kết quả chạy chương trình: 8
Hướng dẫn các thao tác bổ sung: Hàm tạo mảng chứa các số chẵn từ mảng cho trước.
Thuật toán tạo mảng số chẵn từ mảng cho trước
Dữ liệu vào: mảng a có n phần tử
Dữ liệu ra: mảng b chứa các số chẵn của mảng a Thao tác: Thao tác: + Gán biến k = 0
+ Duyệt lần lượt từng phần tử của mảng a
Nếu phần tử đang xét là số chẵn thì:
Đưa phần tử đang xét của mảng a vào vị trí k của mảng b Tăng k lên 1 + Trả về mảng b
Cài đặt hàm tạo mảng các số chẵn từ mảng cho trước.
int evenArr(int a[], int n, int b[]) { int i, k; k = 0; for(i = 0; i < n; i++) if(a[i] % 2 == 0) { b[k] = a[i]; k++; } return k; }
Bổ sung các lệnh sau trong hàm main int y[10], n; n = evenArr(x, 5, y);
cout << "Mang cac so chan gom " << n << " so: "; outputArr(y, n);
Kết quả chạy chương trình: 9
Viết các hàm sau rồi gọi chúng trong hàm main.
a) Tính trung bình cộng của các số trong mảng.
Gợi ý: tính tổng các số trong mảng rồi chia cho số phần tử của mảng. float avgArr(int a[], int n) { }
b) Tìm một số nguyên có trong mảng hay không?
bool findArr(int a[], int n, int x) { }
c) Sắp xếp mảng theo thứ tự tăng void sortArr(int a[], int n) { }
d) Ghép hai mảng tăng vào một mảng tăng. 10
int mergeArr(int a[],, int n, int b[], int m, int c[]) { }
e) Đếm số lần xuất hiện từng số trong mảng.
Gợi ý: dùng một mảng b để lưu các số khác nhau của mảng a cho trước, mảng d dùng
để lưu số lần xuất hiện từng số tương ứng trong mảng b.
Ví dụ: a = {4, 3, 1, 3, 4, 5, 1} thì b = {4, 3, 1, 5} và d = {2, 2, 2, 1}.
Hàm countArr() trả về số phần tử của mảng b.
int countArr(int a[], int n, int b[], int d[]) { } Câu hỏi:
a) Làm thế nào để biết được số ô nhớ của một biến mảng?
b) Có thể thay đổi kích thước mảng trong chương trình không?
c) Có thể duyệt biến mảng không qua chỉ số không?
Bài 3. Kiểu con trỏ
Thực hành một số thao tác trên biến kiểu con trỏ.
Ví dụ: Chương trình dưới đây minh họa các thao tác trên biến con trỏ gồm: khai báo,
gán địa chỉ, gán giá trị cho biến con trỏ. #include int main() { 11
// Declare an integer variable and a pointer to it int x = 10; int* p = &x;
// Print the value of x and the address of x
std::cout << "x = " << x << ", &x = " << &x << std::endl;
// Print the value of p and the value pointed to by p
std::cout << "p = " << p << ", *p = " << *p << std::endl;
// Modify the value of x through the pointer *p = 20; // Print the new value of x
std::cout << "x = " << x << std::endl; return 0; } Kết quả chương trình:
Câu hỏi: Hãy thêm một biến con trỏ q kiểu int, sau đó gán cho nó giá trị của biến con
trỏ p. Sửa dữ liệu của ô nhớ do q đang trỏ đến rồi in lại biến x xem giá trị có thay đổi không?
Ví dụ: Chương trình Pointer1.cpp minh họa các thao tác câp phát và thu hồi ô nhớ dùng biến con trỏ. #include int main() {
// Dynamically allocate an integer and a pointer to it int* p = new int; *p = 10;
// Print the value of p and the value pointed to by p
std::cout << "p = " << p << ", *p = " << *p << std::endl;
// Deallocate the memory pointed to by p delete p; 12
// Set p to null to prevent it from being used again p = nullptr; return 0; } Kết quả chương trình: Câu hỏi:
a) Sau khi thu hồi ô nhớ p, nếu in ra giá trị p và *p thì kết quả thế nào? Giải thích lý
do có kết quả như vậy.
b) Sau khi thu hồi ô nhớ p rồi cấp phát lại thì địa chỉ cấp phát cho ô nhớ p có giống
như cấp phát lần đầu không? Hãy viết các lệnh để minh họa cho điều này. Giải
thích lý do tại sao như vậy.
Ví dụ: chương trình Pointer2.cpp minh họa biến con trỏ của con trỏ. #include int main() {
// Declare an integer variable and a pointer to it int x = 10; int* p = &x;
// Declare a pointer to the pointer p int** pp = &p;
// Print the value of x, the address of x,
// the value of p, and the value pointed to by p
std::cout << "x = " << x << ", &x = " << &x << std::endl;
std::cout << "p = " << p << ", *p = " << *p << std::endl;
// Modify the value of x through the pointer to the pointer **pp = 20; // Print the new value of x
std::cout << "x = " << x << std::endl; return 0; } Kết quả chương trình: 13
Câu hỏi: Hãy giải thích tại sao giá trị cuối của x là 20.
Con trỏ và mảng: trong C++ biến mảng là biến con trỏ và giá trị của nó là địa chỉ của ô
nhớ đầu tiên trong mảng.
Ví dụ: nếu khai báo mảng int a[10]; thì biến a là biến con trỏ lưu địa chỉ ô nhớ a[0].
Chương trình Point3.cpp minh họa việc sử dụng biến con trỏ thao tác với mảng trong C++: #include int main() { int arr[] = {1, 2, 3, 4, 5}; int* ptr = arr;
std::cout << "Array elements using pointer: ";
for (int i = 0; i < 5; i++) {
std::cout << *ptr << " "; ptr++; }
std::cout << std::endl;
std::cout << "Array elements using array subscript notation: ";
for (int i = 0; i < 5; i++) {
std::cout << arr[i] << " "; } return 0; }
Kết quả chạy chương trình:
Chương trình Pointer4.cpp minh họa việc sử dụng con trỏ thay cho biến mảng. #include int main() { 14 const int SIZE = 5; int* arr = new int[SIZE]; int* ptr = arr; // Initialize array
for (int i = 0; i < SIZE; i++) { *ptr = i + 1; ptr++; }
ptr = arr; // Reset pointer to the beginning of the array
std::cout << "Original array: ";
for (int i = 0; i < SIZE; i++) {
std::cout << *ptr << " "; ptr++; }
ptr = arr; // Reset pointer to the beginning of the array
for (int i = 0; i < SIZE; i++) { *ptr = *ptr * 2; ptr++; }
ptr = arr; // Reset pointer to the beginning of the array
std::cout << std::endl;
std::cout << "Array after doubling the values: ";
for (int i = 0; i < SIZE; i++) {
std::cout << *ptr << " "; ptr++; } delete[] arr; return 0; }
Kết quả chạy chương trình: 15
Chương trình sử dụng toán tử new để cấp phát ô nhớ cho biến con trỏ và delete để
thu hồi các ô nhớ của biến con trỏ. Bài 4. Mảng động
Chương trình DynamicArray1.cpp minh họa thao tác trên mảng động. #include int main() { int size;
std::cout << "Enter the size of the array: "; std::cin >> size; int* arr = new int[size]; int* ptr = arr; // Initialize array
for (int i = 0; i < size; i++) { *ptr = i + 1; ptr++; }
ptr = arr; // Reset pointer to the beginning of the array
std::cout << "Original array: ";
for (int i = 0; i < size; i++) {
std::cout << *ptr << " "; ptr++; } //Resize the array int new_size;
std::cout << "\nEnter the new size of the array: "; std::cin >> new_size;
int* new_arr = new int[new_size];
// copy the elements to the new array
for (int i = 0; i < std::min(size, new_size); i++) { 16 new_arr[i] = arr[i]; }
ptr = new_arr; // Update pointer to point to the new array
std::cout << "Array after resizing: ";
for (int i = 0; i < new_size; i++) {
std::cout << *ptr << " "; ptr++; } // Free the memory delete[] arr; delete[] new_arr; return 0; }
Giải thích: ban đầu biến con trỏ arr được cấp phát size ô nhớ và gán các giá trị từ 1 đến
size. Sau đó một con trỏ new_arr được cấp phát new_size ô nhớ và copy các giá trị từ arr sang
new_arr. Như vậy ta có thể dùng biến con trỏ để tạo các mảng mà kích thước có thể thay đổi
trong quá trình sử dụng.
Hãy dùng mảng động viết chương trình DynamicArray2.cpp thực hiện các yêu cầu sau:
a) Nhập một mảng động n số nguyên.
b) In mảng động n số nguyên.
c) Thêm một số vào cuối mảng động Viết các hàm:
a) Hàm nhập mảng động n số nguyên. Trả về con trỏ đến phần tử đầu tiên của mảng. int* inputDynamicArr(int n) { }
b) Hàm in mảng động n số nguyên có địa chỉ từ arr.
void printDynamicArr(int *arr, int n) { } 17
c) Hàm thêm một số x vào cuối mảng arr có n số.
void appendDynamicArr(int *arr, int &n, int x) { }
Viết hàm main() sử dụng các hàm trên. int main() { }
Bài 5 Mảng hai chiều
Chương trình Arr2D_1.cpp minh họa thao tác đơn giản với mảng hai chiều. #include int main() {
// Declare a 2D array with 3 rows and 4 columns int myArray[3][4];
// Initialize the elements of the array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) { myArray[i][j] = i + j; } }
// Print the elements of the array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
std::cout << myArray[i][j] << " "; }
std::cout << std::endl; 18 } return 0; }
Chương trình Arr2D_2.cpp minh họa các chức năng nhập, xuất mảng hai chiều và cộng
hai ma trận được lưu trong hai mảng hai chiều. #include const int ROWS = 3; const int COLS = 4;
void inputArray(int arr[][COLS]) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
std::cout << "Enter element at position [" << i << "][" << j << "]: "; std::cin >> arr[i][j]; } } }
void outputArray(int arr[][COLS]) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
std::cout << arr[i][j] << " "; }
std::cout << std::endl; } }
void addArray(int arr1[][COLS], int arr2[][COLS], int arr3[][COLS]) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
arr3[i][j] = arr1[i][j] + arr2[i][j]; } } } 19