1. Trang chủ
  2. » Công Nghệ Thông Tin

Danh sách liên kết đại học quy nhơn

50 4 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 50
Dung lượng 642,32 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

1 1 BÀI 3 DANH SÁCH 3 1 Khái niệm danh sách 3 2 Danh sách và mảng 3 3 Danh sách liên kết đơn 3 4 Cách dạng danh sách liên kết khác 2 3 1 Khái niệm danh sách 3 1 1 Nhắc lại về mảng 3 1 2 Khái niệm danh.

Trang 1

3.1.2 Khái niệm danh sách

3.1.3 Biểu diễn danh sách

Trang 2

3.1.1 Nhắc lại về mảng

phần tử cùng kiểu Không có phép bổ sung phần tử hoặc

loại bỏ phần tử được thực hiện đối với mảng Thường

chỉ có các phép tạo lập (create) mảng, tìm kiếm

(retrieve) và lưu trữ (store) 1 phần tử của mảng Ngoài

giá trị, 1 phần tử của mảng còn được đặc trưng bởi chỉ

số (index) thể hiện thứ tự của phần tử đó trong mảng

– Vectơ, dãy số là mảng 1 chiều, mỗi phần tử aiứng với 1 chỉ số i.

– Ma trận là mảng 2 chiều, mỗi phần tử aijứng với 2 chỉ số i và j.

– Tương tự với mảng 3 chiều, mảng 4 chiều,…, mảng n chiều.

4

Cấu trúc lưu trữ của mảng

• Cấu trúc lưu trữ đơn giản nhất dùng địa chỉ tính được để thực hiện

lưu trữ và tìm kiếm phần tử là mảng 1 chiều hay vectơ

• Cấu trúc lưu trữ của mảng: Thông thường 1 số ô nhớ kế tiếp sẽ

được dành ra để lưu trữ các phần tử của mảng, ta gọi là cách lưu

trữ kế tiếp – (sequential storage allocation).

• Xét t/h mảng 1 chiều có n phần tử và mỗi phần tử của nó có thể

lưu trữ được trong 1 (ô nhớ) thì cần phải dành cho nó n ô nhớ kế

tiếp nhau Do kích thước của mảng đã được xác định nên không

gian nhớ dành ra cũng đã được ấn định trước.

Trang 3

Cấu trúc lưu trữ của mảng

được lưu trữ trong cn từ máy kế tiếp nhau như sau:

Loc(ai) = Lo + c * (i – 1) – Lo được gọi là địa chỉ gốc – đó là địa chỉ ô nhớ đầu tiên trong

miền kế tiếp dành để lưu trữ vectơ, gọi là vectơ lưu trữ.

– f(i) = c * (i – 1) gọi là hàm địa chỉ (address function)

được thực hiện tương tự, nghĩa là vẫn bằng 1 vectơ lưu

trữ kế tiếp như trên

major order), nghĩa là “hết hàng này đến hàng khác”

Loc(aij) = Lo + (i – 1) * m + (j – 1)

Khai báo mảng trong Turbo Pascal

kiểu dữ liệu phần tử là kiểu Ngay_sinh gồm có 3 trường

(Ngay, Thang, Nam)

Var {Khai báo mảng với KDL Ngay_sinh}

Sinh_ngay : Array [1 100] of Ngay_sinh;

Trang 4

Ví dụ danh sách

• CTDL mảng rất thông dụng trong các bài toán tin học:

dãy số, vectơ, ma trận,… do tính đơn giản, dễ sử dụng,

khả năng truy cập trực tiếp và tốc độ truy cập các phần tử

rất nhanh thông qua tên và chỉ số, GT cài đặt đơn giản,…

• Tuy nhiên, trong 1 số t/h CTDL mảng không đáp ứng

được yêu cầu của bài toán, thường là về bộ nhớ lưu trữ

• Ta sẽ xem xét thông qua 2 ví dụ sau:

• Ví dụ 1: Quản lý 1 danh mục điện thoại khoảng 100 phần

tử, mỗi phần tử ứng với 1 đơn vị thuê bao, gồm 3 trường:

– Tên đơn vị hoặc chủ hộ thuê bao.

– Địa chỉ.

– Số điện thoại.

8

Bài toán danh mục điện thoại

• Khai báo danh mục điện thoại bằng CTDL mảng 1 chiều:

Type

Thue_bao = record {Kiểu bản ghi}

Ten, DC, DT : String;

End;

Var {Khai báo mảng với KDL Danh_muc}

Danh_muc : Array [1 100] of Thue_bao;

• Tuy nhiên, nếu dùng NNLT Turbo Pascal, máy sẽ báo lỗi:

“Error 22: Structure too large” : Cấu trúc quá lớn

• Vấn đề đặt ra: Làm sao quản lý được danh mục điện thoại

như vậy Không những thế, số lượng thuê bao thực tế còn

lớn hơn, và mỗi thuê bao còn bao gồm nhiều trường dữ

liệu hơn: Giới tính, tuổi,…

Trang 5

Bài toán cộng 2 đa thức

• Ví dụ 2: Xét bài toán tính (cộng, trừ, nhân, chia) đa thức

của x, y Chẳng hạn cộng 2 đa thức:

(3x2– xy+ y2– x+ 2y ) + (x2+ 4xy- y2- y+ 1)

= (4x2+ 3xy– x + y+ 1)

Khi thực hiện cộng 2 đa thức, phải tìm kiếm từng số hạng, phải

phân biệt được các biến, hệ số, số mũ trong từng số hạng đó.

• Vấn đề đặt ra: Phải biểu diễn đa thức như thế nào để phép

toán trên được thực hiện thuận tiện và có hiệu quả?

• Có thể sử dụng mảng 2 chiều để biểu diễn đa thức:

– Bài toán cộng 2 đa thức trở thành bài toán cộng 2 ma trận.

– Hệ số của số hạng xiyjsẽ được lưu trữ ở phần tử thuộc hàng i+1,

và cột j+1 của ma trận (mảng 2 chiều).

Bài toán cộng 2 đa thức

• Khai báo mảng 2 chiều Da_thuc:

Type {Khai báo KDL Da_thuc là mảng 2 chiều}

Da_thuc = Array [1 100,1 100] of Shortint;

Var {Khai báo các biến với KDL Da_thuc}

a, b, kq : Da_thuc;

• Kết quả:

– Đưa bài toán đa thức về dạng đơn giản, dễ xử lý.

– GT của bài toán được cài đặt đơn giản:

Trang 6

– Nếu hạn chế kích thước ma trận là 4x4 thì số mũ cao nhất của x,

y chỉ có thể là 3, nghĩa là chỉ xử lý được đa thức bậc 3 của x, y.

– Nếu các hệ số không vượt quá 127 (shortint) thì kích thước ma

trận cũng không thể vượt quá 260x260.

– Nếu các hệ số vượt quá 32767 (Integer) thì kích thước ma trận

cũng không thể vượt quá 200x200.

– Trong t/h cộng 2 đa thức:

(x150 – y) + (y - x150) = 0 Khi đó: Ma trận kích thước [151 x 151] gồm toàn các phần tử = 0!

– Không thể cộng được 2 đa thức sau:

(x300– 1) + (y300 + 1) = ???

Trang 7

Kết luận

1 CTDL mảng có tốc độ xử nhanh, dễ xử lý Tuy nhiên,

trong rất nhiều bài toán, CTDL mảng không thể đáp ứng

được yêu cầu, đặc biệt trong các bài toán ma trận thưa

(ví dụ bài toán cộng 2 đa thức), hoặc các bài toán có kích

thước dữ liệu lớn, trong khi bộ nhớ có giới hạn (ví dụ bài

toán danh mục điện thoại)

2 Trong những trường hợp như vậy, CTDL danh sách mà

chúng ta sẽ nghiên cứu sau đây tỏ ra thích hợp hơn so

với CTDL mảng

3.1.2 Khái niệm danh sách

1 số biến động (không cố định) các phần tử cùng kiểu

Phép bổ sung và phép loại bỏ 1 phần tử là các phép

thường xuyên tác động lên danh sách

– Chú ý: Mảng còn được gọi là danh sách đặc.

1 Danh sách: Tập hợp các người đến khám bệnh cho ta hình ảnh

1 danh sách Họ sẽ được khám theo 1 thứ tự nào đó.

2 Phép bổ sung: Số người có lúc tăng lên (do có người mới đến).

3 Phép loại bỏ: Số người có lúc giảm đi (đã khám xong, hoặc bỏ

về vì chờ lâu).

(record), gồm 1 hoặc nhiều trường (fields)

– Ví dụ: Danh mục điện thoại là 1 DSTT, mỗi phần tử là 1 thuê

bao, gồm 3 trường: Tên, Địa chỉ và Điện thoại.

Trang 8

Danh sách tuyến tính

• Danh sách tuyến tính (DSTT - linear list): Là danh sách

mà quan hệ lân cận giữa các phần tử được hiển thị ra

– Mảng 1 chiều chính là t/h đặc biệt của DSTT, đó là hình ảnh của

DSTT xét tại 1 thời điểm nào đó.

– DSTT là 1 danh sách hoặc rỗng (không có phần tử nào) hoặc có

dạng (a1, a2, …, an) với ai(1 ≤ i ≤ n) là các phần tử của danh

sách Trong DSTT luôn tồn tại 1 phần tử đầu a1và 1 phần tử

cuối an.

– Đối với mỗi phần tử aibất kỳ với 1in-1 thì có 1 phần tử ai+1

gọi là phần tử sau ai, và với 2in thì có 1 phần tử ai-1gọi là

phần tử trước ai.

– aiđược gọi là phần tử thứ i của DSTT, n được gọi là độ dài hoặc

kích thước của danh sách, n có giá trị thay đổi.

16

Các phép toán trong danh sách

phép sau đây cũng hay được tác động lên danh sách:

1 Ghép 2 hoặc nhiều danh sách

2 Tách 1 danh sách thành nhiều danh sách

Trang 9

Danh sách và tập tin

• Khái niệm: Tập tin (file) là 1 loại danh sách có kích

thước lớn được lưu trữ ở bộ nhớ ngoài Mỗi phần tử của

tập tin là 1 bản ghi (record), bao gồm nhiều trường (field)

dữ liệu, tương ứng với các thuộc tính khác nhau

– Ví dụ: Tập tin hồ sơ nhân sự của cán bộ trong 1 cơ quan lớn

Phần lý lịch của mỗi cán bộ là 1 bản ghi, nó bao gồm các trường

dữ liệu tương ứng với các thuộc tính như: Họ và tên, ngày sinh,

nơi sinh, quê quán, trình độ văn hoá,…

• Khác với bộ nhớ trong, bộ nhớ ngoài có những đặc điểm

riêng, do đó khi xử lý tập tin cần có những kỹ thuật riêng

• Môn học CTDL và GT chủ yếu nghiên cứu đối với danh

sách có liên quan đến bộ nhớ trong

3.1.3 Biểu diễn danh sách

thể mà máy tính hiểu được để biểu diễn DS, nói cách

khác là lưu trữ các phần tử của DS, đồng thời viết các

đoạn chương trình con mô tả các thao tác cần thiết

tử trong danh sách

1 Cài đặt danh sách bằng mảng 1 chiều

• Có 1 biến nguyên n lưu số phần tử hiện có trong danh sách

Các phần tử trong danh sách được cất giữ trong mảng bằng các

phần tử được đánh số từ 1 tới n

2 Cài đặt danh sách bằng danh sách liên kết

• Cách này lưu trữ địa chỉ của 1 phần tử ở 1 chỗ nào đó trong bộ

nhớ, khi cần xác định sẽ lấy ở đó ra Loại địa chỉ này được gọi

là con trỏ (pointer) hoặc mối nối (link).

Trang 10

Các loại danh sách

DSTT thành 2 loại như sau:

1 Danh sách đặc: Là DSTT mà địa chỉ của các phần tử

trong danh sách được lưu trữ bằng mảng 1 chiều

2 Danh sách liên kết: Là DSTT mà địa chỉ của các phần tử

trong danh sách được lưu trữ bằng con trỏ hay mối nối

liên kết Tuỳ theo cách liên kết mà sẽ có danh sách liên

kết đơn, liên kết vòng, liên kết đôi,…

người ta còn đưa ra 2 loại danh sách đặc biệt là:

Trang 11

3.2.1 Lưu trữ kế tiếp của DSTT

1 chiều để lưu trữ địa chỉ các phần tử của danh sách

tuyến tính cũng được gọi là lưu trữ kế tiếp

là kích thước n thay đổi, còn số phần tử của mảng lưu

trữ là m cố định, nên việc lưu trữ chỉ có thể đảm bảo

được nếu m = Max(n) Nhưng điều này thường không dễ

xác định chính xác mà chỉ là dự đoán

Nhược điểm của lưu trữ kế tiếp

nhiều vì có hiện tượng “giữ chỗ để đấy” mà không dùng

loại bỏ phần tử trong danh sách, mà không phải là phần

tử cuối cùng sẽ đòi hỏi phải dồn hoặc dãn danh sách,

nghĩa là phải dịch chuyển 1 số phần tử lùi xuống (để lấy

chỗ bổ sung) hoặc tiến lên (để lấp chỗ của phần tử đã bị

loại bỏ) và điều này sẽ gây tổn phí nhiều thời gian nếu

các phép toán này được thực hiện thường xuyên

truy cập lại rất rõ

Trang 12

Chèn phần tử vào DSTT

nguyên thứ tự các phần tử còn lại, ta phải:

1 Dồn tất cả các phần tử từ vị trí p + 1 tới vị trí n lên trước

1 vị trí:

2 Giảm n đi 1:

Trang 13

3.2.2 Stack

trong các bài toán tin học là: Ngăn xếp và hàng đợi

mà phép bổ sung và phép loại bỏ luôn luôn thực hiện ở 1

đầu gọi là đỉnh (top)

súng tiểu liên Lắp đạn hay lấy đạn ra cũng chỉ ở 1 đầu

hộp Viên đạn mới nạp vào sẽ nằm ở đỉnh (top), còn viên

nạp vào đầu tiên nằm ở đáy (bottom) Viên đạn nạp vào

sau cùng lại chính là viên đạn lên nòng súng trước tiên

gọi khác: danh sách kiểu LIFO (Last In First Out)

Mô tả Stack

• Stack có thể rỗng hoặc bao gồm 1 số phần tử Minh hoạ

stack như hình vẽ sau:

K 6 5 4 3 2 1

… 5 4 3 2 1

Thêm 1

pt vào Stack

Loại bỏ 1

pt khỏi Stack

T

T

T

Trang 14

Lưu trữ Stack bằng mảng

nhớ kế tiếp Nếu T là địa chỉ của phần tử đỉnh của stack

thì T sẽ có giá trị biến đổi khi stack hoạt động (vì vậy

người ta gọi T là 1 biến trỏ - variable pointer)

khi stack rỗng T = 0

phần tử bị loại khỏi stack, T sẽ giảm đi 1 Có thể thấy

cấu trúc lưu trữ của stack như hình vẽ sau:

1 Việc bổ sung 1 phần tử vào Stack tương đương với việc

thêm 1 phần tử vào cuối mảng

• Thủ tục Push

2 Việc loại bỏ một phần tử khỏi Stack tương đương với

việc loại bỏ một phần tử ở cuối mảng

Trang 15

Procedure Push(V: Integer); {Đẩy 1 giá trị V vào Stack}

Begin {Nếu Stack đã đầy thì không đẩy được thêm vào nữa}

If Last = max Then WriteLn('Stack is full')

Else begin{Nếu không thì thêm một phần tử vào cuối mảng}

Inc(Last); Stack[Last] := V; end;

End;

GT ứng với Stack

{Lấy 1 giá trị ra khỏi Stack, trả về kết quả trong tên hàm}

Function Pop: Integer;

Begin {Stack đang rỗng thì không lấy được}

If Last = 0 then WriteLn('Stack is empty')

Else begin{Lấy phần tử cuối ra khỏi mảng}

Trang 16

3.2.3 Ứng dụng của stack

nguyên tắc “vào sau ra trước” của Stack, người ta ứng

dụng nó trong một số bài toán điển hình như sau:

1 Bài toán đổi cơ số

2 Bài toán định giá biểu thức số học theo ký pháp nghịch

đảo Balan

Bài toán tính N!, bài toán tháp Hà Nội, …

32

Bài toán đổi cơ số

• Bài toán: Dữ liệu lưu trữ trong bộ nhớ của MTĐT đều

được biểu diễn nhị phân Nghĩa là các số xuất hiện trong

chương trình đều phải chuyển từ thập phân sang nhị phân

trước khi thực hiện các phép xử lý

– Đối với hệ thập phân: Khi ta viết 26 thì nó biểu diễn con số mà

giá trị là: 2 * 101+ 6 * 100

– Đối với hệ nhị phân: Khi ta viết 11010 thì nó biểu diễn số thập

phân có giá trị là:

1*24+ 1*23+ 0*22+ 1*21+ 0*20= (26)10

• Quy tắc chuyển đổi: Khi đổi 1 số nguyên từ thập phân

sang nhị phân thì ta dùng phép chia liên tiếp cho 2 đến khi

thương là 0 và viết các số dư (là các chữ số nhị phân 0, 1)

theo chiều ngược lại

Trang 17

Bài toán đổi cơ số

được hiển thị trước Cơ chế sắp xếp này chính là cơ chế

của stack

qua từng phép chia: Khi thực hiện phép chia số thập

phân thì nạp số dư vào stack, sau đó lấy chúng lần lượt

từ stack ra và được số nhị phân

1 Thực hiện phép chia 26 liên tiếp cho 2 đến khi thương = 0

2 Đẩy các số dư thu được vào Stack

3 Lấy các số dư thu được khỏi Stack và viết ra

Trang 18

R := N mod 2; {Tính số dư R trong phép chia N cho 2}

PUSH(R); {Nạp R vào đỉnh stack}

N := N div 2; {Thay N bằng thương của N div 2}

Bài toán ký pháp nghịch đảo Balan

• Bài toán: Nhiệm vụ của bộ dịch là tạo ra các chỉ thị máy

cần thiết để thực hiện các lệnh của chương trình nguồn,

viết bằng NNLT cấp cao Một phần trong nhiệm vụ này là

tạo ra các chỉ thị định giá các biểu thức số học Chẳng hạn

với câu lệnh gán:

X := A * B + C

• Bộ dịch phải tạo ra các chỉ thị máy tương ứng như sau:

– LOA A: Tìm giá trị A lưu trữ trong bộ nhớ, tải nó vào thanh ghi.

– MUL B: Tìm giá trị B và nhân nó với giá trị đang ở thanh ghi.

– ADD C: Tìm giá trị C và cộng nó với giá trị trong thanh ghi.

– STO X: Đưa giá trị trong thanh ghi vào lưu trữ ở vị trí tương

ứng của X, trong bộ nhớ

Trang 19

Bài toán ký pháp nghịch đảo Balan

• Trong các NNLT, biểu thức số học được viết như dạng

thông thường của toán học, nghĩa là theo ký pháp trung

tố Mỗi ký hiệu của phép toán 2 ngôi được đặt giữa 2 toán

hạng, có thể có thêm dấu ngoặc

– Dấu ngoặc là cần thiết vì nếu viết: 5 * 7 – 3

– Thì theo quy ước về thứ tự ưu tiên của phép toán (mà các NNLT

đều chấp nhận) thì biểu thức trên có nghĩa là:

(5 * 7) – 3

• Nhà logic học Ba Lan Lukasiewicz đã đưa ra dạng biểu

thức số học theo ký pháp hậu tố và tiền tố, được gọi là

dạng ký pháp Ba Lan

Bài toán ký pháp nghịch đảo Balan

• Ở dạng hậu tố, các toán tử đi sau các toán hạng Như biểu

• Còn ở dạng tiền tố, các toán tử đi trước các toán hạng

• Ông cũng khẳng định rằng đối với các dạng ký pháp này

dấu ngoặc là không cần thiết

• Nhiều bộ dịch khi định giá biểu thức số học thực hiện:

– B1: Chuyển các bt dạng trung tố có dấu ngoặc sang hậu tố

– B2: Tạo ra các chỉ thị máy để định giá bt ở dạng hậu tố.

– Chú ý: Việc biến đổi từ dạng trung tố sang hậu tố không khó

khăn gì, còn việc định giá theo dạng hậu tố thì dễ dàng hơn,

“máy móc” hơn so với dạng trung tố

Trang 20

Bài toán ký pháp nghịch đảo Balan

• Cách chuyển từ dạng trung tố sang dạng hậu tố:

Trung tố: th1 {tt} th2 Hậu tố: th1 th2 {tt}

• Ví dụ: Xét các định giá của biểu thức sau:

1 5 + 8 4 1 - - *Tương ứng với bt trung tố: (1 + 5) * (8 – (4 – 1))

• Bt này được đọc từ trái sang phải cho tới khi tìm ra 1 toán

tử 2 toán hạng được đọc cuối cùng, trước toán tử này, sẽ

được kết hợp với nó

• B1: Trong bt trên, toán tử đầu tiên được đọc là + và 2 toán

hạng tương ứng với nó là 1 và 5, sau khi kết hợp, bt con

này có giá trị là 6, thay vào bt ban đầu ta có bt rút gọn là:

6 8 4 1 - - *

40

Bài toán ký pháp nghịch đảo Balan

• B2: Toán tử đầu tiên được đọc là - và 2 toán hạng tương

ứng với nó là 4 và 1, sau khi kết hợp, bt con này có giá trị

là 3, thay vào bt ban đầu ta có bt rút gọn là:

6 8 3 - *

• B3: Toán tử đầu tiên được đọc là - và 2 toán hạng tương

ứng với nó là 8 và 3, sau khi kết hợp, bt con này có giá trị

là 5, thay vào bt ban đầu ta có bt rút gọn là:

Trang 21

Bài toán ký pháp nghịch đảo Balan

• Phương pháp định giá biểu thức hậu tố như trên đòi hỏi

phải lưu trữ các toán hạng cho tới khi 1 toán tử được đọc

Tại thời điểm này, 2 toán hạng cuối cùng phải được tìm ra

và kết hợp với toán tử này

• Như vậy, ở đây đã xuất hiện cơ chế hoạt động: “vào sau ra

trước”, nghĩa là ta sẽ phải sử dụng tới stack để lưu trữ các

toán hạng

• Cứ mỗi lần đọc được 1 toán tử thì 2 giá trị sẽ được lấy ra

từ stack để áp đặt toán tử đó lên chúng và kết quả lại được

đẩy vào stack

• Ví dụ: Minh hoạ cơ chế hoạt động Stack đối với biểu thức

hậu tố 5 7 3 - * (tương ứng với biểu thức 5 * (7 – 3))

Minh hoạ cơ chế hoạt động stack

Phần tử X tiếp theo là 1 toán tử (-)

- * 4  T Lấy 3 và 7 từ stack Thực hiện (7 – 3)

Rồi đẩy kết quả vào stack

Phần tử X tiếp theo là 1 toán tử (*)

* 20  T Lấy 4 và 5 từ stack, thực hiện (5 * 4)

Rồi đẩy kết quả vào stack

Trang 22

<Đọc phần tử X tiếp theo trong biểu thức>;

If <X là toán hạng> then PUSH(X)

• Khái niệm: Queue (hàng đợi) là kiểu DSTT mà phép bổ

sung được thực hiện ở 1 đầu, gọi là lối sau (rear), và phép

loại bỏ thực hiện ở 1 đầu khác, gọi là lối trước (front)

• Cơ cấu của queue giống như 1 hàng đợi, chẳng hạn mua

vé xe lửa, khách hàng nào xếp hàng trước sẽ được mua vé

trước, vào ở 1 đầu và ra ở 1 đầu khác

• Vì nguyên tắc “vào trước thì ra trước” như vậy, queue còn

được gọi là danh sách kiểu FIFO (First In First Out)

Last First

Trang 23

Lưu trữ Queue bằng mảng

• Khi mô tả Queue bằng mảng, ta có hai chỉ số First và Last, First

lưu chỉ số phần tử đầu Queue còn Last lưu chỉ số cuối Queue.

• Khởi tạo Queue rỗng: First := 1 và Last := 0;

• Để thêm 1 phần tử vào Queue, ta tăng Last lên 1 và đưa giá trị đó

vào phần tử thứ Last.

• Để loại một phần tử khỏi Queue, ta lấy giá trị ở vị trí First và tăng

First lên 1.

• Khi Last tăng lên hết khoảng chỉ số của mảng thì mảng đã đầy,

không thể đẩy thêm phần tử vào nữa.

• Khi First > Last thì tức là Queue đang rỗng.

• Như vậy chỉ 1 phần của mảng từ vị trí First tới Last được sử dụng

làm Queue

GT ứng với Queue

Program QueueByArray;

Const max = 10000;

Var Queue: Array[1 max] of Integer;

First, Last: Integer;

Procedure QueueInit; {Khởi tạo Queue rỗng}

Begin

First :=1; Last := 0;

End;

Procedure Push(V: Integer); {Đẩy một giá trị V vào Queue}

Begin {Nếu Queue đã đầy thì không đẩy được thêm vào nữa}

If Last = max Then WriteLn(‘Queue is full')

Else begin{Nếu không thì thêm một phần tử vào cuối mảng}

Inc(Last); Queue[Last] := V; end;

End;

Trang 24

GT ứng với Queue

{Lấy 1 giá trị ra khỏi Queue, trả về trong kết quả hàm}

Function Pop: Integer;

Begin {Queue đang rỗng thì không lấy được}

If First > Last then WriteLn(‘Queue is empty')

Else begin{Lấy phần tử đầu ra khỏi mảng}

Nhược điểm khi lưu trữ Q bằng mảng

• Xem lại chương trình cài đặt Stack bằng 1 mảng kích

thước tối đa 10000 phần tử, ta thấy rằng nếu như ta làm

6000 lần Push, rồi 6000 lần Pop, rồi lại 6000 lần Push thì

vẫn không có vấn đề gì xảy ra Lý do là vì chỉ số Last lưu

đỉnh của Stack sẽ được tăng lên 6000 rồi lại giảm đến 0

rồi lại tăng trở lại lên 6000

• Nhưng đối với cách cài đặt Queue như trên thì sẽ gặp

thông báo lỗi tràn mảng, bởi mỗi lần Push, chỉ số cuối

hàng đợi Last cũng tăng lên và không bao giờ bị giảm đi

cả Đó chính là nhược điểm mà ta nói tới khi cài đặt: Chỉ

có các phần tử từ vị trí First tới Last là thuộc Queue, các

phần tử từ vị trí 1 tới First - 1 là vô nghĩa

Trang 25

Khắc phục nhược điểm

• Để khắc phục, mô tả Queue bằng 1 danh sách vòng (biểu

diễn bằng mảng hoặc cấu trúc liên kết), coi như các phần

tử của Queue được xếp quanh vòng theo 1 hướng nào đó

– Các phần tử nằm trên phần cung tròn từ vị trí First tới Last là

các phần tử của Queue.

– Có thêm 1 biến n để lưu số phần tử của Queue.

– Việc thêm 1 phần tử vào Queue tương đương với việc ta dịch chỉ

số Last theo vòng 1 vị trí rồi đặt giá trị mới vào đó.

– Việc loại bỏ 1 phần tử trong Queue tương đương với việc lấy ra

phần tử tại vị trí First rồi dịch chỉ số First theo vòng.

• Lưu ý là trong thao tác Push và Pop phải kiểm tra Queue

tràn hay Queue cạn nên phải cập nhật lại biến n

Mô tả Queue bằng danh sách vòng

Ngày đăng: 24/11/2022, 11:58