4/28/2010
1
Chương 7.
Bài 3. Queue
ĐỖ BÁ LÂM
ViỆN CNTT&TT, TRƯỜNG ĐHBK HÀ NỘI
Nội dung
1. Khái niệm queue
2. Xây dựng queue
2.1. Sử dụng mảng
2.2. Sử dụng danh sách liên kết
2
1. Khái niệm queue
Queue (Hàng đợi)
Là một hàng chờ đợi, xếp hàng (waiting line)
Là một cấu trúc dữ liệu trong đó cho phép sử
dụng cả 2 phía: một phía để thêm và một phía để
lấy ra phần tử
3
4/28/2010
2
lối sau
lối
trước
1. Khái niệm Queue
Dữ liệu được thêm vào ở lối sau
(rear), và lấy ra ở lối trước
(front)
Cấu trúc FIFO (First In First Out)
– Vào trước ra trước
Thao tác
enqueue(Element e)
Element dequeue()
Các thao tác cơ bản của Queue
enQueue: Thêm một phần tử vào Queue
Queue
Enqueue
D
Data
A B
front
rear
A B D
front
rear
Queue
Các thao tác cơ bản của Queue
deQueue: Lấy một phần tử khỏi Queue
Queue
Dequeue
A
Data
B D
front
rear
A B D
front
rear
Queue
4/28/2010
3
Ứng dụng của Queue
Hàng đợi trong các phòng bán vé
Truy nhập vào các thiết bị dùng chung tại
văn phòng (ví dụ máy in)
7
Ghi nhớ
Queue được hình dung như một hàng đợi
bao gồm nhiều nhiều người xếp hàng với 2
thao tác đưa vào và đẩy ra theo nguyên
tắc:
Người nào vào trước sẽ được ra trước –
FIFO (First In First Out)
2. Xây dựng Queue
Lưu trữ được các đối tượng dữ liệu
Xây dựng 2 thao tác Push và Pop theo
nguyên tắc FIFO
Có hai cách cài đặt queue
Sử dụng mảng
Sử dụng danh sách liên kết
4/28/2010
4
2.1. Sử dụng mảng
Biễu diễn Queue dưới dạng mảng Q
Lưu trữ chỉ số phần tử lối trước và lối sau
của Queue qua biến F và R
Khởi tạo F=R=-1
Queue rỗng (empty) F = R = -1
Queue đầy (full) R=MAX-1
0 1 2 MAX-1
F (Front) R (Rear)
2.1. Sử dụng mảng
Để thuận tiện định nghĩa cấu trúc Queue
gồm mảng và 2 biến Front, Rear
#define MAX 100
typedef ElementType;
typedef struct {
ElementType Elements[MaxLength];
//Lưu trữ các chỉ số
int Front, Rear;
} Queue;
Queue Q;
11
2.1. Sử dụng mảng
Khởi tạo Queue
Front = -1
Rear = -1
Khi bổ sung thêm một phần tử vào Queue
Nếu Front=-1 thì gán Front=0
Rear tăng lên 1.
Khi lấy ra một phần tử trong Queue
Nếu Front==Rear thì gán Front = Rear = -1
Ngược lại Front tăng lên 1
12
4/28/2010
5
Enqueue
int EnQueue(ElementType N){
if(Q.Rear==MAX-1)
return 0;
else{
if(Q.Front==-1) Q.Front=0;
Q.Rear=Q.Rear+1;
Q.Elements[Q.Rear]=X;
return 1;
}
}
13
Dequeue
int DeQueue(ElementType *N){
if(Q.Front == -1) return 0;
else{
*N = Q.Element[Q.Front];
if (Q.Front == Q.Rear){
Q.Front = -1; Q.Rear = -1;
}else
Q.Front=Q.Front+1;
return 1; //Dequeue thanh cong
} }
2.1. Sử dụng mảng
Nhược điểm của cách tổ chức lưu trữ này
Hiện tượng ĐẦY (Full) vẫn xảy ra dù mảng Q vẫn
còn chỗ nhưng R = MAX-1
15
0 1 2 MAX-1
F (Front) R (Rear)
4/28/2010
6
EMPTY QUEUE
[1]
[2] [1] [2]
[0] [3] [0] [3]
[5] [4] [5] [4]
front = -1 front = 0
rear = -1 rear = 2
J2
J1
J3
Cải tiến
[1] [2] [1] [2]
[0] [3][0] [3]
[5] [4] [5] [4]
J2 J3
J1 J4
J5
J6 J5
J7
J8 J9
Cải tiến
Thêm vào theo chiều kim đồng hồ
front =0
rear = 4
front =4
rear = 2
2.2. Sử dụng danh sách liên kết
Biểu diễn
Front trỏ tới đầu danh sách
Rear: trỏ tới cuối danh sách
Queue là cấu trúc FIFO (First In First Out)
Thao tác Push, Pop?
18
Rear
Front
4/28/2010
7
2.2. Sử dụng danh sách liên kết
Push
Thêm một nút vào sau nút cuối cùng trong
danh sách
Pop
Lấy giá trị nút đầu tiên trong danh sách
Loại bỏ nút này khỏi danh sách
19
2.2. Sử dụng danh sách liên kết
struct node {
ElemType data;
struct node *next;
};
struct node *Front, *Rear;
//Front, Rear được khai báo
là hai biến toàn cục
7
1
8
\
Front
Rear
void enQueue(ElemType N){
struct node *Temp;
Temp=(struct node *)
malloc(sizeof(struct node));
Temp->data = N;
Temp->next = NULL;
if(Front==NULL){
Front = Temp; Rear = Temp;
}else{
Rear->next = Temp;
Rear = Rear->next;
}}
enQueue
7
1
8
\
Front
45
Temp
Rear
4/28/2010
8
void enQueue(ElemType N){
struct node *Temp;
Temp=(struct node *)
malloc(sizeof(struct node));
Temp->data = N;
Temp->next = NULL;
if(Front==NULL){
Front = Temp; Rear = Temp;
}else{
Rear->next = Temp;
Rear = Rear->next;
}}
enQueue
7
1
8
Front
45
Temp
Rear
void enQueue(ElemType N){
struct node *Temp;
Temp=(struct node *)
malloc(sizeof(struct node));
Temp->data = N;
Temp->next = NULL;
if(Front==NULL){
Front = Temp; Rear = Temp;
}else{
Rear->next = Temp;
Rear = Rear->next;
}}
enQueue
7
1
8
Front
45
Temp
Rear
int deQueue(ElementType *N){
struct node *Temp=Front;
if(Front==NULL) return 0;
else{
*N = Front->data;
if(Front==Rear){
Front = NULL;Rear = NULL;
}else
Front = Front->next;
free(Temp);
return 1; } }
deQueue
7
1
8
Front
45
Rear
Temp
4/28/2010
9
int deQueue(ElementType *N){
struct node *Temp=Front;
if(Front==NULL) return 0;
else{
*N = Front->data;
if(Front==Rear){
Front = NULL;Rear = NULL;
}else
Front = Front->next;
free(Temp);
return 1; } }
deQueue
7
1
8
Front
45
Rear
Temp
int deQueue(ElementType *N){
struct node *Temp=Front;
if(Front==NULL) return 0;
else{
*N = Front->data;
if(Front==Rear){
Front = NULL;Rear = NULL;
}else
Front = Front->next;
free(Temp);
return 1; } }
deQueue
1
8
Front
45
Rear
Temp
Bài tập
Demo dQueue.c
Bài 1. Kiểm tra tính đối xứng của một xâu
Dùng stack: lưu các kí tự của xâu
Dùng Queue: lưu các kí tự của xâu
Lấy lần lượt khỏi stack và queue các phần
tử và so sánh
27
4/28/2010
10
Bài tập
Ví dụ
Đầu vào : MADAM
Bước 1: Đọc xâu từ trái
sang phải, lưu vào trong
Stack và Queue
Bước 2: Lấy lần lượt các
ký tự ra khỏi Stack và
Queue
M A D A M M A D A M
Stack
Queue
top
front
M A D A A D A M
Stack
Queue
top
front
M = M
M A D D A M
Stack Queue
top
front
A= A
Bài tập
Bài 2. Kiểm tra cặp ngoặc
Mỗi dấu “(”, “{”, or “[” đều phải có một dấu đóng tương
ứng “)”, “}”, or “[”
Đúng: ( )(( )){([( )])}
Sai: )(( ))
Sai: ({[ ])}
Viết giải thuật nhận một xâu đầu vào gồm các ký
tự mở , đóng ngoặc. Kiểm tra xâu có hợp lệ
không
29
Thảo luận
30