* Có 3 chức năng chính: - Hiện thị thông tin các tuyến đường đô thị - Tìm đường đi từ điểm ban đầu đến điểm kết thúc theo 2 chức năng+ Con đường ngắn nhất+ Con đường có thời gian di chuy
Trang 1ĐẠI HỌC BÁCH KHOA HÀ NỘI TRƯỜNG ĐIỆN- ĐIỆN TỬ
🙢🙢🙢
Báo cáo bài tập lớn cuối kỳ
Cấu trúc dữ liệu và giải thuật
ĐỀ TÀI:
HỖ TRỢ GIAO THÔNG
Giáo viên hướng dẫn : Phạm Doãn Tĩnh
Sinh viên thực hiện
Trang 2Mục lục
I Xác định bài toán 3
1 Đặt vấn đề 3
2 Giới thiệu chung 3
3 Định nghĩa bài toán 3
II Các cấu trúc dữ liệu được sử dụng 3
1 Đồ thị 3
2 Mảng( vectors) 4
3 Hàng đợi ưu tiên( priority queue) 4
4 Kiểu dữ liệu Pair 4
III Thuật toán Dijkstra 5
1 Ý tưởng 5
2 Minh họa thuật toán 5
IV Cài đặt chương trình 6
1 Lớp Street 6
2 Đồ thị 8
3 Thuật toán Dijkstra 12
4 Hàm main 14
Trang 3I Xác định bài toán:
1 Đặt vấn đề:
- Ùn tắc giao thông là một vấn đề nan giải đối với hầu hếtcác thành phố lớn trên thế giới, kể cả các quốc gia phát triểncũng như các quốc gia đang phát triển Hệ lụy của ùn tắc giaothông ảnh hưởng tiêu cực tới nhiều mặt của đời sống xã hội nhưlàm tăng thời gian đi lại, tăng tiêu hao nhiêu liệu và hao mònphương tiện, tăng chi phí đi lại, tăng lượng khí thải và tiếng ồn,làm giảm sự cơ động của giao thông đô thị, giảm chất lượngmôi trường sống đô thị, kìm hãm sự phát triển của kinh tế đôthị…
=> Cần có một ứng dụng giúp định vị và tìm kiếm các tuyếnđường hiệu quả về mặt thời gian
2 Giới thiệu chung:
- Hệ thống được tạo ra nhằm giúp người dùng tìm được nhưngcon đường đi phù hợp với bản thân về không gian và thời gian
* Có 3 chức năng chính:
- Hiện thị thông tin các tuyến đường đô thị
- Tìm đường đi từ điểm ban đầu đến điểm kết thúc theo 2 chức năng
+ Con đường ngắn nhất+ Con đường có thời gian di chuyến ngắn
- Thêm vị trí người dùng lên bản đồ để từ đó tìm đường
đi đến các vị trí khác
3 Định nghĩa bài toán:
- Cần 1 lớp Street để lưu trữ các thuộc tính của con đường + Gồm : Điểm bắt đầu, điểm kết thúc, độ dài con đường, vận tốc tối đa cho phép, số làn xe
-Xây dựng hàm in thông tin con đường để thực hiện chức năng hiển thị thông tin
-Xây dựng các hàm liên quan để thực hiện chức năng tìm đường đi tiết kiệm thời nhât và con đường ngắn nhất
-Xây dựng hàm để thêm một vị trí người dùng chọn vào bản đồ
II Các cấu trúc dữ liệu được sử dụng:
Trang 41 Đồ thị:
- Là một dạng cấu trúc dữ liệu không tuyến tính biểu diễn một tập các đối tượng, trong đó các đối tượng được kết nối với nhau
- Các đối tượng được biểu diễn bởi các đỉnh( vertices/nodes),
và được nối với nhau bởi các cạnh( edges)
- Nói chung đồ thị G(V,E) là một cặp các tập hợp (V,E), trong
đó V là tập các đỉnh , E là tập các cạnh
- Hai đỉnh được gọi là kề nhau( adjacent) nếu chúng được kết nối với nhau thông qua một cạnh
2 Mảng( vectors):
- Trong dự án, ta sử dụng vector(mảng động) trong C++ STL
- Vectors có thể tự động thay đổi kích thước khi xóa hoặc thêmphần tử
- Có thể được truy cập ngẫu nhiên và duyệt như mảng tĩnhbình thường hoăc dùng Iterators
- Thêm 1 phần tử vào vectors bằng hàm push_back()
- Xóa 1 phần tử bằng hàm pop_back()
3 Hàng đợi ưu tiên( priority queue):
-Hàng đợi ưu tiên (priority queue) là một hàng đợi trong đómỗi phần tử được gắn với một con số được gọi là độ ưu tiên
- Độ ưu tiên do ứng dụng xác định
Trang 5- Việc lấy một phần tử ra khỏi hàng đợi dựa trên độ ưu tiên vàquy tắc FIFO Nghĩa là phần tử nào có độ ưu tiên cao nhất sẽđược lấy ra trước nhất Trường hợp các phần tử có mức độ ưutiên như nhau thì sử dụng quy tắc FIFO.
4 Kiểu dữ liệu Pair:
Kiểu dữ liệu pair được định nghĩa trong thư viện STL của C++, cho phép lưu 2 giá trị cùng lúc và được sử dụng trong nhiều trường hợp khác nhau
Pair<T1, T2> pair_name(value1, value2);
T1, T2 là kiểu dữ liệu của hai giá trị trong pair
pair_name là tên của pair
value1, value2 là giá trị hai phần tử trong pair
Truy cập các phần tử trong pair bằng cách sử dụng thuộc tính first và second
III Thuật toán Dijkstra:
- Được tạo ra bởi nhà khoa học máy tính người Hà LanW.Dijkstra vào năm 1956
- Là một trong những thuật toán cổ điển để tìm đường đi ngắnnhất từ một điểm cho trước tới tất cả các điểm còn lại trong đồthị không có trọng số âm
- Cụ thể hơn, thuật toán sẽ duy trì đường đi ngắn nhất đến tất cả các đỉnh Ở mỗi bước, chọn đường đi S→ucó tổng trọng
số nhỏ nhất trong tất cả các đường đi đang được duy trì Sau đótiến hành tối ưu các đường đi S→v bằng cách thử kéo dài thành S→u→v như đã mô tả trên
2 Minh họa thuật toán:
- B1: Khởi tạo:
+ Chọn đỉnh nguồn ban đầu
Trang 6+ Gán giá trị 0 cho đỉnh nguồn và vô cùng (hoặc giá trị lớn nhất có thể) cho các đỉnh còn lại.
+ Đánh dấu tất cả các đỉnh là chưa được duyệt
- B2: Lặp lại cho tất cả các đỉnh: a Tìm đỉnh v có giá trị nhãn nhỏ nhất (đỉnh gần nhất) chưa được duyệt b Đánh dấu đỉnh v
là đã duyệt.
- B3: Duyệt qua tất cả các đỉnh kề của đỉnh v: a Nếu đỉnh kề
chưa được duyệt và có giá trị nhãn hiện tại lớn hơn giá trị nhãn của đỉnh v cộng với trọng số của cạnh với đỉnh kề, cập nhật giá trị nhãn của đỉnh kề b Lưu đỉnh v là đỉnh trước đỉnh kề
- B4: Lặp lại từ bước 2 cho đến khi tất cả các đỉnh đều đã được duyệt hoặc giá trị nhãn của đỉnh tiếp theo là vô cùng
IV Cài đặt chương trình:
Trang 7pair<char, pair<char, double>> name; // pair<'A', pair<'B', 2.5>> = con đường bat dau tai A và ket thuc tai B => AB=2.5;
int maxspeed; // Toc do cho phep
int numLanes; // So lan xe
int Check(); // Hàm kiểm tra loại đường
void Print(); // Hàm in thông tin đường
};
int Street::Check()
{
if (Street::maxspeed <= 40) return 1; // 1 tương ứng với đường phổ thông
if (Street::maxspeed > 40 && maxspeed <= 80) return 2; // 2 tương ứng với đường quốc lộ
if (Street::maxspeed > 80) return 3; // 3 tương ứng với đường cao tốc }
Trang 8cout << " Maximum speed allowed: " << Street::maxspeed << "(km/h)"
cout << " Street Type: Expressway" << endl;
cout << " Attention: Only for cars" << endl;
int NumPlaces = 12; / / Số điểm trên bản đồ
int NumStreet = 17; // Số đường đi được khởi tạo
void Input(vector<Street> st, vector<vector<pair<int, double>>>& adj) // Nhập thông tin vào vector các vector
{
Trang 9for (int i = 0; i < NumStreet; i++)
Trang 10void AddPoint(vector<Street> &v) // Cho phép người dùng thêm một địa điểm mới vào bản đồ và cập nhật đồ thị tương ứng.
{
cout << " Which Street are you on on the map? " << endl;
for (int i = 0; i < v.size(); i++)
Trang 11Street st2(streetName, v[choice1-1].maxspeed , v[choice1-1].numLanes); v.push_back(st2);
v.push_back(st1);
Trang 12cout << " You have successfully added the location." << endl;
cout << " Your position is called " << char(NumPlaces + 64) << endl;}
Thêm điểm vào đồ thị
3 Thuật toán Dijkstra:
void Dijkstra(int Start, int End,vector<Street> st) // Thuật toán Dijkstra{
vector<vector<pair<int, double>>> adj(NumPlaces+1); // khởi tạo vector các vector với số phần tử xin cấp phát là NumPlaces+1
Input(st, adj); // thực hiện nhập vào adj tạo đồ thị
int pre[maxn]; // tạo mảng pre[] có tác dụng in ra đường đi ngắn nhất vector<double> Distance(NumPlaces + 1, INF); // tạo vector số thực để khởi tạo khoảng cách đến mọi điểm, ban đầu khởi tạo khoảng cách là vô cùng Distance[Start] = 0; // Cho khoảng cách đến điểm bắt đầu bằng 0
Trang 13pre[Start] = Start; // cho pre[Start]=Start tức đường đi đến điểm khởi đầu là chính nó.
priority_queue<pair<double, int>, vector<pair<double, int>>,
greater<pair<double, int>>> Q; // Khởi tạo hàng đợi ưu tiên theo thứ tự bé đến lớn
Q.push({0, Start}); // push điểm đầu với chiều dài là 0
double Dis = top.first;
if (Dis > Distance[u]) // kiểm tra xem điểm này đã được thăm trước đó chưa
continue;
for (auto it : adj[u]) // it là pair gồm điểm lân cận và khoảng cách từ điểm lân cận đến điểm đang xét
{
int v = it.first; // v là điểm lân cận
double w = it.second; // w là khoảng cách từ điểm lân cận đến điểm đangxét
if (Distance[v] >= Distance[u] + w) // Nếu khoảng cách từ Start đến v lớn hơn tổng khoách cách từ Start đến u kết hợp với w
Trang 14}
Kết quả của thuật toán dijkstra
4 Hàm main
- Lưu phần đồ thị và thuật Dijkstra trong file function.cpp
- Lưu lớp Street trong file Street.cpp
Trang 17cout << "What would you like to do?" << endl;
cout << " 1 View streets information" << endl;
cout << " 2 Find the way" << endl;
cout << " 3 Add your location" << endl;
cout << " 4 Exit." << endl;
cout << "Enter your choice: ";
Trang 18if(i<9) cout << " " << i + 1 << "." << v[i].name.first << v[i].name.second.first << " ";
else cout << " " << i + 1 << "." << v[i].name.first <<
Trang 19}
case 2:
{
Edit();
cout << " Enter starting point" << endl;
cout << " Enter here: ";
cout << " Enter the end point" << endl;
cout << " Enter here: ";
Trang 20cout << " Location does not exist on the map Please re-enter." << endl;
cout << " Enter again here: ";
cout << "(KM):Total path length" << endl;
cout << " The route with the shortest travel time" << endl;
Trang 21cout<< " 2.NO" <<endl;
cout<< "Enter here: ";
Trang 22Thông tin đường BC
Trang 23Khoảng cách ngắn nhất từ A đến L và thời gian ngắn nhất từ A đến L
Trang 24Nhập thêm điểm M vào giữa đoạn AE với khoảng cách từ A đến G là 0.6 km
Kết thúc chương trình