Tải bản đầy đủ (.pdf) (29 trang)

Cấu Trúc Dữ Liệu Và Giải Thuật Chapter 4.2 Queue Trong Lập Trình

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (657.29 KB, 29 trang )

Phần 2: Hàng đợi (Queue)

1


Hàng đợi ( Queue)

Theo cơ chế FIFO (First In First Out)
 Các đối tượng có thể được thêm vào hàng đợi bất
kỳ lúc nào.
 Chỉ có đối tượng thêm vào đầu tiên mới được
phép lấy ra khỏi hàng đợi.

2


Giới thiệu
Vào, ra dữ liệu:

3


Giới thiệu
Ứng dụng của hàng đợi:
 Khử đệ qui.
 Lưu vết các quá trình tìm kiếm theo chiều rộng
và quay lui, vét cạn
 Quản lý và phân phối tiến trình trong các hệ
điều hành, tổ chức bộ đệm bàn phím, …

4




Biếu diễn Queue
Mảng 1 chiều

Danh sách liên kết
Cấp phát
động!

Kích thước stack
khi quá thiếu, lúc
quá thừa

Push/Pop
khá dễ
dàng

Push / Pop hơi
phức tạp

5


Biểu diễn Queue dùng mảng
Biểu diễn một Queue bằng mảng:
 Mảng một chiều Ary lưu các phần tử dữ liệu.
 Hằng số N cho biết kích thước (số phần tử tối đa)
của hàng đợi.
 Hai biến nguyên front, rear cho biết chỉ số của
đầu và cuối của hàng đợi.


6


Biểu diễn Queue bằng mảng
typedef struct item
{
int data;
};
typedef struct queue
{
int front, rear;
item A[N];
};
7

Cấu trúc một
phần tử dữ liệu

Cấu trúc hàng
đợi


Biểu diễn Queue bằng mảng
Các thao tác cơ bản trên Queue
 Khởi tạo Queue: Init (q)
 Kiểm tra Queue rỗng: IsEmpty (q)
 Kiểm tra Queue đầy: IsFull (q)
 Thêm phần tử vào Queue: Add(q, x)
 Lấy phần tử ra khỏi Queue: Remove (q)


8 179/44


Biểu diễn Queue dùng mảng
 Khởi tạo Queue:
 Lệnh khởi tạo front = 0 và rear = 0 sẽ tạo ra một
queue rỗng.
 Đảm bảo các thao tác trên queue thực hiện đúng đắn.
Thuật toán:
+Vào: Queue cần khởi tạo.
+ Ra: Queue sau khi khởi tao.
B1) Gán front = 0;
rear = -1
BKT) Kết thúc;

Cài đặt:
void Init(queue &q)
{
q.front = 0;
rear = -1;
}
9


Biểu diễn Queue dùng mảng
 Kiểm tra Queue rỗng:
 Được gọi đến trước khi thực hiện thao tác lấy một
phần tử ra khỏi queue.
 Queue rống nếu front = 0 hoặc front > rear.

Thuật toán:
+Vào: Queue cần kiểm tra.
+ Ra: giá trị 0 hoặc 1
B1) if front = 0 or front > rear
then return 1;
else return 0;
BKT) Kết thúc;

Cài đặt:
int IsEmpty(Queue q)
{
if (q.front > q.rear)
return 1;
return 0;
}
10


Biểu diễn Stack dùng mảng
Kiểm tra Queue đầy
 Được gọi đến trước khi thực hiện thao tác đưa một
phần tử vào queue.
 Queue đầy nếu rear= N-1.
Thuật toán:
+Vào: Queue cần kiểm tra.
+ Ra: giá trị 0 hoặc 1
B1) if rear= N-1 then return 1;
else return 0;
BKT) Kết thúc;


11

Cài đặt:
int IsFull (queue q)
{
if (q.rear==N-1)
return 1;
return 0;
}


Biểu diễn Stack dùng mảng
Thêm một phần tử vào queue

 Việc thêm phần tử luôn được thực hiện ở cuối hàng đợi.
Thuật toán
 Vào: Queue q, phần tử dữ liệu x
 Ra: q với phần tử dữ liệu x ở cuối hàng đợi.
B1) Kiểm tra nếu queue đầy thì thực hiện BKT;
Ngược lại, thực hiện B2;
B2) lưu phần tử dữ liệu x vào queue:
2.1) Tăng rear lên 1;
2.2) Giá trị phần tử với chỉ số rear = x;
BKT) Kết thúc;
12


Biểu diễn Queue dùng mảng
Thêm một phần tử vào hàng đợi
Void Add (queue &q, item x){

if (!Full(q)) //Queue chưa đầy
{
q.rear++;
q.A[q.rear] = x;
}
}

13


Biểu diễn Queue dùng mảng
Lấy phần tử ra khỏi queue
Thuật toán
 Vào: Queue q;
 Ra: Giá trị phần tử cuối hàng đợi x.
B1) Kiểm tra nếu queue rỗng thì thực hiện BKT;
Ngược lại, thực hiện B2;
B2) Lấy phần tử ra khỏi hàng đợi
2.1) x  giá trị phần tử ở đầu hàng đợi (front);
2.2) Tăng chỉ số fron lên 1;
BKT) Kết thúc;
14


Biểu diễn Queue dùng mảng
Lấy một phần tử ra khỏi hàng đợi
Cài đặt:
item Remove (queue &q)
{
item x;

if (!Empty(q))
{
item x = q.A[q.front];
q.front++;
return x;
}
}
15


Biểu diễn Queue dùng mảng
Nhận xét:
 Ưu điểm:
• Các thao tác trên queue làm việc với chi phí O(1).
• Việc cài đặt queue thông qua mảng một chiều đơn
giản và khá hiệu quả.

 Hạn chế:
• Giới hạn về kích thước của queue N.
• Giá trị của N có thể quá nhỏ so với nhu cầu thực tế
hoặc quá lớn sẽ làm lãng phí bộ nhớ.

Khắc phục: Sử dụng DSLK đơn để biểu diễn queue
16


Biểu diễn Queue bằng DSLK
Có thể tạo một hàng đợi sử dụng một DSLK đơn.

Phần tử đầu DSKL (pHead) sẽ là phần tử đầu

hàng đợi, phần tử cuối DSKL (pTail) sẽ là phần
tử cuối hàng đợi.
Ñaàu haøng

Cuoái
haøng
a0

a1

a2

17

aN-2

an-1


Biểu diễn Queue bằng DSLK
typedef struct node
{
int data;
node *Next;
};
typedef struct queue
{
node *front, *rear;
};
18



Biểu diễn Queue bằng DSLK
Các thao tác cơ bản trên Queue
 Khởi tạo queue: Init (q)
 Kiểm tra queue rỗng: IsEmpty (q)
 Tạo mới một nút chứa dữ liệu x: CreateNode(x)
 Thêm phần tử vào queue: Add(q, x)
 Lấy phần tử ra khỏi queue: Remove (q)

19 179/44


Biểu diễn Queue dùng mảng
 Khởi tạo Queue:
 Lệnh khởi tạo front = rear = NULL sẽ tạo ra một
queue rỗng.
Thuật toán:
+Vào: Queue cần khởi tạo.
+ Ra: Queue sau khi khởi tao.
B1) Gán front = rear = NULL
BKT) Kết thúc;

20

Cài đặt:
void Init(queue &q)
{
q.front = q.rear = NULL;
}



Biểu diễn Queue dùng mảng
 Kiểm tra Queue rỗng:
 Queue rỗng nếu front = NULL.
Thuật toán:
+Vào: Queue cần kiểm tra.
+ Ra: giá trị 0 hoặc 1
B1) if front = NULL then return 1;
else return 0;
BKT) Kết thúc;

21

Cài đặt:
int IsEmpty(Queue q)
{
if (q.front == NULL)
return 1;
return 0;
}


Biểu diễn Stack dùng DSLK
Tạo mới một nút:
Node* CreateNode (int x) {
Node *p;
p = (Node*) malloc (sizeof(Node));
if (p==NULL) {
printf (“Khong du bo nho!”);

return NULL;
}
p->data=x;
p->next=NULL;
return p;
}

22


Biểu diễn Stack dùng mảng
Thêm một phần tử vào queue

 Việc thêm phần tử luôn được thực hiện ở cuối hàng đợi.
Thuật toán
 Vào: Queue q, phần tử dữ liệu x
 Ra: q với phần tử dữ liệu x ở cuối hàng đợi.
B1) NewNode  Tạo mới nút chứa dữ liệu x;
B2) Nếu tạo nút thành công thì
- Kiểm tra nếu front = NULL thì
front = rear = NewNode

23


Biểu diễn Stack dùng mảng
B3) Ngược lại, chèn vào cuối danh sách:

+ q.rear->Next = NewNode;
+ q.rear = NewNode;

BKT) Kết thúc;

24


Biểu diễn Queue bằng DSLK
Thêm một phần tử vào queue
Cài đặt:
void Add (queue &q, node *NewNode){
if(q.front == NULL){
q.front = NewNode;
q.rear = NewNode;
}
else{
q.rear->Next = NewNode;
q.rear = NewNode;
}
25
}


×