3. HÀNG ĐỢI – Queue
3.2 Các thao tác cơ bản của hàng đợi
3.2.1 Cài đặt hàng đợi bằng mảng
Ta dùng một mảng để chứa các phần tử của hàng, khởi đầu phần tử đầu tiên của hàng được đưa vào vị trí thứ 1 của mảng, phần tử thứ 2 vào vị trí thứ 2 của mảng... Giả sử hàng có n phần tử, ta có First=0 và Last=n-1. Khi xoá một phần tử First tăng lên 1, khi thêm một phần tử Last tăng lên 1. Như vậy hàng có khuynh hướng đi xuống, đến một lúc nào đó ta không thể thêm vào hàng được nữa (Last=maxlength-1) dù mảng còn nhiều chỗ trống (các vị trí trước First) trường hợp này ta gọi là hàng bị tràn. Trong trường hợp toàn bộ mảng đã chứa các phần tử của hàng ta gọi là hàng bị đầy.
Cách khắc phục hàng bị tràn: Dời toàn bộ hàng lên First -1 vị trí, cách này gọi là di chuyển tịnh tiến. Trong trường hợp này ta luôn có First<=Last.
Cách khắc phục này gọi là dùng mảng xoay vòng: Xem mảng như là một vòng tròn nghĩa là khi hàng bị tràn nhưng chưa đầy ta thêm phần tử mới vào vị trí 0 của mảng, thêm một phần tử mới nữa thì thêm vào vị trí 1 (nếu có thể)...Rõ ràng cách làm này First có thể lớn hơn Last.
0 1 1 2 First → 3 4 → 4 5 5 6 6 Last → 7 7
Hàng sau khi dịch chuyển tịnh tiến Hàng tràn
a) Tạo hàng rỗng
Lúc này First và Last không trỏ đến vị trí hợp lệ nào trong mảng vậy ta có thể cho First và Last đều bằng -1.
b) Kiểm tra hàng rỗng
Trong quá trình làm việc ta có thể thêm và xóa các phần tử trong hàng đợi. Rõ ràng, nếu ta có đưa vào hàng đợi một phần tử nào đó thì First >-1. Khi xoá một phần tử ta tăng First lên 1. Hàng rỗng nếu First>Last. Hơn nữa khi mới khởi tạo hàng đợi, tức là First = -1, thì hàng đợi cũng rỗng. Tuy nhiên để phép kiểm tra hàng rỗng đơn giản, ta sẽ làm một phép kiểm tra khi xoá một phần tử của hàng, nếu phần tử bị xoá là phần tử duy nhất trong hàng thì ta đặt lại First=- 1. Vậy hàng rỗng khi và chỉ khi First =-1.
Function Empty: Boolean; Begin
If (First= -1) or (First> Last) then Empty:=true
Else Empty:=false; End;
c) Kiểm tra hàng đợi đầy
Hàng đợi đầy nếu số phần tử hiện có trong hàng bằng số phần tử trong mảng.
Function Full: Boolean; Begin
If Last- First +1 >=N then Full:=true Else Full:=False;
End;
d) Xóa phần tử ra khỏi hàng
Khi xóa một phần tử đầu hàng ta chỉ cần cho First tăng lên 1. Nếu First > Last thì hàng thực chất là hàng đã rỗng.
Procedure Pop; Begin
If Empty then write(‘Hàng rỗng) Else First:=First+1;
End;
Một phần tử khi được thêm vào hàng sẽ nằm kế vị trí Last cũ của hàng. Khi thêm một phần tử vào hàng ta phải xét các trường hợp sau:
Nếu hàng đầy thì báo lỗi không thêm được nữa.
Nếu hàng chưa đầy ta phải xét xem hàng có bị tràn không. Nếu hàng bị tràn ta di chuyển tịnh tiến rồi mới nối thêm phần tử mới vào đuôi hàng ( Last tăng lên 1). Đặc biệt nếu thêm vào hàng rỗng thì ta cho First=0 để First trỏ đúng phần tử đầu tiên của hàng.
Procedure Push(x: Datatype); Begin
If not Full then Begin
If Empty then begin First:=0; Q[First]:=x; Last:=0; end;
If Last= Maxlength-1 then Begin
For i:=First to Last do Q[i- First]:=Q[i]; Last:=Maxlength-First; First:=0; Last:=Last+1: Q[Last]:=x; End; End; End; 3.2.2 Cài đặt hàng đợi bằng DSLK type queuePtr=^node; node = record data: integer; next: queuePtr; end;
var First,back: queuePtr; chon,n: integer;
a) Thêm một phần tử vào Queue
procedure Put(x: integer); var p: queuePtr;
begin new(p); p^.data:= x; p^.next:= NIL; if First=NIl then begin First:=p; back:=p; end else begin back^.next:=p; back:=p;
end; end;
b) Lấy ra một phần tử
function Get: integer; var p: queuePtr;
begin if First=NIL then Get:=0 else begin Get:= First^.data; p:= First; First:= First^.next; dispose(p); end; end;