You are on page 1of 53

Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

TRƯỜNG TCN CƠ ĐIỆN ĐÔNG NAM BỘ

KHOA CÔNG NGHỆ THÔNG TIN

GIÁO TRÌNH
CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

ĐỒNG NAI

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 1
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

MỤC LỤC

LỜI NÓI ĐẦU............................................................................................................4


CHƯƠNG 1: TỔNG QUAN VỀ CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT .........7
1. MỐI QUAN HỆ GIỮA CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT .....................7
1.1. MỐI QUAN HỆ ............................................................................................7
1.2. MỘT SỐ VÍ DỤ MINH HỌA .......................................................................7
2. TIÊU CHUẨN ĐÁNH GIÁ CẤU TRÚC DỮ LIỆU ............................................8
3. CÁC KIỂU DỮ LIỆU CƠ BẢN ..........................................................................8
3.1. KHÁI NIỆM KIỂU DỮ LIỆU.......................................................................8
3.2. CÁC KIỂU DỮ LIỆU CƠ SỞ .......................................................................9
4. CÁC KIỂU DỮ LIỆU CẤU TRÚC......................................................................9
5. KIỂU DỮ LIỆU CON TRỎ ...............................................................................10
6. ĐỘ PHỨC TẠP CỦA THUẬT TOÁN ..............................................................10
7. CÂU HỎI VÀ BÀI TẬP ....................................................................................11
CHƯƠNG 2: ĐỆ QUY VÀ GIẢI THUẬT ĐỆ QUY..............................................13
1. KHÁI NIỆM ĐỆ QUY.......................................................................................13
2. GIẢI THUẬT ĐỆ QUY VÀ CHƯƠNG TRÌNH ĐỆ QUY ................................13
3. ƯU NHƯỢC ĐIỂM CỦA THUẬT TOÁN ĐỆ QUY.........................................13
3.1. ƯU ĐIỂM ...................................................................................................13
3.2. NHƯỢC ĐIỂM ...........................................................................................13
4. MỘT SỐ BÀI TOÁN.........................................................................................13
5. CÂU HỎI VÀ BÀI TẬP ....................................................................................15
CHƯƠNG 3 : DANH SÁCH....................................................................................18
1. DANH SÁCH LIÊN KẾT ĐƠN.........................................................................18
1.1. KHÁI NIỆM DANH SÁCH ........................................................................18
1.2. KHÁI NIỆM DANH SÁCH LIÊN KẾT ĐƠN ............................................18
1.3. TỔ CHỨC DANH SÁCH LIÊN KẾT ĐƠN................................................18
1.4. CÁC THAO TÁC TRÊN DANH SÁCH .....................................................19
2. DANH SÁCH LIÊN KẾT KÉP..........................................................................22
2.1. KHÁI NIỆM DANH SÁCH KÉP................................................................22
2.2. KHAI BÁO DỮ LIỆU CHO DANH SÁCH LIÊN KẾT KÉP .....................23
2.3. CÁC THAO TÁC TRÊN DANH SÁCH LIÊN KẾT KÉP...........................23
3. STACK (NGĂN XẾP) .......................................................................................26
3.1. KHÁI NIỆM NGĂN XẾP ...........................................................................26
3.2. TỔ CHỨC NGĂN XẾP BẰNG DANH SÁCH ...........................................27
3.3. ỨNG DỤNG CỦA NGĂN XẾP..................................................................30
4. HÀNG ĐỢI (QUEUE) .......................................................................................33
Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 2
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

4.1. KHÁI NIỆM HÀNG ĐỢI ...........................................................................33


4.2. TỔ CHỨC HÀNG ĐỢI BẰNG DANH SÁCH LIÊN KẾT .........................34
5. CÂU HỎI VÀ BÀI TẬP ....................................................................................36
CHƯƠNG 4: PHƯƠNG PHÁP SẮP XẾP CƠ BẢN.............................................. 40
1. ĐỊNH NGHĨA BÀI TOÁN SẮP XẾP................................................................40
2. CÁC PHƯƠNG PHÁP SẮP XẾP CƠ BẢN.......................................................40
2.1. PHƯƠNG PHÁP SẮP XẾP CHỌN TRỰC TIẾP (SELECTION SORT) ....40
2.2. PHƯƠNG PHÁP CHÈN TRỰC TIẾP (INSERTION SORT)......................41
2.3. PHƯƠNG PHÁP NỔI BỌT (BUBBLE SORT) ..........................................42
2.4. PHƯƠNG PHÁP ĐỔI CHỖ TRỰC TIẾP...................................................44
2.5. PHƯƠNG PHÁP SẮP XẾP NHANH (QUICK SORT)...............................44
2.6. PHƯƠNG PHÁP SẮP XẾP TRỘN (MERGE SORT).................................46
3. CÂU HỎI VÀ BÀI TẬP ....................................................................................47
CHƯƠNG 5: TÌM KIẾM ........................................................................................ 49
1. TÌM KIẾM TUYẾN TÍNH ................................................................................49
1.1. THUẬT TOÁN TÌM KIẾM TUẦN TỰ ......................................................49
1.2. TÌM KIẾM NHỊ PHÂN ..............................................................................50
2. CÂU HỎI VÀ BÀI TẬP ....................................................................................52
TÀI LIỆU THAM KHẢO ....................................................................................... 53

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 3
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

LỜI NÓI ĐẦU

Cấu trúc dữ liệu và giải thuật là một môn học bắt buộc trong chương trình đào tạo nghề
Quản Trị Mạng. Giáo trình này được hình thành dựa trên nội dung giảng dạy nhiều năm tại
khoa Công Nghệ Thông Tin Trường TCN Cơ Điện Đông Nam Bộ của nhiều Giảng viên.

Nội dung gồm 5 chương:

Chương 1: Trình bày một số kiến thức về cấu trúc dữ liệu và giải thuật;

Chương 2: Trình bày về đệ quy và giải thuật đệ quy;

Chương 3: Danh sách

Chương 4: Các phương pháp sắp xếp

Chương 5: Các thuật toán tìm kiếm

Giáo trình được soạn trên cơ sở chương trình đào tạo của Khoa. Một số kiến thức về
thuật toán và kỹ thuật lập trình sinh viên đã được học trong các môn học trước đó nên
không được đề cập trong giáo trình này. Giáo trình dùng làm tài liệu học tập cho sinh
viên năm thứ hai, học kỳ 2 của năm thứ hai ngành Quản Trị Mạng với thời lượng 75 tiết.

Trong mỗi chương của giáo trình, các kiến thức lý thuyết được trình bày cơ bản, rõ
ràng, được minh hoạ chi tiết cùng với những ứng dụng cụ thể giúp cho người học dễ đọc,
dễ hình dung những ứng dụng của các cấu trúc dữ liệu trong một số ứng dụng điển hình.
Do đó giáo trình có thể dùng làm tài liệu tự học cho những người đã có những kiến thức
cơ bản về thuật toán và lập trình trên một ngôn ngữ lập trình bậc cao. Nội dung trong
giáo trình bám sát những nội dung cơ bản về các cấu trúc dữ liệu mà các chương trình
đào tạo cử nhân Tin học và Công nghệ thông tin yêu cầu. Cuối mỗi chương đều cung cấp
một hệ thống các bài tập từ cơ bản đến nâng cao nhằm giúp cho sinh viên rèn luyện tư
duy, kỹ thuật lập trình và hiểu rõ hơn những nội dung lý thuyết.

Trong giáo trình sử dụng ngôn ngữ lập trình Pascal để minh hoạ các cấu trúc dữ liệu
và thuật toán để giúp sinh viên dễ hình dung hơn trong cài đặt thành chương trình. Các cấu
trúc dữ liệu được tổ chức dưới hình thức bao gói thông tin, mỗi cấu trúc dữ liệu được xem
như một kiểu dữ liệu độc lập. Các thuật toán trình bày dưới dạng ngôn ngữ tự nhiên và
được hoàn chỉnh bằng những thủ tục viết bằng Pascal nên rất thuận tiện cho sinh viên trong
thực hành bằng Pascal hay bất kỳ một ngôn ngữ lập trình bậc cao nào mà mình ưa thích.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 4
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Để hoàn thành giáo trình này tác giả đã nhận được nhiều ý kiến đóng góp và động
viên của các đồng nghiệp.

Do thời gian và khả năng còn hạn chế nên giáo trình không thể tránh khỏi những
khiếm khuyết nhất định. Chúng tôi chân thành và mong đón nhận những ý kiến đóng góp
của độc giả.

Tác giả

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 5
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG I: TỔNG QUAN VỀ CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

NỘI DUNG
Mối quan hệ giữa cấu trúc dữ liệu và giải thuật;
Tiêu chuẩn đánh giá cấu trúc dữ liệu và giải thuật;
Các kiểu dữ liệu cơ bản, kiểu dữ liệu cấu trúc, kiểu dữ liệu con trỏ;
Độ phức tạp của thuật toán;
Câu hỏi và bài tập.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 6
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 1: TỔNG QUAN VỀ CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

Mục tiêu:

- Trình bày được nội dung của: dữ liệu, giải thuật, mối quan hệ giữa cấu trúc
dữ liệu và giải thuật ;

- Trình bày được các kiểu dữ liệu (cơ bản, có cấu trúc, kiểu con trỏ) và đánh
giá được độ phức tạp của thuật toán.

1. MỐI QUAN HỆ GIỮA CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

Trong khi giải một bài toán, thông thường ta chỉ chú trọng đến giải thuật (hay
cách giải của bài toán) mà ít khi quan tâm đến việc tổ chức dữ liệu. Tuy nhiên giữa việc tổ
chức dữ liệu và thuật toán có mối liên hệ chặt chẽ nhau.

1.1. MỐI QUAN HỆ

Theo cách tiếp cận của lập trình cấu trúc, Niklaus Wirth đưa ra công thức thể hiện
được mối liên hệ giữa cấu trúc dữ liệu và giải thuật:

CẤU TRÚC DỮ LIỆU + GIẢI THUẬT = CHƯƠNG TRÌNH

Một thuật toán giải bài toán bao giờ cũng được thao tác trên một cấu trúc dữ liệu
cụ thể và các thao tác phải được cấu trúc dữ liệu đó hỗ trợ.

Khi tổ chức dữ liệu cho bài toán thay đổi thì thuật toán giải cũng phải thay đổi
theo cho phù hợp với cách tổ chức dữ liệu mới. Ngược lại, trong quá trình xây dựng,
hoàn chỉnh thuật toán cũng gợi mở cho người lập trình cách tổ chức dữ liệu phù hợp với
thuật toán và tiết kiệm tài nguyên hệ thống. Chẳng hạn dùng thêm các ô nhớ phụ để lưu
các kết quả trung gian để giảm thời gian tính toán.

Quá trình giải một bài toán trên máy tính là một quá trình hoàn thiện dần cách tổ
chức dữ liệu và thuật toán để tiết kiệm tài nguyên của hệ thống.

1.2. MỘT SỐ VÍ DỤ MINH HỌA

Ví dụ 1. Xét bài toán đổi giá trị hai biến số x,y.

Với bài toán này ta có 2 phương án giải như sau:

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 7
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Phương án 1. Dùng ô nhớ trung gian

tg := x;

x:= y;

y := tg;

Phương án 2. Không dùng biến trung gian.

x := x + y;

y := x - y;

x := x - y;

Qua ví dụ đơn giản trên, ta nhận thấy việc tổ chức dữ liệu khác nhau (dùng hay
không dùng biến trung gian) ảnh hưởng rất lớn đến thuật toán và gần như thay đổi toàn
bộ thuật toán. Hơn nữa nó còn ảnh hưởng đến tính hiệu quả và phạm vi ứng dụng của
thuật toán.

2. TIÊU CHUẨN ĐÁNH GIÁ CẤU TRÚC DỮ LIỆU

Để đánh giá một cấu trúc dữ liệu chúng ta thường dựa vào một số tiêu chí sau:

- Cấu trúc dữ liệu phải tiết kiệm tài nguyên;

- Phải phản ánh đúng thực tế của bài toán;

- Rỏ ràng, dễ dàng trong việc thao tác.

3. CÁC KIỂU DỮ LIỆU CƠ BẢN

3.1. KHÁI NIỆM KIỂU DỮ LIỆU

Mọi dữ liệu lưu trữ trên máy tính đều được biểu diễn dưới dạng các số nhị phân.
Việc sử dụng trực tiếp các số nhị phân trên máy tính là một công việc khó khăn cho
người nlập trình. Chính vì lý do này mà các ngôn ngữ lập trình cấp cao đã xây dựng nên
các kiểu dữ liệu. Một kiểu dữ liệu là sự trừu tượng hóa các thuộc tính bản chất của các
đối tượng trong thực tế và phù hợp với cách tổ chức thông tin trên máy tính, chẳng hạn
như các kiểu số nguyên, số thực, logic,...

Một kiểu dữ liệu T là một bộ T = <V, O>, trong đó V là tập các giá trị hợp lệ của
kiểu T và O là tập các phép toán trên kiểu T.

Ví dụ: Kiểu dữ liệu Byte = <VByte, OByte>, với VByte = {0, 1, ..., 255}, OByte =
Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 8
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

{+, -, *, div, mod, >, >=, <, <=, =, <>}

3.2. CÁC KIỂU DỮ LIỆU CƠ SỞ

Kiểu số nguyên

- Kiểu số nguyên 1 byte

- Kiểu số nguyên 2 bytes

- Kiểu số nguyên 4 bytes

- Kiểu số nguyên thường được thực hiện với các phép toán: O = {+, -, *, /, DIV,
MOD, <, >, <=, >=, =, …}

Kiểu số thực

- Kiểu số thực 4 bytes

- Kiểu số thực 6 bytes

- Kiểu số thực 8 bytes

- Kiểu số thực 10 bytes

- Kiểu số thực thường được thực hiện với các phép toán: O = {+, -, *, /, <, >, <=, >=, =, …}

Kiểu ký tự: Có thể có các kích thước sau:

- Kiểu ký tự byte

- Kiểu ký tự 2 bytes

- Kiểu ký tự thường được thực hiện với các phép toán: O = {+, -, <, >, <=, >=, =, ORD, CHR, …}

- Kiểu chuỗi ký tự: Có kích thước tùy thuộc vào từng ngôn ngữ lập trình

- Kiểu chuỗi ký tự thường được thực hiện với các phép toán: O = {+, <, >, <=, >=, =, Length, Trunc, ..}

Kiểu luận lý: Thường có kích thước 1 byte

Kiểu luận lý thường được thực hiện với các phép toán: O = {NOT, AND, OR, XOR, <, >, <=, >=, =, }

4. CÁC KIỂU DỮ LIỆU CẤU TRÚC

Kiểu dữ liệu có cấu trúc là các kiểu dữ liệu được xây dựng trên cơ sở các kiểu dữ
liệu đã có (có thể lại là một kiểu dữ liệu có cấu trúc khác). Tùy vào từng ngôn ngữ lập
trình song thường có các loại sau:

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 9
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Kiểu mảng hay còn gọi là dãy: kích thước bằng tổng kích thước của các phần tử.

Kiểu bản ghi hay cấu trúc: kích thước bằng tổng kích thước các thành phần (Field).

5. KIỂU DỮ LIỆU CON TRỎ

Các ngôn ngữ lập trình thường cung cấp cho chúng ta một kiểu dữ liệu đặc biệt để
lưu trữ các địa chỉ của bộ nhớ, đó là con trỏ (Pointer). Tùy vào loại con trỏ gần (near
pointer) hay con trỏ xa (far pointer) mà kiểu dữ liệu con trỏ có các kích thước khác nhau:

- Con trỏ gần: 2 bytes

- Con trỏ xa: 4 bytes

6. ĐỘ PHỨC TẠP CỦA THUẬT TOÁN

Việc đánh giá thời gian thực hiện của thuật toán phụ thuộc vào nhiều yếu tố :

- Dữ liệu đầu vào

- Tốc độ của máy tính

- Chương trình dịch và hệ điều hành

Do đó việc đo, đếm chính xác thời gian thực hiện thuật toán là bao nhiêu đơn vị
thời gian gần như không thể thực hiện được. Để có thể so sánh thời gian chạy của các
thuật toán, trên phương diện lý thuyết thời gian thực hiện thuật toán được đánh giá là
một hàm phụ thuộc vào kích thước của dữ liệu vào gọi là độ phức tạp thuật toán.

Để đánh giá độ phức tạp của thuật toán thông thường người ta tính số phép toán cơ
bản thuật toán thực hiện. Các phép toán cơ bản thường dùng để đánh giá như các phép
toán: +, -, *, /, các phép so sánh, phép gán, thao tác đọc, ghi file,... Tùy thuộc vào thuật
toán, độ phức tạp là một hàm phụ thuộc vào kích thước của dữ liệu vào, ký hiệu T(n),
với n là đại lượng đặc trưng cho kích thước của dữ liệu vào. Trong thường hợp thuật toán
thực hiện nhiều phép toán cơ bản ta có thể đánh giá độ phức tạp trên từng loại phép toán
hoặc tổng hợp của các phép toán. Chẳng hạn thuật toán sắp xếp thường được đánh giá
trên 2 phép toán thường dùng là so sánh và phép gán.

Trong nhiều thường hợp, việc tính toán chính xác độ phức tạp thuật toán T(n) là
không thể thực hiện được vì còn tùy thuộc vào sự phân bố của dữ liệu vào. Chẳng hạn
thuật toán tìm một phần tử trong một danh sách cho trước không chỉ phụ thuộc vào số
phần tử của danh sách mà còn phụ thuộc vào vị trí của phần tử cần tìm có trong danh

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 10
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

sách hay không, nếu có thì phụ thuộc vào vị trí của phần tử do đó số phép so sánh phụ
thuộc vào từng danh sách và phần tử cần tìm. Trong những thường hợp như thế này
thông thường độ phức tạp được đánh giá trong trường hợp xấu nhất của dữ liệu vào.
Trong một số tình huống cụ thể có thể tính trung bình hoặc tính theo xác suất.

Ví dụ 1 Thuật toán tìm một phần tử x trong danh sách L có n phần tử bằng cách
tìm tuần tự

TimThay= False;

For i:=1 To n Do

If L[i] = x then

begin

TimThay:=True;

Exit;

End

Độ phức tạp của thuật toán được đánh giá trên 2 phép toán cơ bản là phép so
sánh trong biểu thức điều kiện của lệnh If và phép gán, ký hiệu tương ứng là C(n) và
M(n). Độ phức tạp được đánh giá trong trường hợp "xấu" nhất của dữ liệu vào là dãy số
ở tình trạng thứ tự giảm. Khi đó ta tính được:

Số phép so sánh C(n) = (n-1)n/2

Số phép gán M(n) = 3(n-1)n/2.

7. CÂU HỎI VÀ BÀI TẬP

Câu 1: Trình bày tầm quan trọng của Cấu trúc dữ liệu và Giải thuật đối với người
lập trình?

Câu 2: Các tiêu chuẩn để đánh giá cấu trúc dữ liệu và giải thuật?

Câu 3: Khi xây dựng giải thuật có cần thiết phải quan tâm tới cấu trúc dữ liệu hay
không? Tại sao?

Câu 4: Liệt kê các kiểu dữ liệu cơ sở, các kiểu dữ liệu có cấu trúc trong C, Pascal?

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 11
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 2: ĐỆ QUY VÀ GIẢI THUẬT ĐỆ QUY


NỘI DUNG
Khái niệm đệ quy ;
Giải thuật đệ quy và chương trình đệ quy ;
Ưu nhược điểm của giải thuật đệ quy ;
Một số bài toán minh họa ;
Câu hỏi và bài tập.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 12
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 2: ĐỆ QUY VÀ GIẢI THUẬT ĐỆ QUY

Mục tiêu:

- Trình bày khái niệm được đệ quy;

- Trình bày được giải thuật và chương trình sử dụng giải thuật đệ quy;

- So sánh giải thuật đệ quy với các giải thuật khác để rút ra tính ưu việt hoặc
nhược điểm của giải thuật;

- Sử dụng được với các bài toán đệ quy đơn giản.

Đệ quy (recursion) là một phương pháp lập trình được sử dụng rộng rãi để giải
quyết các bài toán có cấu trúc đệ quy (được định nghĩa đệ quy) các bài toán sử dụng
chiến lược chia để trị, các bài toán tìm kiếm vét cạn quay lui.

1. KHÁI NIỆM ĐỆ QUY

Một thuật toán được gọi là đệ quy nếu nó yêu cầu thực hiện lại chính nó với mức dữ
liệu nhỏ hơn.

2. GIẢI THUẬT ĐỆ QUY VÀ CHƯƠNG TRÌNH ĐỆ QUY

Thuật toán đệ quy phải được mô tả thông qua tên gồm hai phần như sau :

- Phần cơ sở : Không yêu cầu thực hiện lại chính nó;

- Phần đệ quy : Có yêu cầu thực hiện lại chính nó.

 Gắn liền với các bài toán có đặc trưng đệ quy là công thức truy hồi

3. ƯU NHƯỢC ĐIỂM CỦA THUẬT TOÁN ĐỆ QUY

3.1. ƯU ĐIỂM

Mô tả bài toán đơn giản, ngắn gọn và gần như thuật toán bất kỳ đều có thể đưa về
dạng đệ quy.

3.2. NHƯỢC ĐIỂM

- Tốn bộ nhớ ;

- Một thuật toán đệ quy thường khó hình dung thuật toán.

4. MỘT SỐ BÀI TOÁN

Bài toán 1: Tìm ƯCLN của hai số tự nhiên a và b cho trước.


Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 13
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Có nhiều thuật toán khác nhau để giải bài toán này, ở đây ta sử dụng một tính chất
của ƯCLN là: nếu a > b thì ƯCLN(a,b)=ƯCLN(a-b,b). Thuật toán được mô tả như sau:

Function Ucln(a,b); {gỉả thiết b<>0}

If (a=b) or (b=1) then ucln:=b (* phần cơ sở *)

Else (* phần đệ qui *)

If a < b then

t:=a; a:=b; b:=t;

(* đổi vai trò a, b để luôn có a >= b *)

Ucln:=ucln(a-b,b);

Bài toán 2: Định nghĩa các số Fibbonacci như sau: f0=1, f1=1, fn=fn-1+fn-2 với n>1.
Tính fn với n cho trước.

Thuật toán đệ qui sử dụng ngay định nghĩa đệ qui của các số Fibbonacci, vì thế
thuật toán chỉ là diễn đạt lại định nghĩa.

Function Fib(n);

If (n=0) or (n=1) then

Fib:=1

Else Fib:=Fib(n-1)+Fib(n-2);

Bài toán 3: Tháp Hà Nội. Có 3 cột 1, 2, 3. Trên cột 1 có n đĩa bán kính khác nhau
được xếp theo thứ tự đĩa lớn nằm dưới, đĩa nhỏ nằm trên. Các đĩa có thể được chuyển từ
cột này sang cột khác. Qui tắc chuyển như sau:

Mỗi lần chỉ được chuyển 1 đĩa. Không được để đĩa lớn nằm trên đĩa nhỏ.

Viết thuật toán chuyển n đĩa từ cột 1 sang cột 3 dùng cột 2 làm trung gian.

Để giải quyết bài toán ta chỉ cần giả thiết đã chuyển được n -1 đĩa nhỏ nhất từ cột 1
tới cột 2. Khi đó ta chỉ cần chuyển đĩa lớn nhất từ cột 1 tới cột 3 sau đó chuyển n -1 đĩa
từ cột 2 tới cột 3.

Như vậy ta cần một thủ tục có thể chuyển m đĩa nhỏ nhất từ cột i tới cột j. Thủ tục
này sẽ làm việc như sau: đầu tiên chuyển m-1 đĩa từ cột i tới cột 6-i-j, sau đó chuyển 1
đĩa từ cột i tới cột j, cuối cùng chuyển m-1 đĩa từ cột 6-i-j tới cột j.
Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 14
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Mô tả thủ tục như sau:

Procedure ThapHN(m,i,j);

{Chuyển m đĩa nhỏ nhất từ cột i tới cột j}

If m > 0 then

ThapHN(m-1,i,6-i-j);

{chuyển đĩa từ cột i sang cột j}

Writeln(i,’  ‘,j);

ThapHN(m-1,6-i-j,j);

Với bài toán đã cho chỉ việc gọi thủ tục ThapHN(n,1,3).

5. CÂU HỎI VÀ BÀI TẬP

Câu 1: Sử dụng tính chất sau của ƯCLN để đưa ra một thuật toán đệ qui tìm
ƯCLN(a,b): Nếu a>b thì ƯCLN(a,b)=ƯCLN(a mod b,b) và ƯCLN(a,0)=a với a>0. Khử
đệ qui của thuật toán này.

Câu 2: Mô tả thuật toán sắp xếp chèn dạng đệ qui.

Câu 3: Thuật toán sau có đạt được ý định tìm và in ra số lớn nhất trong n số hay
không? Giải thích.

Procedure Max(n);

If n=1 then write(a1)

Else

If an>Max(m-1) then write(an)

Else Max(n-1);

Câu 4: Thuật toán sau nhằm sửa lại thuật toán của bài tập 3. Thuật toán này có đạt
được mục đích không?

Function MaxNew(n);

If n=1 then write(a1); max:=a1;

Else

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 15
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

If an>MaxNew(m-1) then write(an); max:=an;

Else max:=MaxNew(n-1);

Return max;

Câu 5: Viết 2 thuật toán đệ qui tính tổng các số hạng của một dãy số.

Câu 6: Đổi cơ số. Để chuyển biểu diễn của một số từ cơ số b sang cơ số 10 ta có


thể làm như sau: Giả sử ta đã biết cách chuyển một số nguyên với n chữ số trong cơ số b
và ta muốn chuyển một số nguyên có n+1 chữ số. Viết 2 thuật toán đệ qui theo cách tiếp
cận này (một cách gọi đệ qui theo n chữ số đầu, cách kia gọi đệ qui theo n chữ số cuối).

Câu 7: Viết thuật toán đệ qui in ra chuỗi đảo ngược của một chuỗi cho trước.

Câu 8: Cho dãy m số nguyên tuỳ ý. Viết thuật toán đệ qui tìm và gán cho B giá trị
lớn nhất trong dãy, đồng thời tìm và gán cho N giá trị lớn thứ nhì trong dãy.

Câu 9: Hàm f(n) xác định trên tập các số nguyên không âm như sau:

f(0)=0, f(1)=1, f(2n)=f(n), f(2n+1)= f(n)+f(n+1) với n=1, 2, ...

Mô tả hai thuật toán đệ qui và không đệ qui tính f(N) với N cho trước .

Câu 10: *Xét bài toán Josephus: Có một nhóm N người. Để chọn một người đi
làm một nhiệm vụ đặc biệt người ta cho N người này đứng thành vòng tròn. Bắt đầu đếm
từng người từ một vị trí nào đó theo chiều kim đồng hồ. Mỗi khi gặp người thứ M thì loại
người đó ra khỏi vòng tròn. Tiếp tục quá trình đếm cho tới khi chỉ còn lại một người. Đó
chính là người được chọn. Ví dụ với N=9, M=5 và đếm từ 1. Khi đó thứ tự người bị loại
ra lần lượt là: 5, 1, 7, 4, 3, 6, 9, 2. Người còn lại là người thứ 8.

Mô tả một thuật toán đệ qui cho biết người được chọn.

Có thể tìm được một thuật toán không đệ qui giải bài toán này không?

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 16
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 3 : DANH SÁCH


NỘI DUNG
Danh sách liên kết đơn;
Danh sách liên kết kép;
Ngăn xếp;
Hàng đợi;
Câu hỏi và bài tập

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 17
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 3 : DANH SÁCH

Mục tiêu :

- Trình bày được định nghĩa được danh sách liên kết, ngăn xếp, hàng đợi;

- Trình bày được các loại danh sách liên kết;

- Trình bày được cách tổ chức dữ liệu bằng danh sách liên kết ;

- Cài đặt các thao tác trên danh sách liên kết đơn, liên kết kép, ngăn xếp,
hàng đợi.

1. DANH SÁCH LIÊN KẾT ĐƠN

1.1. KHÁI NIỆM DANH SÁCH

Danh sách là một dãy hữu hạn các phần tử cùng loại được xếp theo một thứ tự
tuyến tính.

Danh sách L gồm các phần tử a1, a2, ..., an được ký hiệu: L = (a1, a2, ..., an).

Trong đó n gọi là chiều dài của danh sách, ai gọi là phần tử thứ i của danh sách. a1
gọi là phần tử đầu tiên của danh sách, an gọi là phần tử cuối cùng của danh sách.Nếu
n= 0 thì danh sách được gọi là rỗng.

Một tính chất quan trọng của danh sách là các phần tử được sắp xếp tuyến tính theo
vị trí của chúng trong danh sách. Với n>1, i =1, 2,..., n-1, phần tử ai là phần tử ngay
trước phần tử ai+1 và ai+1 là phần tử ngay sau phần tử ai.

1.2. KHÁI NIỆM DANH SÁCH LIÊN KẾT ĐƠN

Danh sách liên kết là một cách tổ chức dữ liệu cho mô hình danh sách trong đó các
phần tử được liên hệ với nhau nhờ vào vùng liên kết.

Danh sách liên kết sử dụng cơ chế cấp phát động nên thích hợp với các thao tác
thêm vào, loại bỏ, ghép nhiều danh sách.

1.3. TỔ CHỨC DANH SÁCH LIÊN KẾT ĐƠN

Mỗi phần tử của danh sách liên kết gồm hai thành phần:

- Phần Data chứa dữ liệu thực sự của từng phần tử trong danh sách.

- Phần Link dùng để liên kết một phần tử với phần tử ngay sau nó.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 18
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Data Link

Từ một phần tử ta chỉ duy trì một liên kết đến phần tử ngay sau nó nên danh sách
liên kết được tổ chức như vậy được gọi là danh sách liên kết đơn. Trong phần này ta chỉ
xét cấu trúc dữ liệu danh sách liên kết đơn nên không gây nhầm lẫn khi ta gọi là danh
sách liên kết.

Hình ảnh một danh sách liên kết L = (a1, a2, a3, .. ,an) được biểu diễn như sau:

Để quản lý danh sách biểu diễn bởi danh sách liên kết ta chỉ cần quản lý phần tử
đầu tiên của danh sách. Từ phần tử này ta có thể thao tác được với các phần tử của
danh sách nhờ liên kết giữa các phần tử.

1.4. CÁC THAO TÁC TRÊN DANH SÁCH

1.4.1. Khởi tạo danh sách

Procedure Init(var Head ListLink);

Begin

Head:=Nil;

End;

1.4.2. Thêm một phần tử vào danh sách

Thêm phần x vào vị trí p trong danh sách có phần tử đầu tiên là phần tử Head

Hình 2: Thêm một phần tử vào danh sách

Thủ tục thêm một phần tử vào vị trí sau p. Trong thủ tục ta xét trường hợp khi
danh sách rỗng thì phần tử thêm vào chính là phần tử duy nhất của danh sách. Chi tiết
thủ tục như sau:

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 19
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Procedure Insert(var Head:ListLink; x:ElementType; p : ListLink);

var q : ListLink;

Begin

New(q);

q^.Data := x;

if Head = Nil then

begin

q^.Link:=nil; Head:=q;

end

else

begin

q^.Link := p^.Link;

p^.Link := q;

end;

End;

1.4.3. Loại bỏ một phần tử khỏi danh sách

Giả sử cần loại bỏ phần tử ngay sau phần tử ở vị trí p trong danh sách có phần tử
đầu là Head.

Hình 3: Loại bỏ một phần tử khỏi danh sách

Cài đặt

Procedure Delete(var Head : ListLink; p : ListLink);

var q : ListLink;

Begin

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 20
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

q := p^.Link;

if q<>nil then

begin

p^.Link := q^.Link;

Dispose(q);

end;

End;

1.4.4. Tìm một phần tử trong danh sách

Cho danh sách liên kết có phần tử đầu Head. Cần tìm một phần tử có khóKey bằng
một giá trị x cho trước.

Với cách tổ chức dữ liệu của danh sách liên kết, việc truy xuất các phần tử là tuần tự
nên thao tác tìm kiếm phải dùng thuật toán tìm tuần tự.

Thủ tục tìm khóa x trong danh sách Head, kết quả trả về qua giá trị found và vị trí
của phần tử tìm được p

Procedure Search(Head:ListLink; x:KeyType;var found:Boolean; varp:ListLink);

Begin

p:=Head;

found:=false;

While (p^.link<>nil) and not found do

if p^.Data.Key = x then

found:=true

else

p:=p^.link;

End;

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 21
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

1.4.5. Nối hai danh sách

Cho 2 danh sách có phần tử đầu tương ứng là Head1 và Head2. Ghép danh sách
Head2 vào sau
danh sách
Head1.

Để ghép
được danh sách 2 sau danh sách 1 phải tìm được vị trí của phần tử cuối danh sách 1 (nếu
có) và liên kết với phần tử đầu của danh sách thứ 2. Trong trường hợp danh sách 1 rỗng
thì kết quả ghép là danh sách 2.

Hình 4: Nối hai danh sách thành một

Thủ tục nối hai danh sách như sau:


Procedure Concat(var Head1:ListLink; Head2:ListLink);
var p : ListLink;
Begin
If Head1 = nil Then
Head1:=Head2
Else
Begin
p:=Head1;
While p^.Link<>nil Do p:=p^.Link;
p^.Link := Head2;
End;
End;
2. DANH SÁCH LIÊN KẾT KÉP

2.1. KHÁI NIỆM DANH SÁCH KÉP

Danh sách liên kết kép là danh sách liên kết mà việc thao tác trên một phần tử của
nó liên quan đến phần tử ngay trước và ngay sau nó.

Hình 5 : Danh sách liên kết kép

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 22
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

2.2. KHAI BÁO DỮ LIỆU CHO DANH SÁCH LIÊN KẾT KÉP

Vì danh sách liên kết kép có thể duyệt theo cả hai chiều nên cần quản lý cả hai
phần tử đầu và cuối danh sách. Khai báo dữ liệu cho danh sách liên kết kép như sau:

Type

DLink = ^Cell2L;

Cell2L = Record

Data : ElementType;

LLink, RLink : DLink;

End;

List2Link = Record

Left, Right : DLink;

End;

Var l : List2Link;

2.3. CÁC THAO TÁC TRÊN DANH SÁCH LIÊN KẾT KÉP

2.3.1. Khởi tạo danh sách liên kết kép

Procedure Init(var l : List2Link);

Begin

l.Left := nil; l.Right:= nil;

End;

2.3.2. Thêm một phần tử vào trước phần tử ở vị trí p

Hình 6: Thêm một phần tử vào vị trí p trong danh sách liên kết kép

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 23
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Thủ tục thêm một phần tử vào trước phần tử ở vị trí p như sau:
Procedure InsertBefore(var l:List2Link;p:DLink; x:ElementType);
var q,p1 : DLink;
Begin
New(q);
q^.Data:= x;{danh sách rỗng}
if (l.Left=nil) and (l.Right=nil) then
begin
q^.LLink:=nil;
q^.RLink:=nil; l.Left:=q;
l.Right:=q;
end
else
Begin
if l.Left = p then {thêm vào đầu}
begin
q^.LLink:=nil;
q^.RLink:=p;
p^.LLink:=q;
l.Left:=q;
end
else
begin
p1:=p^.LLink;
q^.LLink:=p1;
p1^.Rlink:=q;
q^.RLink:=p;
p^.LLink:=q;
end;
end;
End.

2.3.3. Xóa một phần tử ở vị trí p

Hình 7: Xóa một phần tử ở vị trí p

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 24
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Thủ tục xóa một phần tử ở vị trí p

Procedure Delete(var l : List2Link; p : DLink);

Begin

if l.Left=p then {xóa phần tử đầu}

l.Left := p^.RLink

else

if l.Right=p then {xóa phần tử cuối}

l.Right:=p^.LLink

else

begin

p^.LLink^.RLink:=p^.RLink;

p^.RLink^.LLink:=p^.LLink;

end;

dispose(p);

End;

2.3.4. Duyệt danh sách liên kết kép

Có thể duyệt từ trái sang phải hoặc ngược lại. Thủ tục duyệt từ trái sang phải được
thực hiện như sau:

Procedure Traverse(l : List2Link);


var p : DLink;
Begin
p:=l.Left;
while p<>nil do
begin
Visit(p);
p:=p^.RLink;
end;
End;

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 25
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

3. STACK (NGĂN XẾP)

Trong một số trường hợp chúng ta sử dụng một mô hình dữ liệu nhưng chỉ dùng
một số trong các thao tác trên mô hình đó. Khi đó mô hình dữ liệu cùng với một số phép
toán cụ thể trên mô hình đó gọi là một kiểu dữ liệu trừu tượng (abstract data type). Trong
phần sau ta xét hai kiểu dữ liệu trừu tượng có ứng dụng nhiều trong các thuật toán tin học
là ngăn xếp và hàng đợi.

3.1. KHÁI NIỆM NGĂN XẾP

Ngăn xếp là một dạng danh sách đặc biệt chỉ được thực hiện hai thao tác: thêm
một phần tử vào cuối danh sách (push) và lấy phần tử cuối ra khỏi danh sách (pop).

Hình ảnh ngăn xếp

Hình 8: Hình ảnh ngăn xếp

Như vậy trong một ngăn xếp phần tử đưa vào sau sẽ được lấy ra trước nên còn gọi
là danh sách kiểu LIFO (Last in First out). Vị trí của phần tử cuối cùng của ngăn xếp còn
gọi là đỉnh (top) của ngăn xếp.

Trong các ngôn ngữ lập trình bậc cao bao giờ cũng dành riêng một vùng nhớ gọi
là Stack dùng để lưu lại các giá trị của biến, hằng,... mỗi khi có lời gọi thủ tục, các giá trị
này được lấy lại mỗi khi có một lời gọi thực hiện xong. Việc lưu các giá trị như trên
phải theo nguyên tắc hoạt động của ngăn xếp vì lời gọi thủ tục cuối cùng sẽ kết thúc
trước. Do đó ngăn xếp là một cách tổ chức dữ liệu được dùng nhiều trong các chương
trình chuyển từ đệ quy sang lặp.

Trong các chương trình dịch (compiler) thường phải biến đổi các biểu thức trung tố

thành các biểu thức tương đƣơng ở dạng hậu tố. Chẳng hạn biểu thức (3 +4) * 2 được

chuyển thành 3 4 + 2 *. Việc chuyển các biểu thức từ trung tố thành hậu tố và tính giá trị

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 26
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

các biểu thức hậu tố phải dùng cấu trúc dữ liệu kiểu ngăn xếp để lưu các kết quả trung
gian. Chi tiết các thuật toán này sẽ được trình bày trong phần sau.

Như đã đề cập ở khái niệm của ngăn xếp, các thao tác trên ngăn xếp gồm hai thao
tác cơ bản là :

push(x,S) : đưa phần tử x vào ngăn xếp S.

pop(x) : lấy phần tử ở đỉnh ngăn xếp S ra và lưu vào biến x.

Ngoài ra còn các thao tác bổ sung:

Init(S) : khởi tạo một ngăn xếp S rỗng.

Empty(S) : cho biết ngăn xếp S có rỗng không.

Full(S) : cho biết ngăn xếp S có đầy không.

Clear(S) : làm rỗng ngăn xếp S.

Tương tự như mô hình danh sách, trên ngăn xếp cũng có thể tổ chức bằng mảng và
danh sách liên kết. Trong phần sau trình bày hai cách tổ chức dữ liệu cho ngăn xếp.

3.2. TỔ CHỨC NGĂN XẾP BẰNG DANH SÁCH

3.2.1. Tổ chức ngăn xếp

Một ngăn xếp tổ chức bằng danh sách liên kết cũng giống như những danh sách
khác, trong đó đỉnh của ngăn xếp chính là con trỏ của danh sách liên kết. Hình ảnh
của ngăn xếp S = (a1, a2, ..., an) tổ chức bằng danh sách liên kết như sau:

Hình 9 : Hình ảnh ngăn xếp bằng danh sách

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 27
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

3.2.2. Khai báo

Type

StackLink = ^Cell;

Cell = Record

Data : ElementType; Link : StackLink;

End;

Var

S : StackLink;

3.2.3. Các thao tác trên danh sách

Khởi tạo: Đỉnh ngăn xếp trở đến Nil

Procedure Init(var S : StackLink);

Begin

S := Nil;

End;

Hàm Empty

Function Empty(S : StackLink): Boolean;

Begin

Empty := S = Nil;

End;

Thêm vào một phần tử: thêm phần tử x vào ngăn xếp S

Hình 10: Thêm vào một phần tử: thêm phần tử x vào ngăn xếp S

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 28
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Thủ tục thêm phần tử x vào ngăn xếp S

Procedure Pop(var x:ElementType; var S:StackLink);

var p:StackLink;

Begin

if not Empty(S) then

begin

x := S^.Data; p := S; S:=p^.Link; Dispose(p);

end;

End;

Lấy ra một phần tử từ ngăn xếp.

Hình 11: Lấy một phần tử từ ngăn xếp tổ chức bằng danh sách liên kết

Thủ tục lấy một phần tử từ ngăn xếp tổ chức bằng danh sách liên kết:

Procedure Pop(var x:ElementType; var S:StackLink);


var p:StackLink;
Begin
if not Empty(S) then
begin
x := S^.Data;
p := S;
S:=p^.Link;
Dispose(p);
end;
End;
Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 29
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Làm rỗng ngăn xếp: xóa và thu hồi các ô nhớ.

Procedure Clear(var S:StackLink);

var p : StackLink;

Begin

while not Empty(S) do

begin

p := S; S:=p^.Link; Dispose(p);

end;

End;

3.3. ỨNG DỤNG CỦA NGĂN XẾP

3.3.1. KHỬ ĐỆ QUI

Giải thuật đệ qui là một trong những giải thuật thường dùng trong lập trình, tuy
nhiên các thủ tục đệ qui khi cài đặt trên các ngôn ngữ lập trình phụ thuộc vào kích thước
vùng nhớ dành cho Stack mà cho phép các thủ tục đệ qui được gọi bao nhiêu lần. Hơn
nữa các thủ tục đệ qui dễ cài đặt nhưng khó hình dung chi tiết các bước thực hiện. Một số
dạng thuật toán đệ qui có thể khử đệ qui bằng cách dùng một ngăn xếp để điều khiển quá
trình gọi đệ qui.

3.3.2. TÍNH GIÁ TRỊ CỦA BIỂU THỨC

Tính giá trị của biểu thức là công việc thường làm của các ngôn ngữ lập trình.
Thông thường các ngôn ngữ lập trình tính giá trị biểu thức bằng cách:

- Chuyển biểu thức từ dạng trung tố (infix) sang dạng hậu tố (posfix).

- Tính giá trị biểu thức hậu tố.

Biểu thức trung tố là cách con người thường sử dụng, trong biểu thức trung tố các
phép toán hai ngôi được viết giữa hai toán hạng. Việc tính trực tiếp các biểu thức trung tố
gặp khó khăn vì phải dùng các cặp dấu ngoặc đơn để qui định thứ tự thực hiện các biểu
thức con. Để tính các biểu thức, người Balan đã đưa ra một ký pháp qui định cách viết
các biểu thức (gọi là ký pháp Balan) trong đó các phép toán được đặt sau toán hạng.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 30
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Việc dùng ký pháp Balan không cần dấu ngoặc nhưng vẫn thể hiện được thứ tự ưu tiên
khi tính giá trị biểu thức nên dễ dàng xây dựng thuật toán tính.

Ví dụ: Biểu thức dạng trung tố 3+(5-2)*3/7-4 được viết dưới dạng biểu thức hậu tố :
352-3*7/4+-

Thuật toán chuyển từ biểu thức trung tố sang hậu tố

Giả sử ta có một biểu thức E dạng trung tố trong đó ta có thể phân tích thành
các thành phần của biểu thức là các toán hạng và phép toán.

Dùng một ngăn xếp S mỗi phần tử là phép toán hoặc dấu ngoặc mở. Kết quả đưa
ra biểu thức hậu tố E1.

Thuật toán:
1. Khởi tạo biểu thức E1 rỗng
2. Duyệt lần lượt các thành phần của biểu thức E, với mỗi thành phần x thực hiện
2.1 Nếu x là toán hạng thì nối vào bên phải biểu thức E1
2.2 Nếu x là dấu ngoặc mở thì đưa vào ngăn xếp
2.3 Nếu x là phép toán thì
a. Đọc phần tử y ở đầu ngăn xếp
b. Nếu độ ưu tiên của y cao hơn x thì
Lấy y ra khỏi ngăn xếp
Nối y vào bên phải E1
Lặp lại bước a.
c. Nếu độ ưu tiên của x cao hơn y thì đưa x vào ngăn xếp
2.4 Nếu x là dấu ngoặc đóng thì
a. Đọc phần tử y ở đầu ngăn xếp b. Nếu y là phép toán thì
Lấy y ra khỏi ngăn xếp
Nối y vào bên phải biểu thức E1
Lặp lại bước a.
c. Nếu y là dấu ngoặc mở thì lấy ra khỏi ngăn xếp
3. Lặp lại bước 2 cho đến hết biểu thức E
4. Lấy lần lượt các phần tử của ngăn xếp và nối vào bên phải biểu thức E1
cho đến khi ngăn xếp rỗng.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 31
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Ví dụ: Với biểu thức E = (2+7*3-8)*4-(3+2)*3-2, thuật toán chuyển thành biểu
thức hậu tố thực hiện qua các bước thể hiện qua các kết quả ở bảng sau:

Thành phần của biểu


Ngăn xếp Biểu thức E1
thức E

(
(
( 2
2
(+ 2
+
(+ 27
7
(+* 27
*
(+* 273
3
(- 273*+
-
(- 273*+8
8
273*+8–
)
* 273*+8–
*
* 273*+8–4
4
- 273*+8–4*
-
-( 273*+8–4*
(
-( 273*+8–4*3
3
-(+ 273*+8–4*3
+
-(+ 273*+8–4*32
2
- 273*+8–4*32+
)
-* 273*+8–4*32
*
-* 273*+8–4*323
3
- 273*+8–4*323*-
-
- 273*+8–4*323*-2
2
273*+8–4*323*-2-

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 32
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

4. HÀNG ĐỢI (QUEUE)

4.1. KHÁI NIỆM HÀNG ĐỢI

Hàng đợi là một kiểu dữ liệu trừu tượng xây dựng trên mô hình danh sách với hai
thao tác cơ bản:

+ Thêm một phần tử vào cuối hàng đợi.

+ Lấy phần tử đầu ra khỏi hàng đợi.

Hàng đợi được thực hiện theo nguyên tắc: các phần tử đưa vào trước lấy ra trước nên
còn gọi là danh sách FIFO (First In First Out). Hàng đợi Q = (a1, a2, ..., an) được thể hiện
bằng hình dưới.

Hình 11 : Hình ảnh một hàng đợi

Trong thực tế ta thường gặp những công việc thực hiện theo nguyên tắc của hàng

đợi, chẳng hạn việc đăng ký mua vé tàu, việc chuyển các toa tàu trên một đƣờng sắt,...

Trong máy tính mô hình hàng đợi được dùng khá phổ biến. Những hàng đợi được tạo
ra khi có nhiều hơn một quá trình đòi hỏi được xử lý, chẳng hạn như máy in, ổ đĩa hay bộ
xử lý trung tâm. Khi các quá trình đòi hỏi một tài nguyên, chúng được đặt trong một
hàng đợi để chờ phục vụ. Ví dụ, nhiều máy tính có thể được phân phối để sử dụng một
máy in, và một hàng đợi spool (Simultanous Peripherial Output On Line - đưa ra đồng
thời với quá trình tính toán) được dùng để lập kế hoạch cho các yêu cầu đầu ra theo
kiểu “đến trước được phục vụ trước”. Nếu có một yêu cầu cho máy in và máy in rỗi, nó
sẽ được cấp phát ngay lập tức công việc này. Trong khi in, một số công việc khác có thể
cần đến máy in, chúng được đặt trong spool để chờ đến lượt. Khi công việc hiện thời của
máy in kết thúc, máy in được giải phóng khỏi công việc ấy và được cấp phát cho công
việc đầu tiên trong hàng spool.

Một ứng dụng quan trọng khác của hàng đợi trong máy tính là tổ chức vùng đệm
cho các đầu vào/ra (input/output buffering). Việc truyền thông tin từ một thiết bị vào
hay đến một thiết bị ra là một thao tác tương đối chậm, do đó nếu phải tạm dừng
chương trình trong khi truyền dữ liệu thì ảnh hưởng rất lớn đến tốc độ thực hiện
Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 33
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

chương trình. Một cách giải quyết thường dùng trên máy tính là dùng các phần của
bộ nhớ trong, gọi là vùng đệm (buffer) và việc truyền dữ liệu từ một chương trình sẽ
được truyền qua vùng đệm mà không thao tác trực tiếp với các thiết bị vào/ra. Chẳng
hạn, một chương trình đọc dữ liệu từ một tệp trên đĩa, dữ liệu sẽ được truyền từ đĩa
sang vùng đệm đầu vào trong bộ nhớ chính, trong khi bộ xử lý trung tâm đang thực
hiện một nhiệm vụ khác nào đó. Khi chương trình đòi hỏi dữ liệu, những giá trị tiếp
theo trong hàng đợi này được lấy ra. Trong khi dữ liệu này đang xử lý thì các dữ liệu
khác có thể được truyền từ tệp sang vùng đệm. Rõ ràng vùng đệm phải được thực hiện
theo kiểu vào trước ra trước.

4.2. TỔ CHỨC HÀNG ĐỢI BẰNG DANH SÁCH LIÊN KẾT

4.2.1. Tổ chức

Cũng như ngăn xếp, ta có thể dùng danh sách liên kết để biểu diễn hàng đợi. Do
thao tác thêm vào và lấy ra trên hàng đợi được lấy ra ở hai vị trí khác nhau nên ta dùng
hai con trỏ front và rear để lưu hai vị trí này.

Hình 12: Hình ảnh tổ chức hàng đợi bằng danh sách liên kết

Khai báo kiểu như sau:


Type
ListLink = ^Cell;
Cell = Record
Data : ElementType;
Link : ListLink;
End;
QueueLink = Record
front, rear : ListLink;
End;
Var Q : QueueLink;

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 34
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

4.2.2. Cài đặt các thao tác trên hàng đợi

Khởi tạo

Procedure InitQueue(var Q : QueueLink);

Begin

Q.front:=Nil;

Q.rear:=Nil;

End;

Thêm vào hàng đợi

Hình 13: Thêm vào hàng đợi biểu diễn danh sách bằng liên kết

Procedure AddQueue(x : ElementType; var Q : QueueLink);

var p : ListLink;

Begin

New(p); P^.Data := x; P^.Link := Nil;

If Empty(Q) Then

begin

Q.front:=p; Q.rear:=p;

end

Else

begin

Q.rear^.Link:= p; Q.rear:=p;

end;

End;

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 35
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Lấy một phần tử khỏi hàng đợi

Hình 14: Lấy một phần tử từ hàng đợi biểu diễn bằng danh sách liên kết

Procedure RemoveQueue(var Q:QueueLink;var x:ElementType);

var p : ListLink;

Begin

If not Empty(Q) Then

begin

x:=Q.front^.Data;

P:=Q.front;

Q.front:=p^.Link;

Dispose(p);

If Q.front=Nil Then

Q.rear:=Nil;

end;

End;

5. CÂU HỎI VÀ BÀI TẬP

Câu 1: Bài 1. Cho một dãy số nguyên a1, a2, ..., an. Hãy tổ chức dữ liệu kiểu
danh sách liên kết đơn để lưu dãy số và cài đặt các thủ tục thực hiện các công việc sau:

- Thủ tục thêm một số vào đầu dãy số.

- Thủ tục thêm một số vào cuối dãy số.

- Thủ tục thêm một số vào sau vị trí p.

- Thủ tục sắp xếp một dãy số theo thứ tự tăng.

- Thủ tục thêm một số x vào dãy đã sắp tăng sao cho vẫn giữ được thứ tự.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 36
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

- Xóa một phần tử sau vị trí p.

- Thủ tục tìm-xoá một số x trong dãy số.

Dựa vào các thủ tục trên viết chương trình tổ chức dạng menu cho phép chọn
thực hiện các công việc sau:

- Nhập một dãy số gồm n số.

- Sắp xếp dãy số

- Chèn một số

- Tìm và xóa một số

- Xóa toàn bộ dãy số

- In dãy số lên màn hình

Câu 2: Dùng ngăn xếp khử đệ quy của hàm tính Cnm được viết như sau:

Function combo(n,m :
integer):longint; Begin

If (n=1) or (m=0) or (m=n)


then

Combo:=1

Else

combo:=combo(n-1,m)+combo(n-1.m-1);

End;

Câu 3: (Danh sách liên kết bội) Để quản lý một danh sách các danh sách liên
kết người ta tổ chức dữ liệu dạng danh sách bội. Mỗi phần tử trong danh sách bội quản
lý một danh sách liên kết gồm các thành phần sau :

- Thành phần head trỏ đến một danh sách liên kết đơn.
- Thành phần link liên kết tới danh sách tiếp theo (nếu có) Hãy tổ chức dữ liệu
và trình bày các thuật toán thực hiện.
- Tạo một danh sách bội trống : danh sách chưa có danh sách nào.
- Thêm một danh sách mới (trống) vào đầu danh sách bội.
- Thêm một phần tử x vào đầu danh sách trỏ bởi con trỏ plist trong danh sách bội.
Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 37
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

- Xóa phần tử sau vị trí p trong danh sách plist trong danh sách liên kết bội.
- Xóa danh sách sau danh sách trỏ bởi con trỏ plist trong danh sách bội.
- Tìm một khóa x trong danh sách bội. Kết quả trả về con trỏ trỏ đến ô chứa
phần tử có khóa x tìm được đầu tiên.
- Xóa tất cả các phần tử có khóa x trong danh sách bội.
Cài đặt các thao tác trên cho danh sách bội chứa các số nguyên.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 38
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 4: PHƯƠNG PHÁP SẮP XẾP CƠ BẢN


NỘI DUNG
Định nghĩa bài toán sắp xếp;
Các phương pháp sắp xếp
Phương pháp sắp xếp chèn trực tiếp;
Phương pháp sắp xếp chọn trực tiếp;
Phương pháp sắp xếp nổi bọt;
Phương pháp sắp xếp đổi chỗ trực tiếp;
Phương pháp sắp xếp trộn;
Phương pháp sắp xếp nhanh.
Đánh giá độ phức tạp của những thuật toán sắp xếp;
Câu hỏi và bài tập.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 39
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 4: PHƯƠNG PHÁP SẮP XẾP CƠ BẢN

Mục tiêu:

- Trình bày được bài toán sắp xếp;

- Trình bày được giải thuật, cài đặt được thuật toán, đánh giá độ phức tạp
của thuật toán sắp xếp;

- Giải được các bài toán sắp xếp sử dụng các phương pháp sắp xếp đã
khảo sát.

6. ĐỊNH NGHĨA BÀI TOÁN SẮP XẾP

Sắp xếp là là quá trình tổ chức lại một danh sách các đối tượng theo một thứ tự
nhất định.

Mục đích của sắp xếp là giúp cho việc tìm kiếm trên danh sách các đối tượng
được dễ dàng hơn. Vì vậy sắp xếp là một bài toán cơ bản và được ứng dụng khá rộng
rãi trong các bài toán tin học. Sắp xếp là là quá trình tổ chức lại một danh sách các đối
tượng theo một thứ tự nhất định. Mục đích của sắp xếp là giúp cho việc tìm kiếm trên
danh sách các đối tượng được dễ dàng hơn. Vì vậy sắp xếp là một bài toán cơ bản và
được ứng dụng khá rộng rãi trong các bài toán tin học.

Người ta chia các phương pháp sắp xếp thành hai lớp: sắp xếp trong và sắp xếp
ngoài. Sắp xếp trong được thực hiện trên danh sách các đối tượng được lưu ở bộ nhớ
trong của máy tính dưới dạng mảng. Do đó phương pháp này còn gọi là sắp xếp mảng.
Khi số các đối tượng trong danh sách cần sắp xếp quá lớn, không thể lưu ở bộ nhớ trong
được thì phải lưu ở bộ nhớ ngoài dưới dạng các file. Khi đó phương pháp sắp xếp trong
không thể sử dụng cho các dữ liệu lưu ở bộ nhớ ngoài vì có những khác biệt cơ bản về
các thao tác truy cập các đối tượng. Do đó phải dùng phương pháp khác gọi là sắp xếp
ngoài.

7. CÁC PHƯƠNG PHÁP SẮP XẾP CƠ BẢN

7.1. PHƯƠNG PHÁP SẮP XẾP CHỌN TRỰC TIẾP (SELECTION SORT)

 Có thể mô tả ngắn gọn như sau:

For i:=1 to n-1 do

Chọn phần tử nhỏ nhất chưa đúng vị trí và đặt nó vào vị trí i

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 40
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Khi sử dụng phương pháp sắp xếp chọn ta giả thiết các vị trí từ 1 đến i-1 trong
mảng đã chọn được các phần tử đúng vị trí. Ta chọn phần tử nhỏ nhất chưa đúng vị trí
nằm trong khoảng từ vị trí i đến vị trí n và sắp nó vào vị trí i.

Mô tả chi tiết

Procedure SXChon;

For i:=1 to n-1 do

min:=i;

For j:=i+1 to n do

If A[j] < A[min] then

min:= j; {phần tử tại vị trí min là nhỏ nhất chưa được sắp}

Hoán vị (A[i], A[min])

Ví dụ: Giả sử mảng đã cho là A = (3, 6, 2, 8, 4, 5). Trong mỗi dòng dưới đây là tình
trạng của mảng sau khi kết thúc một vòng lặp ứng với i

i=1 2, 6, 3, 8, 4, 5

i=2 2, 3, 6, 8, 4, 5

i=3 2, 3, 4, 8, 6, 5

i=4 2, 3, 4, 5, 6, 8

i=5 2, 3, 4, 5, 6, 8

7.2. PHƯƠNG PHÁP CHÈN TRỰC TIẾP (INSERTION SORT)

Bài toán : Cho mảng L[1..n], sắp xếp L tăng dần.

Có thể mô tả ngắn gọn như sau

For i:=2 to n do

chèn A[i] vào vị trí thích hợp trong các phần tử A[1],…, A[i-1]

Trong phương pháp này, ở bước thứ i ta có các phần tử từ A[1] đến A[i-1] đã được
sắp thứ tự. Để chèn A[i] vào vị trí thích hợp trong các phần tử A[1],…, A[i-1] ta sẽ tìm vị
trí j nhỏ nhất thỏa mãn A[i] < A[j] và chèn A[i] vào vị trí j. Khi đó các phần tử từ vị trí j

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 41
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

đến i-1 sẽ dịch sang phải 1 vị trí. Trong quá trình tìm vị trí j ta đồng thời dịch các phần tử
lớn hơn A[i] sang phải một vị trí.

Mô tả chi tiết như sau

Procedure SXChen;

For i:=2 to n do

x:=A[i]; j:=i-1;

While (j>0) and (x<A[j]) do

A[j]:= A[j-1]

j:=j-1;

A[j+1] :=x;

Với mỗi i vòng lặp While dừng lại khi j=0 hoặc khi j>0 và x >= A[j]. Nếu j=0 có
nghĩa là x được xếp vào đầu mảng (vị trí j+1). Nếu j>0 thì x được xếp vào sau vị trí j.

Ví dụ: Giả sử mảng đã cho là A = (3, 6, 2, 8, 4, 5). Trong quá trình sắp thứ tự theo
thuật toán sắp xếp chèn, mảng biến đổi như sau (j nhận giá trị sau khi kết thúc vòng lặp
While):

i=2 x=6 j=1 3, 6, 2, 8, 4, 5

i=3 x=2 j=0 2, 3, 6, 8, 4, 5

i=4 x=8 j=3 2, 3, 6, 8, 4, 5

i=5 x=4 j=2 2, 3, 4, 6, 8, 5

i=6 x=5 j=3 2, 3, 4, 5, 6, 8

7.3. PHƯƠNG PHÁP NỔI BỌT (BUBBLE SORT)

Thuật toán sắp xếp bằng cách đổi chỗ trực tiếp được thực hiện bằng cách duyệt
các phần tử trong mảng, nếu hai phần tử liền nhau sai vị trí thì đổi chỗ cho nhau. Sau
mỗi lần duyệt phần tử nhỏ nhất được đưa lên đầu (hoặc phần tử lớn nhất đưa về cuối tùy
thuộc vào cách duyệt từ 1 đến n hay ngược lại). Sau mỗi bước lặp danh sách các phần tử
cần sắp xếp sẽ giảm đi 1.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 42
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Thuật toán sắp xếp nỗi bọt:

1. Xuất phát i=2


2. Duyệt danh sách A[i..n] theo thứ tự ngược từ n đến i, bước thứ j thực hiện
Nếu a[j].Key<a[j-1].Key thì đổi chỗ hai phần tử ở vị trí j và j-1.
3. Tăng i lên 1
4. Lặp lại bước 2 khi i<n
Thủ tục sắp xếp nỗi bọt như sau:
Procedure BubbleSort;
var
i,j:Integer;
tmp:ElementType;
Begin
for i:=2 to n do
for j:=n downto i do
if a[j].Key<a[j-1].Key then
begin
tmp:=a[j]; a[j]:=a[j-1]; a[j-1]:=tmp;
end;
End;

Ví dụ: Giả sử mảng đã cho là A = (4, 6, 3, 8, 2, 5). Trong mỗi dòng dưới đây là tình
trạng của mảng sau khi kết thúc một vòng lặp ứng với i

i=5 4, 3, 6, 2, 5, 8

i=4 3, 4, 2, 5, 6, 8

i=3 3, 2, 4, 5, 6, 5

i=2 2, 3, 4, 5, 8, 6

i=1 2, 3, 4, 5, 6, 8

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 43
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

7.4. PHƯƠNG PHÁP ĐỔI CHỖ TRỰC TIẾP

Phương pháp sắp xếp đổi chỗ trực tiếp ứng với mỗi i, so sánh a[i] với các phần tử
còn lại trong mảng nếu thấy phần tử nào nhỏ hơn thì đổi chỗ a[i] và a[j] cho nhau.

Thủ tục sắp xếp đổi chỗ trực tiếp

Procedure Interchange sort ;

Var i,j,tg integer;

begin

for i=1 to n-1 do

for j=i+1 to n do

if a[i] >a[j] then đổi chỗ a[i]và a[j]

end;

Ví dụ: Giả sử mảng đã cho là A = (4, 6, 3, 8, 2, 5). Trong mỗi dòng dưới đây là tình
trạng của mảng sau khi kết thúc một vòng lặp ứng với i

i=5 4, 3, 6, 2, 5, 8

i=4 3, 4, 2, 5, 6, 8

i=3 3, 2, 4, 5, 6, 5

i=2 2, 3, 4, 5, 8, 6

i=1 2, 3, 4, 5, 6, 8

7.5. PHƯƠNG PHÁP SẮP XẾP NHANH (QUICK SORT)

Khác với sắp xếp trộn, phần không đệ qui của thuật toán này không kết hợp các lời
giải con mà là đi xây dựng các bài toán con.

Bước đầu tiên thuật toán chọn một phần tử trong mảng làm mốc (pivot). Sau đó
mảng được chia thành hai phần ở hai phía của mốc: các phần tử lớn hơn mốc được đưa
sang phải và các phần tử không lớn hơn mốc được đưa sang trái mốc. Nếu bây giờ mỗi
phần được sắp thứ tự nhờ lời gọi đệ qui thì toàn bộ mảng sẽ được sắp thứ tự mà không
cần trộn.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 44
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Lưu ý rằng có nhiều biến thể của thuật toán QuickSort, chủ yếu khác nhau ở
phương pháp chọn phần tử để đặt mốc. Ở đây ta sẽ chọn phần tử đầu tiên của mảng làm
mốc.

Mô tả thuật toán:

Procedure QuickSort(T[i..j]);

If j-i nhỏ then insert(T[i..j])

Else

Datmoc(T[i..j],m);

{sau khi đặt mốc thì T[k]  T[m] với ik<m và T[k] > T[m] với m<kj }

QuickSort(T[i..m-1]); QuickSort(T[m+1..j]);

Trong đó thủ tục Datmoc sẽ chia mảng T thành 2 phần như mong muốn. Ta sẽ thực
hiện điều này bằng cách duyệt mảng T đồng thời từ hai đầu. Dùng 2 biến k và h để duy
trì 2 vị trí duyệt, khởi tạo k:=i và h:=j+1. Tăng k cho đến khi T[k] > p và giảm h cho tới
khi T[h]  p. Khi đó đổi chỗ T[k] và T[h]. Quá trình này còn tiếp tục khi nào mà k<h.
Cuối cùng đổi chỗ T[i] và T[h] để đặt mốc đúng chỗ.

Trong thuật toán này ta đã chọn thuật toán sắp xếp chèn làm thuật toán sắp xếp cơ sở

Thủ tục đặt mốc có thể mô tả như sau :

Procedure Datmoc(T[i..j], var h);

p:=T[i]; k:=i; h:=j+1;

repeat k:=k+1 until (T[k]>p) or (jk);

repeat h:=h-1 until T[h]  p;

while k<h do

Đổi chỗ T[k] và T[h];

repeat k:=k+1 until T[k]>p;

repeat h:=h-1 until T[h]  p;

Đổi chỗ T[i] và T[h];

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 45
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Đánh giá độ phức tạp của thuật toán QuickSort:

Giả thiết mảng đã cho có kích thước n = 2k và giả sử ở mỗi lần đặt mốc mảng được
chia làm hai phần có kích thước gần bằng nhau. Dễ thấy độ phức tạp của thủ tục Datmoc
là n. Gọi thời gian chạy của thuật toán QuickSort với mảng kích thước n là h(n).

Khi đó theo mô tả của thuật toán ta có h(n) = 2h(n/2)+n

Ta có h(n) = 2(2h(n/4)+n/2)+n = 4h(n/4) + 2n = ... = nh(1)+kn =kn

Do đó ta có h(n) = O(n.logn)

7.6. PHƯƠNG PHÁP SẮP XẾP TRỘN (MERGE SORT)

Giả sử T[1..n] là mảng, ta đã biết một số thuật toán sơ cấp sắp xếp mảng với độ
phức tạp là O(n2). Theo cách tiếp cận chia để trị ta sẽ chia T thành hai phần có kích thước
gần bằng nhau và sắp xếp các phần này bằng lời gọi đệ qui, sau đó trộn các kết quả, lưu ý
bảo toàn thứ tự. Công việc chủ yếu chỉ là trộn 2 mảng sắp thứ tự thành 1 mảng sắp thứ
tự. Mô tả thuật toán như sau:

Procedure SXTron(T[i..j]);

If j-i nhỏ then Insert(T)

Else

U:= T[i..(i+j)div 2];V:= T[1+(i+j)div 2 ,,n]

SXTron(U); SXTron(V);

Tron(T,U,V);

Trong đó Insert(T) là thuật toán sắp xếp chèn đã biết, còn Tron(T,U,V) là thủ tục
trộn 2 mảng U, V đã sắp thứ tự thành mảng sắp thứ tự T.

Thuật toán này phù hợp với mô tả tổng quát của kỹ thuật chia để trị, trong đó thao
tác Tron chính là việc kết hợp các lời giải của bài toán con để được lời giải của bài toán
ban đầu.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 46
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

8. CÂU HỎI VÀ BÀI TẬP

Câu 1 : Đánh giá độ phức tạp trong trường hợp tồi nhất của các thuật toán sắp xếp
sơ cấp đã nêu.

Câu 2 : Trong các thuật toán sắp xếp sơ cấp trên, thuật toán nào có tính ổn định?
Giải thích.

Câu 3 : Chạy từng bước các thuật toán sắp xếp đã nêu trên các mảng cụ thể có kích
thước 10.

Câu 4: Mô tả một thuật toán thích hợp sắp xếp một mảng các bit. Cho biết độ phức
tạp của thuật toán được sử dụng.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 47
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 5: TÌM KIẾM


NỘI DUNG
Tìm kiếm tuyến tính;
Tìm kiếm nhị phân;
Câu hỏi và bài tập.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 48
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

CHƯƠNG 5: TÌM KIẾM

1. TÌM KIẾM TUYẾN TÍNH


Tìm kiếm là một thao tác đóng vai trò quan trọng trong nhiều tính toán và được áp
dụng nhiều trong thực tế. Có nhiều yêu cầu tìm kiếm khác nhau cũng như có nhiều thuật
toán tìm kiếm khác nhau. Ta sẽ quan tâm tới một số thuật toán tìm kiếm sơ cấp trên
mảng. Bài toán đặt ra là tìm một phần tử trong mảng A[1..n] cho trước có giá trị bằng T
cho trước. Có thể xét bài toán tổng quát hơn là tìm một phần tử trong mảng A[1..n] cho
trước có tính chất P cho trước.

1.1. THUẬT TOÁN TÌM KIẾM TUẦN TỰ

Để tìm kiếm tuần tự một phần tử T cho trước trong mảng A ta sử dụng một vòng
lặp, tại mỗi bước của vòng lặp ta thao tác với một phần tử xác định của mảng, ở đây cụ
thể là so sánh lần lượt mỗi phần tử của mảng với T (hay kiểm tra xem phần tử tương ứng
có tính chất P hay không). Thao tác này được gọi là duyệt mảng. Việc duyệt mảng được
dừng lại khi bắt gặp một phần tử bằng T hoặc đã so sánh hết các phần tử của mảng. Khi
gặp một phần tử bằng T (hay có tính chất P) ta sẽ ghi nhận sự kiện này.

Mô tả 1 :
Bước 1: i = Vị trí đầu;
Bước 2: Nếu a[i] = x : Tìm thấy. Dừng, vị trí xuất hiện: i
Bước 3 : i = Vị trí kế(i);// xét tiếp phần tử kế trong mảng
Bước 4: Nếu i >Vị trí cuối: //Hết mảng
Không tìm thấy. Dừng.
Ngược lại: Lặp lại Bước 2.

Mô tả 2:

Procedure TimTT(A,T);

Found:= False;

For i:=1 to n do

If A[i]=T then

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 49
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

Found:=True;

Exit;

Biến Found dùng để ghi nhận có phần tử trong mảng bằng T.

Trong trường hợp tổng quát, điều kiện

If A[i]=T

được thay bằng

If A[i] có tính chất P.

1.2. TÌM KIẾM NHỊ PHÂN


Trong tình huống A là mảng sắp thứ tự ta có thuật toán tìm kiếm tốt hơn tìm tuần
tự, đó là tìm kiếm nhị phân. Ý tưởng của thuật toán tìm nhị phân là ta so sánh T với phần
tử ở giữa mảng A, dựa vào kết quả so sánh mà kết thúc hoặc tiếp tục tìm kiếm bằng cách
thu hẹp phạm vi tìm kiếm còn bằng một nửa phạm vi trước đó. Quá trình này được thực
hiện lặp đi lặp lại cho tới khi gặp một phần tử bằng T hoặc phạm vi tìm kiếm là rỗng.

Mô tả 1
Bước 1: left = VTĐ; right = VTC;
Bước 2: Trong khi left  right lặp: //đoạn tìm kiếm chưa rỗng
Bước 2.1: mid = (left+right)/2; // lấy mốc so sánh
Bước 2.2: Nếu a[mid] = x: //Tìm thấy.
Dừng, vị trí xuất hiện: mid
Bước 2.3: Nếu a[mid] > x: //tìm x trong dãy con aleft .. amid -1
right = mid - 1;
Ngược lại //tìm x trong dãy con amid +1 .. aright
left = mid + 1;
//Hết lặp
Bước 3: Dừng, không tìm thấy.

Mô tả thuật toán: Giả sử A[1..n] là mảng sắp thứ tự tăng

Procedure TimNP(A,T);

d:=1; c:=n; co:=false;

While (d<=c) and not co do

g:=(d+c) div 2;

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 50
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

If T=A[g] then co:=true

Else

If T < A[g] then c:=g-1

{tiếp tục tìm ở nửa trái phạm vi}

Else d:=g+1;

{tiếp tục tìm ở nửa phải phạm vi }

If co then

Phần tử bằng T có tại vị trí g trong mảng

Else Không có T trong mảng.

Nếu T < A[g] thì với mọi chỉ số k > g ta có T < A[g] < A[k] (do mảng sắp thứ tự
tăng), do đó ta chỉ cần tìm T trong mảng ứng với các chỉ số k < g. Lúc này ta thu hẹp
phạm vi tìm kiếm bằng cách xác định lại vị trí cuối của phạm vi là g-1.

Nếu T > A[g] thì ta thực hiện một hành động tương tự là tìm T trong mảng ứng với
các chỉ số k > g. Lúc này ta thu hẹp phạm vi tìm kiếm bằng cách xác định lại vị trí đầu
của phạm vi là g+1.

Phạm vi là rỗng khi d > c.

Ví dụ

Giả sử A = (1, 6, 14, 17, 22, 25, 25, 30,45)

- Với T = 14 ta có các bước tìm kiếm được thể hiện như sau

Trước khi vào vòng lặp: d=1, c=9, co = False

Sau lần lặp d c g A[g] co

1 1 4 5 22 F

2 3 4 2 6 F

3 3 4 3 14 T

Kết luận giá trị T có trong mảng tại vị trí thứ 3.


Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 51
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

- Với T = 50 ta có các bước tìm kiếm được thể hiện như sau

Trước khi vào vòng lặp: d=1, c=9, co = False

Sau lần lặpd c g A[g] co

1 5 9 5 22 F

2 6 9 7 25 F

3 8 9 8 30 F

4 9 9 9 45 F

5 10 9 9 45 F

Lúc này d > c và vòng lặp dừng.

Kết luận giá trị T không có trong mảng vì giá trị của biến co là False.

2. CÂU HỎI VÀ BÀI TẬP

Câu 1 : Đánh giá độ phức tạp của các thuật toán tìm kiếm sơ cấp

Câu 2 : Mô tả thuật toán Tìm phần tử lớn thứ nhì trong một dãy tuỳ ý có n phần tử
và đánh giá độ phức tạp của thuật toán.

Câu 3 : Chạy từng bước thuật toán tìm nhị phân trên một mảng cụ thể có 16 phần
tử, xét hai trường hợp: phần tử cần tìm có trong mảng và không có trong mảng.

Câu 4 : Mô tả thuật toán Tìm phần tử xuất hiện nhiều lần nhất trong một dãy tuỳ ý
có n phần tử và đánh giá độ phức tạp của thuật toán.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 52
Trường Trung Cấp Nghề Cơ Điện Đông Nam Bộ Khoa Công nghệ thông tin

TÀI LIỆU THAM KHẢO

1. Niklaus Wirth, Cấu trúc dữ liệu + Giải thuật = Chương trình, bản dịch
tiếng Việt của Nguyễn Quốc Cường, NXBGD, 1993.

2. Đỗ Xuân Lôi, Cấu trúc dữ liệu và Giải thuật, NXBGD, 1993.

3. Đinh Mạnh Tường, Cấu trúc dữ liệu và thuật toán, NXBKHKT, 2001

4. Trần Hạnh Nhi, Trương Anh Đức, Giáo trình Cấu trúc dữ liệu 1, Khoa CNTT,
ĐHKHTN, ĐHQGHCM, 1996.

5. Derick Wood, Data Strutures, Algorithms, and Performance, Addison-Wesley

Publishing, 1993.

6. Alfred V. Aho, Jeffrey D. Ullman, Cơ sở của khoa học máy tính, Tập 1, 2,
Bản dịch tiếng Việt của Trần Đức Quang, NXB Thống kê, 1999.

7. Larry Nyhoff, Sanford Leestma, Lập trình nâng cao bằng Pascal với các cấu
trúc dữ liệu, Tập 1, 2, Bản dịch tiếng Việt của Lê Minh Trung, Công ty Scitec, 1991.

Giáo trình môn học Cấu Trúc Dữ Liệu & Giải Thuật Trang 53

You might also like