- Tốn chi phí tái cấp phát và sao chép vùng nhớ nếu sử dụng
3.5.2. Hàng ñợi (Queue)
Hàng ñợi là một vật chứa (container) các ñối tượng
Làm việc theo cơ chế FIFO (First In First Out) "Vào trước ra trước".
Phòng vé
CTDL Queue hỗ trợ các thao tác:
InitQueue: Khởi tạo hàng ñợi rỗng
IsEmpty: Kiểm tra hàng ñợi rỗng ?
IsFull: Kiểm tra hàng ñợi ñầy ?
EnQueue: Thêm 1 phần tử vào cuối hàng ñợi, có thể làm hàng ñợi ñầy
DeQueue: Lấy ra 1 phần tử từ ñầu Queue, có thể làm Queue rỗng
QueueFront: Kiểm tra phần tử ñầu Queue
65
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương Ðể biểu diễn Queue: Dùng mảng 1 chiều hoặc danh sách liên kết.
Mảng 1 chiều Danh sách liên kết ñơn
- Viết chương trình dễ dàng, nhanh chóng nhanh chóng
- Bị hạn chế do số lượng phần tửcố ñịnh cố ñịnh
- Tốn chi phí tái cấp phát và saochép vùng nhớ nếu sử dụng chép vùng nhớ nếu sử dụng
mảng ñộng
Phức tạp khi triển khai chương trình
Không bị cố ñịnh về số phần tử, phụ thuộc vào bộ nhớ
Mảng (QArray) ñể chứa các phần tử.
Số nguyên (QMax)ñể lưu số phần tử tối ña
2 số nguyên (Qfront/QRear) ñể xác ñịnh vị trí ñầu/cuối
Số nguyên (QNumItems) ñể lưu số phần tử hiện có
Hàng ñợi sử dụng mảng 0 1 2 3 4 5 6 Qarray 37 22 15 3 QMax = 7 QNumItems = 4 QFront = 1 QRear = 4
67
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương
// Giả sử Queue chứa các phần tử kiểu nguyên (int) // Khai báo cấu trúc Queue
typedef struct QUEUE { int* QArray; int QMax; int QNumItems; int QFront; int QRear; };
Khi thêm nhiều phần tử sẽ xảy ra hiện tượng “tràn giả”
Giải pháp? Nối dài mảng (mảng ñộng) hay sử dụng một mảng vô cùng lớn? 0 1 2 3 4 5 6 Qarray 37 22 15 3 7 9 QMax = 7 QNumItems = 4 QFront = 1 QRear = 7
69
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương
//Thao tác “Khởi tạo Queue rỗng”:
int InitQueue(QUEUE& q, int MaxItem) {
q.QArray = new int[MaxItem]; if (q.QArray == NULL) return 0; // không ñủ bộ nhớ q.QMax = MaxItem; q.QNumItems = 0; q.QFront = q.QRear = -1; return 1; // thành công }
//Thao tác “Kiểm tra Queue rỗng”: int IsEmpty(QUEUE q) { if (q.QNumItems == 0) return 1; // rỗng return 0; // không rỗng }
//Thao tác “Kiểm tra Queue ñầy”:
int IsFull(QUEUE q) {
if (q.QMax == q.QNumItems) return 1; // ñầy
71
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương
//Thao tác EnQueue: thêm 1 phần tử vào cuối Queue
int EnQueue(QUEUE &q, int newitem) {
if (IsFull(q))
return 0; // Queue ñầy, không thêm vào ñược
q.QRear++;
if (q.QRear==q.QMax) // “tràn giả”
q.QRear = 0; // Quay trở về ñầu mảng
q.QArray[q.QRear] = newitem;
// thêm phần tử vào cuối Queue
if (q.QNumItems==0) q.QFront = 0; q.QNumItems++;
return 1; // Thêm thành công
//Thao tác DeQueue: lấy ra 1 phần tử ở ñầu Queue
int DeQueue(QUEUE &q, int& itemout) {
if (IsEmpty(q))
return 0; // Queue rỗng, không lấy ra ñược
itemout = q.QArray[q.QFront]; // lấy phần tử ñầu ra
q.QFront++;
q.QNumItems--;
if (q.QFront==q.QMax) // nếu ñi hết mảng …
q.QFront = 0; // … quay trở về ñầu mảng
if (q.QNumItems==0) // nếu lấy ra phần tử cuối cùng
q.QFront = q.QRear = -1; // khởi tạo lại Queue
return 1; // Lấy ra thành công
73
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương
//Thao tác QueueFront: Kiểm tra phần tử ở ñầu Queue
int QueueFront(const QUEUE &q, int& itemout) {
if (IsEmpty(q))
return 0; // Queue rỗng, không kiểm tra
// lấy phần tử ñầu ra
itemout = q.QArray[q.QFront]; return 1;
}
//Thao tác QueueRear: Kiểm tra phần tử ở cuối Queue
int QueueRear(const QUEUE &q, int& itemout) {
if (IsEmpty(q))
return 0; // Queue rỗng, không kiểm tra
// lấy phần tử cuối ra
itemout = q.QArray[q.QRear]; return 1;
//Khai báo cấu trúc
typedef struct tagNODE {
int data;
tagNODE* pNext; } NODE, *PNODE;
typedef struct tagQUEUE {
int NumItems;
PNODE pFront, pRear; } QUEUE;
75
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương
Các thao tác cơ bản
int InitQueue(QUEUE& q);
int IsEmpty(const QUEUE& q);
int IsFull(const QUEUE& q);
int EnQueue(QUEUE &q, int newitem);
int DeQueue(QUEUE &q, int& itemout);
int QueueFront(const QUEUE &q, int& itemout);
//Khởi tạo Queue rỗng
int InitQueue(QUEUE& q) {
q.NumItems = 0;
q.pFront = q.pRear = NULL; return 1;
77
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương
//Kiểm tra Queue rỗng
int IsEmpty(const QUEUE& q) {
return (q.NumItems==0); }
//Kiểm tra Queue ñầy
int IsFull(const QUEUE& q) {
PNODE tmp = new NODE; if (tmp==NULL)
return 1; delete tmp; return 0; }
//Thêm 1 phần tử vào cuối Queue
int EnQueue(QUEUE &q, int newitem) {
if (IsFull(q)==1) return 0;
PNODE p = new NODE; p->data = newitem;
p->pNext = NULL;
if (q.pFront==NULL && q.pRear==NULL) q.pFront = q.pRear = p; else { q.pRear->pNext = p; q.pRear = p; }
79
© Dương Thành Phết-www.thayphet.net Khoa KTCN Trường ðH KTKT B.Dương
//Lấy ra 1 phần tử ở ñầu Queue
int DeQueue(QUEUE &q, int& itemout) { if (IsEmpty(q)==1) return 0; PNODE p = q.pFront; q.pFront = p->pNext; itemout = p->data; q.NumItems--; delete p; if (q.NumItems==0) InitQueue(q); return 1; }
//Kiểm tra 1 phần tử ở ñầu Queue
int QueueFront(const QUEUE &q, int& itemout) { if (IsEmpty(q)==1) return 0; itemout = q.pFront->data; return 1; }
//Kiểm tra 1 phần tử ở cuối Queue
int QueueRear(const QUEUE &q, int& itemout) {
if (IsEmpty(q)==1) return 0;
itemout = q.pRear->data; return 1;