int row, col;: Khai báo hai biến row và col để lưu số hàng và số cột của ma trận mà người dùng sẽ nhập vào.. Trong biểu diễn này, với mỗi đỉnh v của đồ thị chúng ta lưu trữ danh sách cá
Trang 1TRƯỜNG ĐẠI HỌC TÀI NGUYÊN VÀ MÔI TRƯỜNG
THÀNH PHỐ HỒ CHÍ MINH
KHOA HỆ THỐNG THÔNG TIN VÀ VIỄN THÁM
BÁO CÁO
LÍ THUYẾT ĐỒ THỊ
DEMO CHƯƠNG TRÌNH :
MA TRẬN KỀ DANH SÁCH KỀ
Sinh viên thực hiện: Nhóm 10
Lớp : 11_ĐH_CNTT3
Khoá : 2022 – 2026
Giảng viên : Lê Tuấn Thu
TP Hồ Chí Minh, tháng 2 năm 2024
Trang 1
Trang 2TRƯỜNG ĐẠI HỌC TÀI NGUYÊN VÀ MÔI TRƯỜNG
THÀNH PHỐ HỒ CHÍ MINH KHOA HỆ THỐNG THÔNG TIN VÀ VIỄN THÁM
BÁO CÁO
LÍ THUYẾT ĐỒ THỊ
DEMO CHƯƠNG TRÌNH :
MA TRẬN KỀ DANH SÁCH KỀ
Sinh viên thực hiện: Nhóm 10
Lớp : 11_ĐH_CNTT3
Khoá : 2022 – 2026
Giảng viên hướng dẫn : Lê Tuấn Thu
TP Hồ Chí Minh, tháng 2 năm 2024
Trang 2
Trang 3MỤC LỤC
1 Ma trận kề……… 4
1.1 Ma trận kề là gì ?……… 4
1.2 Tính chất của ma trận kề……… 4
1.3 Demo ma trận kề……… 5
2 Danh sách kề……… 8
2.1 Danh sách kề là gì……… 8
2.2 Demo danh sách kề……… 9
Danh sách nhóm 10 Lớp CNTT3
9 1150080110 Nguyễn Ngọc Tuyết Nhiên Chich gai
1 Ma trận kề
1.1 Ma trận kề là gì ?
Trang 3
Trang 4Ma trận kề là cách biểu diễn đồ thị G = {V,E} dưới dạng ma trận các giá trị boolean có kích thước bằng với số đỉnh của đồ thị
1.2 Tính chất của ma trận kề :
Tính chất của ma trận kề của đồ thị vô hướng:
Tính đối xứng: a[i,j]=a[j,i], i,j=1,2, .,n
Tổng các phần từ trên dòng i (cột j) bằng bậc của đỉnh i (đỉnh j)
Tính chất của ma trận kề của đồ thị có hướng:
Không có tính đối xứng
Tổng các phần từ trên dòng i bằng bán bậc ra của đỉnh i (deg+(i)) và tổng các phần từ trên cột j bằng bán bậc vào của đỉnh j (deg(-j))
1.3 Demo ma trận kề
Khai báo thư viện fstream :
Thư viện fstream trong C++ được sử dụng để thực hiện các thao tác đọc và ghi vào các tệp (file) Với các lớp :
ifstream (Input File Stream): Dùng để đọc dữ liệu từ tệp.
ofstream (Output File Stream): Dùng để ghi dữ liệu vào tệp.
Trang 4
Trang 5Viết hàm nhập ma trận từ bàn phím với class ofstream :
void nhapmatran(int a[][100]): Đây là khai báo của hàm nhapmatran trong C++
Hàm này không trả về bất kỳ giá trị nào (void), nhưng nhận một mảng hai chiều làm a
tham số đầu vào
int row, col;: Khai báo hai biến row và col để lưu số hàng và số cột của ma trận mà
người dùng sẽ nhập vào
ofstream file("matranke.txt");: Tạo một đối tượng của lớp ofstream (output file
stream) có tên file và mở tệp có tên là "matranke.txt" để ghi dữ liệu vào
cout << "Nhap so hang : ";: Hiển thị thông báo để yêu cầu người dùng nhập số hàng
của ma trận
cin >> row;: Nhận giá trị số hàng từ người dùng thông qua bàn phím và lưu vào biến row.
cout << "Nhap so cot : ";: Hiển thị thông báo để yêu cầu người dùng nhập số cột của
ma trận
cin >> col;: Nhận giá trị số cột từ người dùng thông qua bàn phím và lưu vào biến col.
Trang 5
Trang 6file << row; file << " "; file << col; file << "\n";, , , : Ghi số hàng và số cột của ma trận vào tệp "matranke.txt"
for (int i = 0; i < row; i++) {: Bắt đầu vòng lặp để nhập giá trị của các phần tử trong
ma trận hàng từng hàng
for (int j = 0; j < col; j++) {: Bắt đầu vòng lặp để nhập giá trị của các phần tử trong
mỗi hàng của ma trận
cout << "Nhap vao a[" << i << "][" << j << "] : ";: Hiển thị thông báo yêu cầu
người dùng nhập giá trị của phần tử a[i][j] trong ma trận
cin >> a[i][j];: Nhận giá trị của phần tử a[i][j] từ người dùng.
file << a[i][j] << "\t";: Ghi giá trị của phần tử a[i][j] vào tệp "matranke.txt", cách
nhau bởi một dấu tab
file << "\n";: Xuống dòng để chuyển sang hàng mới trong tệp "matranke.txt" sau khi
nhập xong một hàng của ma trận
file.close();: Đóng tệp "matranke.txt" sau khi đã ghi xong dữ liệu ma trận vào tệp.
Viết hàm xuất mà trận từ file txt với class ifstream :
void xuatmatran(int b[][100]) :Khai báo hàm xuatmatran nhận một mảng hai chiều b
dưới dạng tham số Kích thước của mảng là 100x100
int row, col; Khai báo hai biến nguyên row và col để lưu số hàng và số cột của ma trận
ifstream file ("matranke.txt");Mở tệp có tên "matranke.txt" để đọc dữ liệu từ đó bằng lớp ifstream
file >> row >> col;Đọc hai giá trị từ tệp "matranke.txt" và gán chúng cho row và col, giả định rằng tệp chứa hai số nguyên đầu tiên lần lượt là số hàng và số cột của ma trận cout << "so hang va so cot cua ma tran : " << row << ", " << col << endl;Hiển thị số hàng và số cột của ma trận lên màn hình
Trang 6
Trang 7for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
file >> b[i][j];
cout << b[i][j] << " ";
}
cout << endl;
} : Đọc dữ liệu từ tệp "matranke.txt" và gán giá trị cho mảng b Vòng lặp đầu tiên
duyệt qua các hàng của ma trận, vòng lặp thứ hai duyệt qua các cột của ma trận Mỗi giá trị được đọc từ tệp và gán vào phần tử tương ứng của mảng , và sau đó hiển thị b
giá trị đó ra màn hình
file.close(); Đóng tệp "matranke.txt" sau khi hoàn thành việc đọc dữ liệu
Chạy chương trình :
Tạo được file txt chung đường dẫn với đường dẫn lưu chương trình :
Dữ liệu của file txt :
Trang 7
Trang 82 Danh sách kề
2.1 Danh sách kề là gì ?
Là cách biểu diễn đồ thị dưới dạng danh sách kề thường được sử dụng Trong biểu diễn này, với mỗi đỉnh v của đồ thị chúng ta lưu trữ danh sách các đỉnh kề với nó mà
ta ký hiệu là Ke(v), nghĩa là:
Ke(v) = { u V: (u, v) E} ∈ ∈
Với cách biểu diễn này, mỗi đỉnh i của đồ thị, ta làm tương ứng với một danh sách tất
cả các
đỉnh kề với nó và được ký hiệu là List(i) Để biểu diễn List(i), ta có thể dùng các kiểu
dữ liệu kiểu tập hợp, mảng hoặc danh sách liên kết
Trang 8
Trang 92.2 Demo chương trình
struct node { int data; node* next; };: Định nghĩa một cấu trúc node đại diện cho
một đỉnh trong đồ thị Mỗi node chứa một số nguyên (data) và một con trỏ next trỏ tới node tiếp theo trong danh sách liên kết
node* p, * DSKe[MAX];: Khai báo biến con trỏ p và mảng DSKe gồm MAX phần
tử, mỗi phần tử của mảng là một con trỏ đến node, được sử dụng để lưu danh sách kề của từng đỉnh trong đồ thị
Trang 9
Trang 10node* Taonode(int x) { }: Hàm này tạo một node mới có dữ liệu là x và trả về con
trỏ đến node mới tạo
node* Themnode(node* head, int x) { }: Hàm này thêm một node mới có giá trị x
vào cuối danh sách liên kết đang tồn tại và trả về con trỏ đầu của danh sách liên kết sau khi thêm
Trang 10
Trang 11void DanhSachKe() {: Khai báo hàm DanhSachKe() Hàm này không trả về giá trị
(void) và không có tham số đầu vào
int dinhdau, dinhcuoi;: Khai báo hai biến nguyên dinhdau và dinhcuoi để lưu trữ
đỉnh đầu và đỉnh cuối của một cạnh khi người dùng nhập vào
cout << "Nhap so dinh cua do thi : ";: In ra màn hình thông báo yêu cầu người dùng
nhập số đỉnh của đồ thị
cin >> sodinh;: Nhận giá trị số đỉnh của đồ thị từ người dùng qua bàn phím và lưu vào
biến sodinh
cout << "Nhap vao so canh cua do thi : ";: In ra màn hình thông báo yêu cầu người
dùng nhập số cạnh của đồ thị
cin >> socanh;: Nhận giá trị số cạnh của đồ thị từ người dùng qua bàn phím và lưu
vào biến socanh
for (int i = 0; i < sodinh; i++) { DSKe[i] = NULL; }: Khởi tạo danh sách kề của mỗi
đỉnh bằng NULL Duyệt qua mảng DSKe và gán giá trị NULL cho từng phần tử
for (int i = 0;i < socanh;i++) {: Bắt đầu vòng lặp để nhập từng cạnh của đồ thị cout << "Nhap dinh dau va dinh cuoi cua canh " << i + 1 << " : ";: In ra màn hình
thông báo yêu cầu người dùng nhập đỉnh đầu và đỉnh cuối của cạnh thứ i+1
cin >> dinhdau >> dinhcuoi;: Nhận giá trị của đỉnh đầu và đỉnh cuối của cạnh từ
người dùng qua bàn phím và lưu vào các biến dinhdau và dinhcuoi
DSKe[dinhdau] = Themnode(DSKe[dinhdau], dinhcuoi);: Thêm đỉnh cuối vào
danh sách kề của đỉnh đầu Hàm Themnode() được gọi để thêm đỉnh cuối vào danh sách kề của đỉnh đầu
DSKe[dinhcuoi] = Themnode(DSKe[dinhcuoi], dinhdau);: Thêm đỉnh đầu vào
danh sách kề của đỉnh cuối Hàm Themnode() được gọi để thêm đỉnh đầu vào danh sách kề của đỉnh cuối
Kết thúc vòng lặp for và kết thúc hàm DanhSachKe()
Trang 11
Trang 12void inDS() {: Khai báo hàm inDS() Hàm này không trả về giá trị (void) và không có
tham số đầu vào
for (int i = 0; i < sodinh; i++) {: Bắt đầu vòng lặp để duyệt qua từng đỉnh trong đồ thị cout << "Dinh " << i << " : ";: In ra màn hình thông báo cho biết đang in danh sách
kề của đỉnh thứ i
node* temp = DSKe[i];: Khởi tạo con trỏ temp và trỏ nó vào đầu danh sách kề của đỉnh thứ i
cout<<"{";: In ra màn hình ký tự { để bắt đầu in danh sách kề của đỉnh.
while (temp->next != NULL) {: Bắt đầu vòng lặp while để duyệt qua danh sách kề
của đỉnh Vòng lặp dừng khi con trỏ temp trỏ đến phần tử cuối cùng của danh sách
cout << temp->data << ", ";: In ra màn hình giá trị của đỉnh mà temp đang trỏ tới,
sau đó dấu phẩy để phân tách giữa các đỉnh.,
temp = temp->next;: Di chuyển con trỏ temp sang phần tử kế tiếp trong danh sách
kề
cout<< temp->data <<"}\n";: Sau khi vòng lặp kết thúc, in ra giá trị của đỉnh cuối
cùng mà temp trỏ tới và ký tự để đóng danh sách kề của đỉnh Dòng này cũng in ra }
ký tự xuống dòng để chuyển xuống dòng mới cho việc in tiếp đỉnh tiếp theo.\n
Kết thúc vòng lặp for và kết thúc hàm inDS()
Trang 12
Trang 13Hàm main là hàm chính của chương trình, nơi bắt đầu thực thi Trong hàm main, chương trình gọi lần lượt hai hàm DanhSachKe() để nhập và xây dựng danh sách kề,
và inDS() để in ra danh sách kề đã được xây dựng
Chạy chương trình :
Trang 13