Báo Cáo Đồ Án Môn Học _ Cấu Trúc Dữ Liệu và Giải Thuật _ Khoa Công Nghệ Thông Tin _ Đồ Án Xây Dựng Trạm Thu Phí Các Loại Xe Dùng Cấu Trúc Dữ Liệu Queue _ Trường Đại Học Sài Gòn _ PDF
Trang 1TRƯỜNG ĐẠI HỌC SÀI GÒN
-o0o -Báo Cáo Đồ Án Môn Học Cấu Trúc Dữ Liệu và Giải Thuật Khoa Công Nghệ Thông Tin
Trang 2Trường Đại Học Sài Gòn
-o0o -Trạm Thu Phí
Báo Cáo Đồ Án Ngành Công Nghệ Thông Tin
Họ và tên: Nguyễn Thành Hưng Lớp: DCT1211
MSSV: 3121410241 Học Phần: Cấu trúc dữ liệu và
giải thuật
Năm hoc: 2022/ HK: 2 Giảng Viên: PGS.TS Nguyễn
Tuấn Đăng
Trang 3Mục Lục
1 Đề bài: 5
A Đề bài: 5
B Các yêu cầu cần được giải quyết của đề bài: 5
2 Mô tả hệ thống sẽ được xây dựng: 5
2.1.Xác định các đối tượng trong hệ thống và các hàm khởi tạo các đối tượng đó: 5 2.2.Các chức năng của hệ thống: 9
3.Giải thích lý do sử dụng các cấu trúc dữ liệu để mô hình hóa các đối tượng dữ liệu trong hệ thống: 9
3.1.Dùng hàng đợi để mô hình hóa trạm thu phí: 9
3.2.Dùng danh sách liên kết để biểu diễn thông tin xe trong trạm: 9
4.Giải thích cài đặt các cấu trúc dữ liệu: 10
4.1.Cấu trúc dữ liệu danh sách liên kết 10
A Định nghĩa: 10
B Cấu trúc dữ liệu của phần tử: 10
4.1.Cấu trúc dữ liệu hàng đợi: 11
A Định nghĩa: 11
B Cài đặt hàng đợi bởi danh sách liên kết: 12
C Cấu trúc dữ liệu của hàng đợi: 12
5 Mã giả trình bày các thuật toán thực hiện các chức năng chính của chương trình:13 5.1.Chức năng thêm xe vào cuối hàng đợi: 13
5.2.Chức năng lấy xe ra ở đầu hàng đợi: 13
5.3.Hiển thị thông tin trong hàng đợi: 14
6 Trình bày và giải thích chương trinh được viết đề cài đặt các thuật toán: 14
6.1 Các chương trình khởi tạo: 14
A Khởi tạo danh sách liên kết: 14
B Khởi tạo hàng đợi rỗng và hàm kiểm tra hàng đợi: 15
6.2.Chương trình cài đặt các thuật toán thêm vào và lấy ra khỏi hàng đợi: 15
A Thêm khóa vào hàng đợi: 15
B Lấy khóa từ hàng đợi: 17
C Lấy thông tin các phần tử trong hàng đợi: 19
7 Kết quả thực thi chương trình và giải thích: 19
7.1 Mô tả hoạt động của hệ thống: 19
8 Kết luận: 23
Trang 4Danh Mục Hình
Hình 1: Sơ đồ tiến trình hàm thongtinxe 8
Hình 2: Danh sách liên kết đơn Fist 10
Hình 3: Hàng đợi là một danh sách liên kết 12
Hình 4: hàng đợi có một phần tử 16
Hình 5: hàng đợi có nhiều phần tử 16
Hình 6: xóa phần tử duy nhất của hàng đợi 18
Hình 7: Xóa một phần tử của hàng đợi có nhiều phần tử 19
Hình 8: Trạm thi phí cho xe vào 20
Hình 9: Trạm thu phí cho xe ra và vào 20
Hình 10: Trạm thu phí bị đầy xe 21
Hình 11: Giải quyết hàng đợi bị đầy 22
Trang 5Vào mỗi thời điểm sẽ có một xe ra khỏi hàng đợi để qua trạm, và có thể
có ngẫu nhiên từ 0 đến 3 xe vào hàng đợi Khi một xe qua trạm thì thông tincủa xe được ghi nhận
Tất cả các dữ liệu đều được khởi tạo ngẫu nhiên
Chương trình chỉ được dừng lại khi một phím quy ước được nhấn hoặckhi hàng đợi bị đầy
- Khởi tạo được các dữ liệu cho từng loại xe
- Thêm xe vào hàng đợi
- Lấy xe ở đầu hàng đợi ra, in thông tin xe được lấy ra
2.Mô tả hệ thống sẽ được xây dựng:
2.1.Xác định các đối tượng trong hệ thống và các hàm khởi tạo các đối tượng đó:
Đề bài yêu cầu xây dựng chương trình có sử dụng cấu trúc dữ liệu để
mô tả hoạt động của một trạm thu phí
Để xây dựng hoạt động của một trạm thu phí ta cần có thông tin ra vàocủa các loại xe Ở đây gồm 4 loại xe: xe tải, xe khách và xe con Mỗi loại xe lạigồm các thông tin như: số đăng ký, loại xe
Thông tin cho mỗi loại xe được xây dựng bởi cấu trúc sau:
Trang 6kiểu int để lưu lại số đăng ký, ban đầu số đăng ký được gán bằng 0, sau đóđược hàm random gán lại một giá trị bất kỳ.
Hàm random được xây dựng như sau:
intrandom(intminN,intmaxN) {
return minN+rand()% (maxN+1- minN);
}
Hàm radom sẽ nhận 2 giá trị đầu vào là maxN và minN, trong đó:
maxN là số ngẫu nhiên lớn nhất có thể , minN là số ngẫu nhiên nhỏ nhất có thể
Hàm radom dựa trên hàm rand trong thư viện stdlib.h Hàm này trả vềmột số nguyên có kiểu dữ liệu là int.Tuy nhiên, hàm rand không random ra sốmới khi chạy lại code Để có thể tạo ra số ngẫu nhiên mới cần kết hợp với hàmsrand trong phần main, và kết hợp với hàm time trong thư viện time.h
Sau đó để tạo hàm sinh số ngẫu nhiên trong một đoạn dựa vào phép toán chia
dư phép toán chia dư (%) của mọi số bất kỳ(a) cho một số b cố định: a % b sẽcho ra giá trị thuộc đoạn [0, b-1]
Để khởi tạo giá trị cho các biến của cấu trúc dữ liệu car, hàm sau sẽ khởitạo các giá trị một cách ngẫu nhiên dựa vào hàm random:
Trang 7kiểu dữ liệu car, con trỏ này sẽ trỏ tới các biến như loaiXe, soDangKy của xe.
Trong hàm thongtinxe sử dụng cấu trúc swich-case, biến r sẽ nhận giá trịngẫu nhiên từ 1 tới 4, khi đó nếu r trùng với bất kì case nào thì biến loaiXe sẽnhận giá trị tương ứng với case đó, sau đó hàm random tiếp tục sinh số ngẫunhiên từ 1 đến 100 để gán giá trị cho biến soDangKy
Flow chart:
Trang 8Hình 1: Sơ đồ tiến trình hàm thongtinxe.
Trang 92.2.Các chức năng của hệ thống:
- Khởi tạo thông tin xe
- Khởi tạo hàng đợi
- Kiểm tra hàng đợi rỗng, đầy
- Khởi tạo số lượng xe vào hàng đợi (từ 0 đến 3 xe)
- Thêm xe vào cuối hàng đợi, đếm số lượng xe vào hàng đợi
- Đếm số lượng xe trong hàng đợi, nếu hàng đợi đầy không cho xe tiếptục vào, nếu hàng đợi rỗng tiếp tục cho xe vào
- Lấy xe ra khỏi hàng đợi ở vị trí đầu hàng
- Lấy thông tin xe khi ra khỏi hàng đợi, đếm số lượng xe còn lại tronghàng đợi
- In thông tin xe trong hàng đợi
3.Giải thích lý do sử dụng các cấu trúc dữ liệu để
mô hình hóa các đối tượng dữ liệu trong hệ thống:
3.1.Dùng hàng đợi để mô hình hóa trạm thu phí:
Dùng cấu trúc dữ liệu hàng đợi để mô hình hóa các đối tượng dữ liệutrong trạm thu phí là một trong những cách tốt để mô hình hóa được các đốitượng dữ liệu vì:
Hàng đợi là một danh sách thêm vào ở đầu này và lấy ra ở đầu kia củadanh sách này Hàng đợi còn được gọi là danh sách FIFO (Fist-In Fist-Out), tức
là thêm vào trước, lấy ra trước Điều đó tương ứng với một trạm thu phí trongthực tế Trạm thu phí ở thực tế sẽ có một đầu vào và một đầu ra, mỗi xe vàotrong đầu tiên sẽ ra ở đầu còn lại đầu tiên Vì sự tương đồng này nên việc mô tảcác đối tượng dữ liệu và cài đặt các hoạt động của trạm thu phí cũng dễ dànghơn
3.2.Dùng danh sách liên kết để biểu diễn
thông tin xe trong trạm:
Đối với danh sách các loại xe và thông tin của từng xe trong trạm thuphí sẽ được cài đặt bởi danh sách liên kết vì:
Các phần tử danh sách có thể được chèn hay xóa một cách dễ dàng màkhông cần phân bổ lại hoặc sắp xếp lại toàn bộ cấu trúc vì các mục dữ liệu
không cần được lưu trữliên tụctrong bộ nhớ hay trên đĩa, trong khi tái cấu trúcmột mảng tạithời gian chạylà một hoạt động tốn kém hơn nhiều Danh sáchliên kết cho phép chèn hay xóa nút tại bất kì điểm nào trong danh sách
Mặc khác, vì bản thân danh sách liên kết được liên kết đơn giản nênkhông cho phép truy cập ngẫu nhiên tới dữ liệu hoặc bất kì hình thức đánh chỉ
Trang 10mục hiệu quả nào, nhiều toán tử cơ bản như lấy nút cuối cùng của danh sách,tìm một nút có chứa dữ liệu đã cho, hay tìm vị trí của nút để chèn một nút mới
sẽ yêu cầu lặp qua hầu hết hoặc tất cả các phần tử của danh sách
Tuy nhiên trong chương trình không cần truy cập tới ngẫu nhiên mộtphần tử, hay tìm kiếm trong danh sách mà chỉ quên tâm tới việc thêm và xóanên việc sử dụng danh sách liên kết thay cho mảng cũng dễ dàng hơn
4.Giải thích cài đặt các cấu trúc dữ liệu:
4.1.Cấu trúc dữ liệu danh sách liên kết
Danh sách liên kết có đặt điểm là hai phần tử kế tiếp nhau không lưu kếtiếp nhau trong bộ nhớ
B Cấu trúc dữ liệu của phần tử:
Fist
Hình 2: Danh sách liên kết đơn Fist
Data Next
Trang 11Một phần tử của danh sách có các thuộc tính:
- Data: chứa nội dung dữ liệu của phần tử, thường là kiểu số
1 Empty(Q) Hàm trả về true nếu hàng Q rỗng và false nếu không
2 Enqueue(x, Q) Thêm đối tượng x vào đuôi hàng Q
3 Dequeue(Q) Loại đối tượng đứng ở đầu hàng Q
4 GetHead(Q) Hàm trả về đối tượng đứng ở đầu hàng Q, còn hàng Qthì không thay đổi
Ví dụ Nếu Q = (a, b, c, d) và a ở đầu hàng, d ở đuôi hàng, thì khi thựchiện phép toán Enqueue(e, Q) ta nhận được Q = (a, b, c, d, e), với e đứng ởđuôi hàng, nếu sau đó thực hiện phép toán Dequeue(Q), ta sẽ có Q = (b, c, d, e)
và b trở thành phần tử đứng ở đầu hàng
Với các phép toán Enqueue và Dequeue xác định như trên thì đối
tượng vào hàng trước sẽ ra khỏi hàng trước Vì lý do đó mà hàng đợi được gọi
là cấu trúc dữ liệu FIFO (viết tắt của cụm từ First- In First- Out) Điều này đốilập với ngăn xếp, trong ngăn xếp đối tượng ra khỏi ngăn xếp là đối tượng saucùng được đặt vào ngăn xếp
Trang 12Hàng đợi sẽ được sử dụng trong bất kỳ hoàn cảnh nào mà chúng ta cần
xử lý các đối tượng theo trình tự FIFO Cuối chương này chúng ta sẽ trình bàymột ứng dụng của hàng đợi trong mô phỏng một hệ phục vụ Nhưng trước hếtchúng ta cần nghiên cứu các phương pháp cài đặt hàng đợi Cũng như ngăn xếp,chúng ta có thể cài đặt hàng đợi bởi mảng hoặc bởi DSLK
B Cài đặt hàng đợi bởi danh sách liên kết:
Cũng như ngăn xếp, chúng ta có thể cài đặt hàng đợi bởi DSLK Vớingăn xếp, chúng ta chỉ cần truy cập tới phần tử ở đỉnh ngăn xếp, nên chỉ cầnmột con trỏ ngoài top trỏ tới đầu DSLK (xem hình 6.3) Nhưng với hàng đợi,chúng ta cần phải truy cập tới cả phần tử ở đầu hàng và phần tử ở đuôi hàng, vìvậy chúng ta cần sử dụng hai con trỏ ngoài: con trỏ front trỏ tới thành
phần đầu DSLK, tại đó lưu phần tử ở đầu hàng, và con trỏ rear trỏ tới thànhphần cuối cùng của DSLK, tại đó lưu phần tử ở đuôi hàng, như trong hình
front
rear
Hình 3: Hàng đợi là một danh sách liên kết
C Cấu trúc dữ liệu của hàng đợi:
Hàng đợi có các thuộc tính sau:
- Front: con trỏ đầu lấy ra của hàng đợi, có kiểu con trỏ phần tử hoặckiểu của phần tử
-Rear: con trỏ đầu thêm vào của hàng đợi, có kiểu con trỏ phần tử hoặckiểu của phần tử
-Count: số phần tử hiện tại của hàng đợi
Code:
Trang 13Alogrithm Enqueue(ref queue, theInfo)
Tạo phần tử mới p có khóa là theInfoIf(queue rỗng) then
Đầu lấy ra front là pElse
Phần tử cuối cùng trỏ pEnd if
Đầu thêm vào rear là pTăng số phần tử hiện tạiEnd Enqueue
5.2.Chức năng lấy xe ra ở đầu hàng đợi:
Rear = NULLEnd if
Front là phần tử sau pHủy bỏ phần tử pEnd if
Giam số phần tử hiện tai
Trang 14End ifEnd Display
6.Trình bày và giải thích chương trinh được viết
đề cài đặt các thuật toán:
6.1 Các chương trình khởi tạo:
A Khởi tạo danh sách liên kết:
Trang 15thoát khỏi chương trình tại đây Nếu có thể cấp phát được bộ nhớ thì biến contrỏ xe của p nhận data làm dữ liệu Phần next của p trỏ tới null.
B Khởi tạo hàng đợi rỗng và hàm kiểm tra hàng đợi:
voidInIt(Queue&queue)
{
queue.front=NULL;
queue.rear=NULL;
đó có nghĩa là con trỏ đó chưa trỏ đến địa chỉ nào cả
Hàm IsEmpty và IsFull kiểm tra hàng đợi đang rỗng hay đầy Việc nàyrất cần thiết cho thuật toán thêm vào hàng đợi hay lấy ra khỏi hàng đợi Haihàm này kiểm tra dựa vào hai con trỏ front (trỏ vào phần tử đầu tiên của hàngđợi) và con trỏ count (đếm số lượng phần tử của hàng đợi)
6.2.Chương trình cài đặt các thuật toán thêm vào và lấy ra khỏi hàng đợi:
A Thêm khóa vào hàng đợi:
voidEnQueue(Queue& queue,carlist*p)
{
if(IsEmty(queue))
{
queue.front=p;
Trang 16p và sau đó chuyển p thành rear.
Ví Dụ: Nếu hàng đợi rỗng ta thêm vào hàng đợi phần tử xe tải như sau:Front
Rear
Hình 4: hàng đợi có một phần tửNếu hàng đợi không rỗng mà chứa các phần tử xe con, xe khách ta thêm xe tảivào hàng đợi như sau:
Trang 17Quá trình thêm khóa vào hàng đợi của ví dụ trên như sau:
- Tạo phần tử p có nội dung là xe tải
- Nếu hàng đợi rỗng, đầu lấy ra front là p
- Nếu hàng đợi khác rỗng, phần tử cuối cùng trỏ p
- Đầu thêm vào rear là p: p là phần tử cuối cùng
- Tăng số phần tử của hiện tại
Hàm CarIn sẽ sữ dụng thuật toán Enqueue để thêm xe vào cũng nhưkiểm soát số lượng xe vào, hàm gọi hàm random sau đó dựa trên số lượng xe
để thực hiện thêm vào, hàm cũng sẽ kiểm tra xem hàng đợi đã đầy chưa, nếu đãđầy thì ngừng
voidCarIn(Queue&queue)
B Lấy khóa từ hàng đợi:
Hàm CarOut là hàm xây dựng dựa trên thuật toán Dequeue, do yêu cầu
đề bài là xe ra khỏi trạm thì lưu lại thông tin xe, nên hàm CarOut bao gồm haicông việc là lấy xe ra khỏi hàng đợi và in thông tin xe
Sau khi lấy xe ra khỏi hàng đợi hàm CarOut sẽ in ra thông tin xe
voidCarOut(Queue&queue)
{
cout <<"So luong xe ra: 1"<<endl;
cout <<"Thong tin xe ra: "<<endl;
if(IsEmty(queue))
exit(1);
else
{
if(queue.front==queue.rear)
queue.rear=queue.front=NULL;
queue.front=p->next;
Trang 18cout<<"Loai xe: "<<p->xe->loaiXe<<endl
<<" So dang ky: "<<p->xe->soDangKy<<endl;
deletep;
queue.cout ;
}
cout <<"======================================="<<endl;}
Nếu hàng đợi rỗng thì ta không thể lấy khóa ra khỏi hàng đợi Nếu hàngđợi chỉ có một khóa thì sau khi lấy khóa từ hàng đợi, hàng đợi là rỗng: đầu lấy
ra front là null, đầu thêm vào rear là null
Nếu hàng đợi có nhiều hơn một khóa, sau khi lấy khóa ra khỏi hàng đợiđầu thêm vào rear không bị thay đổi
Ví dụ: Trong hàng đợi có duy nhất phần tử xe con để lấy xe con ra khỏihàng đợi ta làm như sau:
FrontRear
Front
Rear
Hình 6: xóa phần tử duy nhất của hàng đợiNếu trong hàng đợi có hai phần tử là xe con và xe khách, lấy xe con ra ngoàinhư sau:
Front
Xe con
Xe con
Trang 19->
Rear
Hình 7: Xóa một phần tử của hàng đợi có nhiều phần tử
Quá trình lấy xe con ra khỏi hàng đợi trong ví dụ trên được thực hiện như sau:
- p là phần tử đầu lấy ra front
- Nếu hàng đợi chỉ có xe con thì sau khi lấy ra, hàng đợi là rỗng đầuthêm vào rear là null
- Nếu hàng đợi có nhiều hơn một khóa, sau khi lấy xe con ra từ hàng đợi,đầu lấy ra front là phần tử sau p
- Hủy bỏ phần tử p, giảm số phần tử trong hàng đợi lại
C Lấy thông tin các phần tử trong hàng đợi:
Hàm Display đầu tiên sẽ kiểm tra xem queue có rỗng không, nếukhông thì thực hiện khởi tạo một con trỏ p trỏ vào đầu ra front của hàngđợi, sau đó dùng dòng while để thực hiện việc duyệt tuyến tính qua toàn
bộ hàng đợi cho tới khi p là phần tử cuối cùng của hàng đợi
voidDisPlay(Queuequeue)
cout<<"Thong tin cac xe trong hang doi "<<endl
cout<<"Loai xe "<<p->xe->loaiXe<<endl<<"So dang ky "<<
p->xe->soDangKy<<endl;
p=p->next;
}
cout <<"======================================="<<endl;}
7.Kết quả thực thi chương trình và giải thích:
7.1 Mô tả hoạt động của hệ thống:
Xe khách
Trang 20Đầu tiên hệ thống sẽ dùng hàm random để khởi tạo thông tin xe và sốlượng xe vào trạm, hệ thống sẽ in số lượng xe vào trạm, tiếp theo hệ thống sẽ incác thông tin của từng xe trong trạm, hệ thống sẽ gọi hàm CarOut để thực hiệnthực toán Dequeue, cho xe qua trạm và lấy lại thông tin xe.
Những xe vào đầu tiên sẽ là những xe
ra khỏi trạm đầu tiên, những xe tiếp theo sẽ ratuần tự tiếp theo
Hình 8: Trạm thi phí cho xe vào
Mỗi lần có một xe ra thì có ngẫunhiên 0 tới 3 xe vào trạm
Hệ thống sẽ tiếp tục cho xe vào chotới khi hàng đợi của trạm đầy xe
Hình 9: Trạm thu phí cho xe ra và vào
Trang 21Hình 10: Trạm thu phí bị đầy xeKhi hàng đợi bị đầy trạm thu phí sẽ không cho xe vào nữa, sau đó cholần lượt từng xe qua trạm, mỗi xe qua trạm sẽ được ghi thông tin lại, thực hiệncho tới khi hàng đợi không còn xe, sau đó tiếp tục cho xe vào.
Trang 22Hình 11: Giải quyết hàng đợi bị đầySau khi hàng đợi rỗng thì tiếp tục cho xe vào, nếu hàng đợi tiếp tục đầythì thực hiện lại bước trên, cứ như thế hệ thống sẽ hoạt động liên tục nhờ vàovòng lặp, vòng lặp này sẽ dừng lại khi người dùng ấn một phím bất kì.