Đồ án giải thuật lập trình với đề tài sơ đồ mạng tại đại học bách khoa đà nẵng. Trong báo cáo bao gồm cách đọc file và xuất file từ định dạng cho trước,bao gồm code của chương trình. Báo cáo nhận được 9đ và rất đầy đủ,chỉ cần tải về và đọc hiểu code. Code được viết bằng java, tuy nhiên có thể viết bằng C hoặc C++.Mong các bạn đón nhận.
Trang 1KHOA CÔNG NGHỆ THÔNG TIN
ĐỒ ÁN
GIẢI THUẬT VÀ LẬP TRÌNH
Đề tài : Sơ đồ mạng
GIẢNG VIÊN HƯỚNG DẪN: Võ Đức Hoàng
SINH VIÊN THỰC HIỆN: Phan Cao Minh Nhật LỚP SH: 18T1
NHÓM: 18.Nh10B
Trang 2
MỤC LỤC
MỤC LỤC i
LỜI MỞ ĐẦU ii
DANH MỤC HÌNH VẼ iii
1 GIỚI THIỆU ĐỀ TÀI 1
2 CƠ SỞ LÝ THUYẾT 1
2.1 Ý tưởng 1
2.2 Thuật toán tìm cây khung nhỏ nhất (Prim) 1
3 TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN 3
3.1 Phát biểu bài toán 3
3.2 Cấu trúc dữ liệu 4
3.3 Thuật toán 6
4 CHƯƠNG TRÌNH VÀ KẾT QUẢ 7
4.1 Tổ chức chương trình 7
4.2 Ngôn ngữ cài đặt 10
4.3 Kết quả 11
4.3.1 Giao diện chính của chương trình 11
4.3.2 Kết quả thực thi của chương trình 12
4.3.3 Nhận xét 12
5 KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 13
5.1 Kết luận 13
5.2 Hướng phát triển 13
TÀI LIỆU THAM KHẢO 14
Trang 3LỜI MỞ ĐẦU
Ngày nay, Công nghệ thông tin đã trở thành một ngành khoa học cực kỳ quan trọng trong cuộc sống hiện đại, góp phần to lớn vào việc nâng cao năng suất, hiệu quả công việc cho các ngành nghề khác Có thể nói, mọi ngành khoa học khác đều cần đến
sự trợ giúp của máy vi tính Do đó, việc học tập và nghiên cứu về tin học cũng trở nên hết sức cần thiết và tất yếu đối với mọi người
Đối với sinh viên trong ngành càng phải tích cực học tập, nắm vững mọi kiến thức về công nghệ thông tin, trong đó cấu trúc dữ liệu và giải thuật được xem là cơ sở, nền tảng đầu tiên Cấu trúc dữ liệu và giải thuật giúp cho sinh viên hiểu được tầm quan trọng của giải thuật và cách tổ chức cấu trúc dữ liệu để giải quyết những bài toán cụ thể
Trong học kỳ này, em đã được giao thực hiện Đồ án giải thuật và lập trình Và
đề tài em thực hiện là: “Sơ đồ mạng”
Trong quá trình thực hiện đồ án chắc chắn khó tránh khỏi các sai sót, vậy rất mong sự đóng góp ý kiến của các thầy, cô giáo trong khoa Và em xin chân thành gửi lời cảm ơn chân thần đến các thầy, cô trong khoa, đặc biệt là thầy Võ Đức Hoàng đã tận tình hướng dẫn, tạo điều kiện cho em hoàn thành đề tài
Trang 4DANH MỤC HÌNH VẼ
Figure 1: Ví dụ lời giải cho bài toán sơ đồ mạng 1
Figure 2: Ví dụ mảng 2 chiều 6
Figure 3: Ví dụ chuyển dữ liệu sang dạng ma trận 8
Figure 4: Dữ liệu vào từ file văn bản SoDoKetNoiKhuVaPhong.txt 11
Figure 5: Kết quả được đưa ra file văn bản output.txt 12
Trang 51 GIỚI THIỆU ĐỀ TÀI
Trường Đại học Bách Khoa bao gồm nhiều khu giảng đường khác nhau Tổ quản trị mạng cần xây dựng một sơ đồ mạng để kết nối tất cả các khu với nhau Các khu có thể kết nối được với 1 số khu khác hoặc không Trong 1 khu các phòng có thể kết nối được với nhau hoặc không Kèm theo là độ dài chi phí dây mạng cần kết nối sao cho chi phí dây mạng dùng kết nối là thấp nhất
2 CƠ SỞ LÝ THUYẾT
2.1 Ý tưởng
- Lúc đầu khung chỉ chứa 1 khu chọn trước, sau đó thêm dần các khu vào cây khung Mỗi lần chọn một khu chưa nạp sao cho khu đó kề và gần nhất với các khu đã thêm
2.2 Thuật toán tìm cây khung nhỏ nhất (Prim)
Thuật toán xuất phát từ một cây chỉ chứa đúng một đỉnh và mở rộng từng bước một, mỗi bước thêm một cạnh mới vào cây, cho tới khi bao trùm được tất cả các đỉnh của đồ thị
- Dữ liệu vào: Một đồ thị có trọng số liên thông với tập hợp đỉnh V và tập hợp cạnh
E Đồng thời cũng dùng V và E để ký hiệu số đỉnh và số cạnh của đồ thị
- Khởi tạo: Vmới = {x}, trong đó x là một đỉnh bất kì (đỉnh bắt đầu) trong V, Emới =
{} Lặp lại cho tới khi Vmới= V:
- Chọn cạnh (u, v) có trọng số nhỏ nhất thỏa mãn u thuộc Vmới và v không thuộc
Vmới (nếu có nhiều cạnh như vậy thì chọn một cạnh bất kì trong chúng)
Figure 1: Ví dụ lời giải cho bài toán sơ đồ mạng
Trang 6- Thêm v vào Vmới, và thêm cạnh (u, v) vào Emới.
- Dữ liệu ra: Vmới và Emới là tập hợp đỉnh và tập hợp cạnh của một cây bao trùm
nhỏ nhất
- Ví dụ:
Đây là đồ thị có trọng số ban đầu Các số là các trọng số của các cạnh
{A}
(A,E) = 100 X
(A,C) = 150 (A,F) = 120
{B,C,E,F}
Chọn một cách tùy ý
đỉnh A là đỉnh bắt đầu Các đỉnh C, F, và E đều được nối trực tiếp tới A bằng cạnh của đồ thị E
là đỉnh gần A nhất nên ta chọn E là đỉnh thứ hai
của cây và thêm cạnh
EA vào cây.
{A,E} (A,F) = 120
(C,E) = 70 X {B,C,F}
Đỉnh được chọn tiếp
theo là đỉnh gần A hoặc
E nhất C có khoảng cách tới A bằng 150 và tới E bằng 70, F có
khoảng cách tới A là
120 C là đỉnh gần cây
hiện tại nhất nên chọn
đỉnh C và cạnh EC.
Trang 7{A,E,C} (C,F) = 80 X
(C,B) = 90
{B,F}
Thuật toán tiếp tục tương
tự như bước trước Chọn
đỉnh F có khoảng cách tới C bằng 80.
{A,E,C,F}
(F,A) = 120
(F,B) = 50 V
(C,B) = 90
{B}
Ở bước này ta có đỉnh B Khoảng cách từ B tới F
là 50 và tới C là 90 Nên
ta chọn đỉnh B và cạnh FB
{A,E,C,F,B} {}
Bây giờ các đỉnh đã nằm trong cây và cây bao trùm nhỏ nhất được tô màu đỏ
3 TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN
3.1 Phát biểu bài toán
- Dữ liệu vào: Tập tin chứa bảng mô tả kết nối và chi phí giữa các khu phòng
+ Ví dụ:
Trang 8Ký hiệu Khu Khu có thể kết nối (5 khu):A,B,C,E,F.
A C(150) , E(100), F(120)
B C(90) , F(50)
C A(150) , B(90), E(70), F(80)
Ký hiệu Phòng Phòng có thể kết nối
A101 A102(5) , A103(9), A201(12) A102 A202(12) , A135(15)
C105 C205(12)
… …
- Dữ liệu ra: Tập tin chứa các lưu trữ mạng kết nối các Khu, Phòng với chi phí thấp nhất + Ví dụ: Khu ket noi Chi phí F - B 50
E - C 70
A - E 100
C - F 80
=> Chi phi ket noi thap nhat la: 300
3.2 Cấu trúc dữ liệu
3.2.1 Mảng một chiều
- Mảng là một tập hợp tuần tự các phần tử có cùng kiểu dữ liệu và các phần tử
được lưu trữ trong một dãy các ô nhớ liên tục trên bộ nhớ Các phần tử của mảng được truy cập bằng cách sử dụng “chỉ số” Mảng có kích thước N sẽ có chỉ số từ 0 tới N–1 Các phần tử trong mảng được truy cập bằng cách sử dụng array_name[index]
- Trong ngôn ngữ Java, việc khai báo mảng được thực hiện theo cú pháp dưới đây và cần 2 tham số:
Dạng 1: [kiểu dữ liệu] [] [tên mảng] ;
Dạng 2: [kiểu dữ liệu] [tên mảng] [] ;
+ Kích thước của mảng: Việc này xác định số lượng phần tử có thể được lưu trữ trong mảng
Trang 9+ Kiểu dữ liệu của mảng: Việc này chỉ định kiểu dữ liệu của các phần tử trong mảng là số nguyên, số thực, ký tự hay là kiểu dữ liệu nào đó
- Cách tạo mảng 1 chiều :
Cách 1: kiểu_dữ_liệu] [] [tên_mảng] = new [kiểu_dữ_liệu] [kích_thước_mảng]; Cách 2: kiểu_dữ_liệu] [tên_mảng] [] = new [kiểu_dữ_liệu] [kích_thước_mảng];
- Trong bài toán đã sử dụng các mảng 1 chiều:
+ tenKhuVaPhong : dùng để chứa tên các khu trong trường cũng như tên các phòng trong 1 khu
+ point : dùng để tách khu và chi phí đi kèm với khu trong file input
+ dinhCha : dùng để chứa những đỉnh là đỉnh cha của những đỉnh được xét để tìm ra đỉnh cần thêm vào tiếp theo dựa vào chi phí của đỉnh con và đỉnh cha
+ chiPhi: dùng để chứa chi phí giữa đỉnh con và đỉnh cha
+ kiemTraDinh : dùng để kiểm tra đỉnh đã được thêm vào khung hay chưa
3.2.2 Mảng 2 chiều
- Mảng hai chiều là một mảng mà các phần tử của nó là mảng một chiều, giống như
một bảng gồm có dòng và cột, được đánh dấu vị trí là các chỉ số bao gồm chỉ số dòng
và chỉ số cột trong đó
- Trong ngôn ngữ Java, mảng hai chiều được khai báo theo cú pháp:
Dạng 1: [kieu_du_lieu] [ten_mang] [][];
Dạng 2: [kieu_du_lieu] [][] [ten_mang] ;
- Cách tạo mảng 2 chiều :
Cách 1: kiểu_dữ_liệu] [][] [tên_mảng] = new kiểu_dữ_liệu [số_dòng] [số_cột]; Cách 2: kiểu_dữ_liệu] [tên_mảng] [][] = new kiểu_dữ_liệu [số_dòng] [số_cột]; Trong đó: [kieu_du_lieu] mô tả kiểu của mỗi phần tử thuộc mảng (như int, char,
double, String, ), tên_mảng là tên của mảng và quy tắc đặt tên phải tuân theo quy tắc đặt
tên biến trong Java
- Trong bài toán đã sử dụng các mảng 2 chiều :
+ mangCacKhu : dùng để chứa chi phí giữa các khu
Ví dụ:
int[][] mangCacKhu = new int[5][5];
Trang 103.3 Thuật toán
Thuật toán tìm khung cây nhỏ nhất bằng thuật toán Prim
- Giải thuật
+ Ý tưởng của thuật toán: Thuật toán xuất phát từ một khung cây chỉ chứa đúng một khu
và mở rộng từng bước một, mỗi bước thêm một cạnh mới vào khung, cho tới khi bao trùm được tất cả các khu Dãy ban đầu có n khu, vậy tóm tắt ý tưởng thuật toán là thực hiện n-1 lần việc đưa khu vào khung cây Các bước thực hiện như sau:
• Bước 1 : Cho tất cả các phần tử của kiemTraDinh[] = false
• Bước 2 : Tìm khu u có chi phí thấp nhất với khu cha Ở lần đầu tiên ta cho u là phần tử đầu tiên trong mảng
+ Ở bước 2 ta có vòng for chạy N-1 lần để tìm được N-1 khu cần thêm vào khung cây nhỏ nhất
• Bước 3 : Cho khu u vừa tìm được là true với kiemTraDinh[u] = true
• Bước 4 : Chạy vòng for N lần để tìm ra những khu có kết nối với khu u vừa tìm được, sau đó quay lại bước 2
Trong đó : - kiemTraDinh[] là mảng chứa các khu được thêm vào với kiemTraDinh[u] = true với u là khu có chi phí thấp nhất với khu cha
- N là độ dài của ma trận
=> Độ phức tạp của thuật toán: từ bước 2 và 4 ta có thể thấy thuật toán có 2 vòng for lồng nhau Khi chạy như vậy thì thuật toán sẽ tốn N.(N-1) lần thì có thể tìm ra những khu cần thêm vào khung cây nhỏ nhất Vậy thuật toán sẽ có độ phức tạp là O(N2)
Figure 2: Ví dụ mảng 2 chiều
Trang 11- Đánh giá giải thuật
+ Thuật toán có độ phức khá cao, tuy nhiên dễ cài đặt và có thể sử dụng tốt với những bài toán với N nhỏ Với những bài toán với N lớn thì thuật toán sẽ gặp vấn đề về thời gian để giải quyết bài toán
4 CHƯƠNG TRÌNH VÀ KẾT QUẢ
4.1 Tổ chức chương trình
4.1.1 Hàm main().
- Chức năng :
+ Đọc file SoDoKetNoiKhuVaPhong.txt và ghi dữ liệu ra file output.txt
+ Lấy dach sách các khu và phòng bằng hàm getRoom() để lưu vào mảng
+ Chuyển dữ liệu đọc được sang dạng ma trận bằng hàm chuyenSangMT()
+ Tìm chi phi thấp nhất giữa các hàm bằng hàm prim() đồng thời ghi dữ liệu ra file output.txt
- Chương trình :
public static void main(String[] args) {
DoAn t = new DoAn();
String[] tenKhuVaPhong = null;
int[][] mangCacKhu = new int[20][20];
try {
//Ghi file ra tep output.txt
FileWriter myWriter = new FileWriter("output.txt");
//Doc du lieu tu file SoDoKetNoiKhuVaPhong.txt File input = new File("SoDoKetNoiKhuVaPhong.txt");
Scanner number = new Scanner(input);
//Xet tung dong trong file
while(number.hasNextLine()) {
String data = number.nextLine();
while(number.hasNextLine()) {
String currentLine[]=data.trim().split("\\s+"); tenKhuVaPhong = t.getRoom(data, number);
t.chuyenSangMT(mangCacKhu, currentLine, data,
number, tenKhuVaPhong); t.prim(mangCacKhu,myWriter,tenKhuVaPhong);
data = number.nextLine();
} }
myWriter.close();
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Trang 124.1.2 Hàm chuyenSangMT().
- Chức năng :
+ Chuyển dữ liệu từ file đọc được sang dạng ma trận với việc dùng 2 hàm check()
và tach()
* Ví dụ:
+ Hàm check() : kiểm tra phòng hoặc khu nằm ở vị trí nào trong mảng
+ Hàm tach() : dùng để tách phòng và chi phí phòng và lưu vào mảng point
*Ví dụ : tach(“C(100),”) => point[0] = “C” , point[1] = 100
- Chương trình :
+ Hàm chuyenSangMT() :
Figure 3: Ví dụ chuyển dữ liệu sang dạng ma trận
int[][] chuyenSangMT(int[][] zones, String[] currentLine, String
data,Scanner number,String[] s){ data = number.nextLine();
int j = 0;
while(data.length() != 0) {
int k = 0;
currentLine = data.trim().split("\\s+");
data = number.nextLine();
for(int i = 0; i < s.length; i++) {
if(k < currentLine.length) {
int a = check(tach(currentLine[k])[0],s);
if(a == i) {
if(a == j) {
zones[j][i] = 0;
} else { zones[j][i] =
Integer.parseInt(tach(currentLine[k])[1]);
zones[i][j] = zones[j][i];
} k++;
}else {
if(zones[j][i] == 0) {
zones[j][i] = zones[i][j];
} }
Trang 13
+ Hàm check() :
+ Hàm tach() :
4.1.3 Hàm prim().
- Chức năng :
+ Tìm chi phí thấp nhất giữa các khu hoặc phòng với việc dùng thêm 2 hàm chiChiThapNhat() và hàm print()
+ Hàm chiChiThapNhat() : tìm chi phí thấp nhất để thêm vào cây khung nhỏ nhất + Hàm print() : ghi dữ liệu tìm được ra file output.txt
- Chương trình :
+ Hàm prim() :
} }
j++;
} return zones;
}
int check(String a,String s[]) {
for(int i = 0; i < s.length; i++) {
if(s[i].equals(a)) { return i;
} }
return -1;
}
String[] tach(String a) {
if(a.length() == 1 || a.length() == 4) {
String[] point = {a,"0"};
return point;
}else {
int e = a.lastIndexOf("(");
int f = a.lastIndexOf(")");
String x = a.substring(e + 1, f);
String y = a.substring(0,e);
String[] point = {y,x};
return point;
} }
void prim(int maTranPhongVaKhu[][],FileWriter myWriter,String[] khu) { int n = khu.length;
int dinhCha[] = new int[n];
int chiPhi[] = new int[n];
Boolean kiemTraDinh[] = new Boolean[n];
for (int i = 0; i < n; i++) {
Trang 14+ Hàm chiChiThapNhat() :
+ Hàm print() :
4.2 Ngôn ngữ cài đặt
Chương trình sử dụng ngôn ngữ Java
//Danh sách đinh được chọn là n-1
for (int count = 0; count < n - 1; count++) {
//Chọn khu có chi phí thấ& p nhấ& t và chưa có trong khung
int u = chiPhiThapNhat(chiPhi, kiemTraDinh, n);
kiemTraDinh[u] = true;
//Cập nhật những đinh liề+ n kề+ với đinh vừa chọn và chưa có trong khung nho nhấ& t
for (int v = 0; v < n; v++)
if (maTranPhongVaKhu[u][v] != 0 && kiemTraDinh[v] == false &&
maTranPhongVaKhu[u][v] < chiPhi[v]) { dinhCha[v] = u;
chiPhi[v] = maTranPhongVaKhu[u][v];
}
}
//In ra file
print(dinhCha,maTranPhongVaKhu,myWriter,khu);
}
int chiPhiThapNhat(int chiPhi[], Boolean kiemTraDinh[],int X) {
int min = Integer.MAX_VALUE, min_index = -1;
for (int v = 0; v < X; v++)
if (kiemTraDinh[v] == false && chiPhi[v] < min) {
min = chiPhi[v];
min_index = v;
}
return min_index;
}
void print(int dinhCha[], int maTranPhongVaKhu[][],FileWriter
myWriter,String[] khu) {
myWriter.write("\nKhu ket noi \tChi phí\n");
for(int i = 1; i < khu.length; i++) {
myWriter.write( " " + khu[dinhCha[i]] + " - " + khu[i] + "\t\t" + maTranPhongVaKhu[i][dinhCha[i]] + "\n");
a = a + maTranPhongVaKhu[i][dinhCha[i]];
myWriter.write("=> Chi phi ket noi thap nhat la: " + a + "\n");
} catch (IOException e) {
e.printStackTrace();
} }
Trang 154.3 Kết quả
4.3.1 Giao diện chính của chương trình
- Trên hình 4 là file văn bản dữ liệu đầu vào với kí hiệu các Khu và Phòng trong khu Cột bên trái thể hiện cho kí hiệu khu hoặc phòng của từng khu Cột bên phải thể hiện cho khu hoặc phòng có thể kết nối được, sau mỗi khu hoặc mỗi phòng là chi phí kết nối giữa
Figure 4: Dữ liệu vào từ file văn bản SoDoKetNoiKhuVaPhong.txt
Trang 164.3.2 Kết quả thực thi của chương trình
- Dựa vào hình 5 ta thấy được kết quả thực thi của chưa trình Với cột bên trái thể hiện cho các khu hoặc các phòng có thể kết nối với nhau và mang chi phí là thấp nhất Cột bên phải thể hiện cho chi phí kểt nối giữa các khu hoặc các phòng Đồng thời kết quả thể hiện chi phí thấp nhất sau mỗi một khu hoặc phòng
4.3.3 Nhận xét
Ta thấy độ phức tạp của chương trình trên là O(V2) , điều đó cho thấy chương trình
sẽ chạy tương đối chậm Nếu đồ thị đầu vào được sử dụng danh sách kề với sự giúp đỡ của đống nhị phân thì độ phức tạp của chương trình sẽ xuống còn O(E log V) Nếu sử
Figure 5: Kết quả được đưa ra file văn bản output.txt