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

Giải thuật ứng dụng trong kinh doanh: Cài đặt bằng ngôn ngữ lập trình Python - Nguyễn Văn Thọ, Phó Hải Đăng, Nguyễn Văn Kiên

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 (18.35 MB, 238 trang )

<span class="text_page_counter">Trang 2</span><div class="page_container" data-page="2">

<i>Giải thuật ứng dụng trong kinh doanh (Tiếng Anh: Applied Algorithms in </i>

Business) là môn học thuộc chương trình đào tạo các ngành: Hệ thống thơng tin quản lý, Tài chính-ngân hàng, Quản trị kinh doanh...của trường Đại học Ngân hàng TPHCM. Với mong muốn có một tài liệu cho các em sinh viên tham khảo trong q

<i>trình học tập, nhóm tác giả đã tâm huyết biên soạn tài liệu Giải thuật ứng dụng trong </i>

<i>kinh doanh. Tài liệu này thể hiện được tính ưu việt hơn so với các tài liệu hiện có trên </i>

thị trường: (1)Nội dung được viết rất cô đọng và sát với đề cương môn học thuộc chương trình đào tạo đã được Ban giám hiệu phê duyệt; (2)Cấu trúc được trình bày theo hướng tóm tắt lý thuyết, cho ví dụ minh họa được cài đặt bằng ngôn ngữ Python, hướng dẫn giải bài tập từng bước. Với mỗi ví dụ và bài tập đều in kết quả sau khi chạy chương trình để sinh viên dễ dàng nắm bắt và thực hành. Cuối mỗi chương có trình bày tóm tắt nội dung chương cùng với các câu hỏi ôn tập và các bài tập thực hành có hướng dẫn chi tiết. Ngồi ra tài liệu cịn có các bài tập đề nghị sinh viên tự giải nhằm giúp các em nâng cao khả năng tự học; (3)Các bài tập tình huống và bài tập tự rèn luyện ở mỗi chương được chọn lọc kỹ, đó là những bài toán rất thực tế và phổ biến trong lĩnh vực kinh doanh mà các doanh nghiệp đang áp dụng; (4)Đính kèm theo sách này là các tập tin mã nguồn của chương trình đã được viết hồn chỉnh bằng ngơn ngữ lập trình Python nhằm giúp người học dễ dàng theo dõi. Độc giả có thể tải các tập tin mã nguồn tại địa chỉ sau:

Nội dung tài liệu được chia thành 7 chương:

<b>Chương 1: Tổng quan Chương 2: Đệ quy Chương 3: Danh sách Chương 4: Cây </b>

<b>Chương 5: Đồ thị </b>

<b>Chương 6: Sắp xếp và tìm kiếm Chương 7: Bảng băm </b>

Nhóm biên soạn chân thành cảm ơn sự hỗ trợ của lãnh đạo trường Đại học Ngân hàng Tp. Hồ Chí Minh, cảm ơn các nhà khoa học đã có những đóng góp ý kiến q báu để nhóm hồn thành tài liệu này.

</div><span class="text_page_counter">Trang 3</span><div class="page_container" data-page="3">

các em sinh viên để lần ấn bản sau được hoàn chỉnh hơn.

Mọi thắc mắc và đóng góp về tài liệu, Quý độc giả vui lòng gửi mail theo địa chỉ: hoặc

Xin chân thành cảm ơn

<b>Nhóm biên soạn</b>

</div><span class="text_page_counter">Trang 5</span><div class="page_container" data-page="5">

<b>MỤC LỤC </b>

<b>CHƯƠNG 1. TỔNG QUAN ... 1</b>

Một số định nghĩa về cấu trúc dữ liệu và giải thuật ... 2

Định nghĩa giải thuật ... 2

Giải thuật ứng dụng trong kinh doanh ... 2

Định nghĩa cấu trúc dữ liệu và cấu trúc lưu trữ... 2

Vai trò của tổ chức dữ liệu và mối quan hệ giữa cấu trúc dữ liệu và giải thuật ... 3

Các kiểu dữ liệu cơ bản ... 4

Các kiểu dữ liệu có cấu trúc ... 6

Phân tích và thiết kế giải thuật ... 7

Phương pháp chia để trị (divide- and-conquer) ... 8

Phương pháp quy hoạch động ... 10

Phương pháp quay lui (backtracking) ... 10

Ký hiệu BigO (Big-Oh Notation) ... 10

Giới thiệu về ngơn ngữ lập trình Python ... 15

Một số câu hỏi và bài tập có lời giải ... 16

Một số câu hỏi và bài tập tự rèn luyện ... 17

<b>CHƯƠNG 2. ĐỆ QUY ... 18</b>

Giới thiệu đệ quy ... 19

Khái niệm: ... 19

Giải thuật đệ quy và hàm đệ quy ... 19

Cơ chế hoạt động của giải thuật đệ quy ... 20

Thiết kế giải thuật đệ quy ... 21

Ưu điểm và nhược điểm của giải thuật đệ quy... 22

Phân loại giải thuật đệ quy ... 22

Đệ quy tuyến tính ... 22

Đệ quy nhị phân ... 23

Đệ quy phi tuyến ... 24

Đệ quy tương hỗ ... 24

Giải một số bài toán phổ biến bằng giải thuật đệ quy ... 25

Bài toán tháp Hà Nội [9]. ... 25

Bài tốn tìm kiếm với đệ quy nhị phân ... 27

Bài toán chia thưởng ... 29

Một số câu hỏi và bài tập có lời giải ... 30

Ứng dụng giải thuật đệ quy để giải bài toán trong kinh doanh ... 34

Sử dụng đệ quy để tính tiền lãi gửi tiết kiệm ngân hàng ... 34

</div><span class="text_page_counter">Trang 6</span><div class="page_container" data-page="6">

Sử dụng đệ quy để tính tiền thưởng ... 35

Sử dụng đệ quy để tính tiền lãi phải trả hàng tháng khi vay ngân hàng ... 36

Một số câu hỏi và bài tập tự rèn luyện ... 37

<b>CHƯƠNG 3. DANH SÁCH ... 38</b>

Giới thiệu danh sách ... 39

Danh sách đặc ... 39

Định nghĩa ... 39

Ưu và nhược điểm của danh sách đặc ... 40

Khai báo danh sách đặc ... 40

Các thao tác trên danh sách đặc ... 40

Danh sách liên kết ... 45

Định nghĩa và phân loại... 45

Danh sách liên kết đơn ... 45

Danh sách liên kết đơi ... 53

Danh sách liên kết vịng ... 58

Danh sách đa liên kết... 58

Ứng dụng của danh sách liên kết... 59

Ngăn xếp ... 59

Định nghĩa ... 59

Khai báo cấu trúc ngăn xếp ... 60

Các thao tác trên ngăn xếp ... 61

Ứng dụng của ngăn xếp ... 63

Hàng đợi ... 64

Định nghĩa ... 64

Khai báo cấu trúc của hàng đợi ... 66

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

Ứng dụng của hàng đợi ... 69

Một số câu hỏi, bài tập có lời giải... 71

Ứng dụng danh sách để giải một số bài toán trong kinh doanh ... 72

Chương trình quản lý sinh viên bằng cấu trúc danh sách đặc ... 72

Chương trình quản lý sách sử dụng cấu trúc danh sách liên kết đơn ... 77

Chương trình quản lý bệnh nhân sử dụng cấu trúc hàng đợi ... 80

Chương trình đảo ngược danh sách các cuốn sách sử dụng ngăn xếp ... 84

Một số câu hỏi và bài tập tự rèn luyện ... 86

<b>CHƯƠNG 4. CÂY ... 88</b>

Các khái niệm cơ bản ... 89

Khái niệm cây ... 89

</div><span class="text_page_counter">Trang 7</span><div class="page_container" data-page="7">

Các thuật ngữ ... 89

Cách biểu diễn cây ... 90

Cây nhị phân ... 91

Một số tính chất của cây nhị phân ... 91

Duyệt cây nhị phân ... 92

Cây nhị phân tìm kiếm ... 95

Định nghĩa ... 95

Khai báo cấu trúc cây nhị phân tìm kiếm ... 96

Các thao tác trên cây nhị phân tìm kiếm ... 96

Duyệt cây ... 96

Cây nhiều nhánh ... 101

Giới thiệu cây TRIE ... 102

Cấu trúc dữ liệu Heap ... 103

Minh họa thao tác nhập xuất cây nhị phân tìm kiếm ... 104

Một số câu hỏi và bài tập có lời giải ... 107

Ứng dụng cấu trúc cây để giải bài toán trong kinh doanh ... 108

Chương trình quản lý sinh viên bằng cấu trúc cây ... 108

Chương trình quản lý hàng hóa bằng cấu trúc cây ... 112

Chương trình quản lý sách bằng cấu trúc cây ... 115

Một số câu hỏi và bài tập tự rèn luyện ... 118

Duyệt theo chiều sâu - DFS ... 125

Duyệt theo chiều rộng - BFS ... 127

Cây khung và cây khung nhỏ nhất ... 128

Cây khung ... 128

Cây khung nhỏ nhất ... 129

Thuật tốn Prim tìm cây khung nhỏ nhất ... 130

</div><span class="text_page_counter">Trang 8</span><div class="page_container" data-page="8">

Thuật tốn Krusal tìm cây khung nhỏ nhất ... 133

Thuật tốn Dijkstra tìm đường đi ngắn nhất ... 138

Mô tả thuật tốn ... 138

Chương trình minh họa giải thuật Dijkstra ... 141

Ứng dụng của đồ thị ... 142

Một số câu hỏi và bài tập có lời giải ... 143

Ứng dụng đồ thị để giải bài toán trong kinh doanh ... 148

Quản lý đường bay ... 148

Bài toán vận chuyển hàng hóa ... 149

Mạng lưới giao thơng ... 152

Lắp đặt hệ thống điện văn phòng ... 152

Một số câu hỏi và bài tập tự rèn luyện ... 153

<b>CHƯƠNG 6. SẮP XẾP VÀ TÌM KIẾM ... 155</b>

Sắp xếp ... 156

Giới thiệu về bài toán sắp xếp ... 156

Giải thuật Bubble Sort ... 156

Giải thuật Selection Sort... 163

Giải thuật Insertion Sort ... 165

Giải thuật Interchange Sort... 168

Giải thuật Merge Sort ... 172

Giải thuật Quick Sort ... 174

Giải thuật Heap Sort ... 177

Giải thuật Radix Sort ... 183

Giải thuật Topo Sort ... 185

Tìm kiếm ... 188

Khái niệm và vai trò của tìm kiếm dữ liệu ... 188

Phân loại ... 189

Một số câu hỏi, bài tập có lời giải... 193

Ứng dụng giải thuật sắp xếp và tìm kiếm để giải bài tốn trong kinh doanh ... 194

Chương trình quản lý sinh viên sử dụng giải thuật InterChange Sort ... 194

Chương trình quản lý hóa đơn bán hàng ... 196

Chương trình quản lý hàng hóa ... 200

Tính thời gian tối thiểu để vận chuyển hàng ... 202

Một số câu hỏi và bài tập tự rèn luyện ... 203

<b>CHƯƠNG 7. BẢNG BĂM ... 204</b>

Tìm hiểu về bảng băm ... 205

Kỹ thuật băm ... 205

</div><span class="text_page_counter">Trang 9</span><div class="page_container" data-page="9">

Hàm băm ... 206

Các kỹ thuật xử lý va chạm ... 208

Kỹ thuật tạo dây chuyền (separated chaining) ... 208

Kỹ thuật định địa chỉ mở (open addressing) ... 208

Ứng dụng bảng băm ... 210

Một số câu hỏi và bài tập có lời giải ... 211

Một số câu hỏi và bài tập tự rèn luyện ... 214

<b>TÀI LIỆU THAM KHẢO ... 1</b>

<b>PHỤ LỤC ... 2</b>

</div><span class="text_page_counter">Trang 10</span><div class="page_container" data-page="10">

<b>DANH MỤC HÌNH ẢNH </b>

Hình 1. 1- Từ bài tốn thực tế đến chương trình trên máy tính ... 3

Hình 1. 2-Mối quan hệ giữa cấu trúc dữ liệu và giải thuật ... 4

Hình 1. 3- Q trình từ bài tốn thực tế đến chương trình ... 8

Hình 1. 4- Đồ thị mô tả độ phức tạp của giải thuật ... 11

Hình 1. 5- Độ phức tạp giải thuật qua các hàm ... 14

Hình 2. 1- Cơ chế hoạt động của giải thuật đệ quy ... 20

Hình 2. 2 - Cơ chế hoạt động của bài tốn tính giai thừa ... 21

Hình 2. 3 – Mơ tả đệ quy tương hỗ ... 24

Hình 2. 4- Minh họa đệ quy bài toán Tháp Hà Nội ... 25

Hình 2. 5- Q trình thực hiện bài tốn Tháp Hà Nội ... 26

Hình 2. 6- Cơ chế tìm kiếm với đệ quy nhị phân ... 27

Hình 2. 7- Cấu trúc của mảng một chiều ... 40

Hình 3. 1-Cấu trúc danh sách liên kết với con trỏ pHead và pTail ... 45

Hình 3. 2- Danh sách liên kết đơn... 45

Hình 3.3-Thêm một phần tử vào vị trí ở đầu danh sách ... 47

Hình 3. 4-Thêm một phần tử vào vị trí ở cuối danh sách ... 47

Hình 3. 5- Thêm một phần tử vào sau nút q ... 48

Hình 3. 6-Xóa một phần tử ở vị trí đầu danh sách ... 48

Hình 3. 7- Xóa một phần tử đứng sau nút q ... 49

Hình 3. 8- Xóa một phần tử có giá trị X ... 49

Hình 3. 9-Danh sách liên kết đơi... 53

Hình 3. 10-Thêm một phần tử vào danh sách liên kết đơi ... 54

Hình 3. 11-Thêm một phần tử vào vị trí cuối danh sách ... 54

Hình 3. 12-Thêm một phần tử sau phần tử q ... 55

Hình 3. 13-Xóa một phần tử ở vị trí đầu danh sách trong danh sách liên kết đơi ... 56

Hình 3. 14-Xóa một phần tử đứng sau vị trí phần tử q trong danh sách liên kết đơi ... 56

Hình 3. 15-Xóa một phần tử có giá trị X trong danh sách liên kết đơi ... 57

Hình 3. 16-Danh sách liên kết vịng là một danh sách liên kết đơn ... 58

Hình 3. 17-Danh sách liên kết vòng là một danh sách liên kết đơi. ... 58

Hình 3. 18-Cấu trúc của danh sách đa liên kết... 58

Hình 3. 19- Minh họa về một ngăn xếp ... 59

Hình 3. 20-Hai tác vụ Push và Pop của ngăn xếp ... 59

Hình 3. 21-Các tác vụ trong ngăn xếp ... 60

Hình 3. 22-Quá trình chuyển đổi cơ số thập phân sang nhị phân ... 64

</div><span class="text_page_counter">Trang 11</span><div class="page_container" data-page="11">

Hình 3. 23- Minh họa thao tác Push và Pop trong bài tốn đổi cơ số ... 64

Hình 3. 24- Minh họa cơ chế của hàng đợi qua việc xếp hàng tính tiền tại quầy ... 65

Hình 3. 25-Cấu trúc của hàng đợi ... 65

Hình 3. 26-Minh họa thao tác thêm phần tử vào hàng đợi ... 65

Hình 3. 27-Minh họa tác vụ xóa phần tử trong hàng đợi ... 66

Hình 3. 28-Quá trình cài đặt giải thuật Radix Sort bằng hàng đợi ... 70

Hình 4. 1- Sơ đồ tổ chức của một cơng ty ... 89

Hình 4. 2-Cây biểu diễn biểu thức ... 89

Hình 4. 3-Mức của cây... 90

Hình 4. 4-Biểu diễn cây bằng đồ thị ... 90

Hình 4. 5-Biểu diễn cây bằng giản đồ ... 90

Hình 4. 6-Biểu diễn cây bằng phương pháp indentatio ... 91

Hình 4. 7- Cấu trúc của một cây nhị phân ... 91

Hình 4. 8-Cây nhị phân hồn chỉnh ... 92

Hình 4. 9-Cây nhị phân đầy đủ ... 92

Hình 4. 10-Quá trình duyệt cây theo thứ tự trước của biểu thức tốn học ... 93

Hình 4. 11-Kết quả duyệt cây nhị phân theo thứ tự trước với các số nguyên ... 93

Hình 4. 12-Quá trình duyệt cây theo thứ tự giữa của biểu thức toán học ... 93

Hình 4. 13-Kết quả duyệt cây nhị phân theo thứ tự giữa với các số nguyên ... 94

Hình 4. 14-Kết quả duyệt cây nhị phân theo thứ tự sau của biểu thức tốn học ... 94

Hình 4. 15-Kết quả duyệt cây nhị phân theo thứ tự sau với các số nguyên ... 94

Hình 4. 16- Chuyển cây tổng quát thành cây nhị phân ... 95

Hình 4. 17-Cấu trúc cây nhị phân tìm kiếm ... 95

Hình 4. 18-Xóa phần tử là nút lá... 99

Hình 4. 19-Xóa phần tử có một nút con ... 100

Hình 4. 20-Nút nhỏ nhất của cây con bên phải ... 100

Hình 4. 21-Nút nhỏ nhất của cây con bên trái ... 100

Hình 4. 22-Cây Trie biểu diễn cho tập S gồm các chuỗi {bear, bell, bid, bull, buy, hear, see, sell, stock, stop} ... 102

Hình 4. 23-Cấu trúc dữ liệu Heap ... 103

</div><span class="text_page_counter">Trang 12</span><div class="page_container" data-page="12">

Hình 5. 8-Đồ thị có trọng số ... 123

Hình 5. 9-Đồ thị khơng có trọng số ... 123

Hình 5. 10-Biểu diễn đồ thị bằng ma trận kề ... 123

Hình 5. 11-Biểu diễn đồ thị bằng danh sách kề ... 124

Hình 5. 12-Biểu diễn đồ thị khơng có trọng số với danh sách kề ... 125

Hình 5. 13-Kết quả duyệt đồ thị theo DFS ... 126

Hình 5. 14-Duyệt đồ thị theo chiều rộng ... 127

Hình 5. 15-Đồ thị gồm cá đỉnh ... 128

Hình 5. 16-Đồ thị và cây khung ... 129

Hình 5. 17-Cây khung nhỏ nhất ... 129

Hình 6. 1- Minh họa giải thuật Bubble Sort ... 157

Hình 6. 2- Minh họa giải thuật Insertion Sort ... 166

Hình 6. 3-Quá trình sắp xếp của giải thuật Merge Sort ... 173

Hình 6. 4-Cấu trúc Heap ... 178

Hình 6. 5-Quá trình sắp xếp của giải thuật Radix Sort ... 184

Hình 6. 6-Minh họa giải thuật Topo Sort ... 185

Hình 6. 7- Minh họa phương pháp tìm kiếm nhị phân với cuốn danh bạ điện thoại ... 191

Hình 7. 1-Mơ tả kỹ thuật băm ... 205

Hình 7. 2-Hàm băm với phép chia dư cho 10 ... 206

Hình 7. 3-HIện tượng va chạm ... 208

Hình 7. 4-Kỹ thuật tạo dây chuyền ... 208

</div><span class="text_page_counter">Trang 13</span><div class="page_container" data-page="13">

<b>DANH MỤC BẢNG BIỂU </b>

Bảng 1-Các kiểu dữ liệu định sẳn trong Python ... 5

Bảng 2- Kiểu dữ liệu và ví dụ minh họa cho kiểu dữ liệu ... 6

Bảng 3- Mô tả giải thuật duyệt theo chiều sâu (DFS) ... 126

Bảng 4- Quá trình duyệt theo chiều rộng (BFS) ... 128

Bảng 5-Mơ tả q trình thăm dị tuyến tính ... 209

Bảng 6-Mơ tả q trình chèn giá trị khóa theo phương pháp băm kép ... 210

</div><span class="text_page_counter">Trang 14</span><div class="page_container" data-page="14">

<b>THUẬT NGỮ SỬ DỤNG </b>

ASCII (American Standard Code for

Information Interchange) <sup>Chuẩn mã trao đổi thông tin Hoa Kỳ </sup>

CPU (Central Processing Unit) Bộ xử lý trung tâm

DB Indexing (Data Base Indexing) Chỉ mục cơ sở dữ liệu Devide-and-conquer Chia để trị

Double linked list Danh sách liên kết kép DFS (Depth First Search) Tìm kiếm theo chiều sâu Dynamic programming Quy hoạch động

Inorder traversal Duyệt theo thứ tự giữa

LIFO (Last In First Out) Vào sau ra trước FIFO (First In First Out) Vào trước ra trước

Minimum spanning tree Cây khung nhỏ nhất

Multi-linked lists Danh sách đa liên kết

Postorder traversal Duyệt theo thứ tự sau

Single linked list Danh sách liên kết đơn

</div><span class="text_page_counter">Trang 17</span><div class="page_container" data-page="17">

<b>CHƯƠNG 1. TỔNG QUAN </b>

<b>T</b>

rong quá trình giải quyết các bài tốn trên máy tính, việc lập trình đóng vai trị rất quan trọng, điều đó địi hỏi phải phân tích và thiết kế các giải thuật để giải quyết bài toán một cách hiệu quả nhất.

Chương tổng quan, người học sẽ làm quen với một số khái niệm cơ bản về cấu trúc dữ liệu và giải thuật, phân tích mối quan hệ giữa cấu trúc dữ liệu và giải thuật có ảnh hưởng đến đề án tin học như thế nào. Ngoài ra, chương 1 cịn trình bày cách đánh giá độ phức tạp của thuật toán.

<b>Nội dung: </b>

- Khái niệm cấu trúc dữ liệu và giải thuật

- Mối quan hệ giữa cấu trúc dữ liệu và giải thuật - Các kiểu dữ liệu cơ bản

- Phân tích và thiết kế giải thuật - Khái niệm BigO

- Xác định độ phức tạp của giải thuật - Câu hỏi và bài tập

</div><span class="text_page_counter">Trang 18</span><div class="page_container" data-page="18">

<b> Một số định nghĩa về cấu trúc dữ liệu và giải thuật </b>

Để giải quyết bài tốn trên máy tính bao gồm nhiều bước. Đầu tiên là xác định được yêu cầu của bài toán sau đó tìm ra mơ hình, tức là chuyển các u cầu tổng quát thành các cấu trúc cụ thể và chặt chẽ, chúng sẽ được thể hiện ở mơ hình tốn học hay nói cách khác là việc mơ hình hóa bài tốn. Mơ hình này là nền tảng để thực hiện các giai đoạn tiếp theo như lựa chọn cấu trúc dữ liệu, thiết kế giải thuật, môi trường triển khai…

<b>Định nghĩa giải thuật </b>

Giải thuật (Algorithms) là tập hợp các câu lệnh được thể hiện chặt chẽ và rõ ràng bao gồm một trình tự các thao tác thực hiện trên một số đối tượng nào đó, sao cho sau khi thực thi với một số hữu hạn bước sẽ cho kết quả mong muốn. Với mỗi thuật tốn sẽ có dữ liệu vào (input) và dữ liệu ra (output) tương ứng [3].

Thuật ngữ “giải thuật” dùng để chỉ một thủ tục hay cách thức có thể được thực hiện trên máy tính, điều này có thể có một số hạn chế trong q trình lập trình, do vậy cần phải có các u cầu về giải thuật:

 Các lệnh hay tập lệnh phải có tính xác định

 Các lệnh này cần phải được tổ chức sao cho máy tính hiểu được

 Sau một số hữu hạn các phép tính thì các lệnh phải dừng để cho kết quả Trong việc phân tích và thiết kế giải thuật, có ba cấu trúc cần được sử dụng là: cấu trúc tuần tự; cấu trúc chọn lựa và cấu trúc lặp.

<b> Giải thuật ứng dụng trong kinh doanh </b>

Giải thuật hay cịn gọi là thuật tốn được áp dụng rộng rãi trong mọi lĩnh vực nhằm mục đích giải quyết các bài toán cụ thể trong lĩnh vực áp dụng. Trong lĩnh vực kinh doanh, giải thuật được sử dụng nhằm giúp doanh nghiệp ứng dụng Công nghệ thông tin vào trong quá trình hoạt động của doanh nghiệp như quản trị nhân sự, quản trị tài chính, quản trị bán hàng,…

Giải thuật ứng dụng trong kinh doanh tập trung giúp người học tìm ra các giải thuật phù hợp nhằm giải quyết các bài toán cụ thể trong kinh doanh trong bối cảnh chuyển đổi số mạnh mẽ như hiện nay.

<b>Định nghĩa cấu trúc dữ liệu và cấu trúc lưu trữ </b>

<b>Cấu trúc dữ liệu (data structure) là cách lưu trữ, tổ chức dữ liệu có hệ thống </b>

để dữ liệu có thể được sử dụng một cách hiệu quả. Có các loại cấu trúc dữ liệu phổ biến sau đây: mảng (array); ngăn xếp (stack); hàng đợi (queue); danh sách liên kết đơn (singly linked list); danh sách liên kết vòng (circularity linked list); danh sách liên kết kép (double linked list); cấu trúc cây (tree); cấu trúc đồ thị (graph) [3].

</div><span class="text_page_counter">Trang 19</span><div class="page_container" data-page="19">

<b>Cấu trúc lưu trữ (storage structure) là phương thức biểu diễn một cấu trúc dữ </b>

liệu trong bộ nhớ máy tính của cấu trúc dữ liệu đó. Có nhiều cấu trúc lưu trữ khác nhau cho cùng một cấu trúc dữ liệu [3]. Ví dụ, cấu trúc dữ liệu mảng hai chiều sẽ có hai cấu trúc lưu trữ là lưu trữ theo dòng và lưu trữ theo cột nhưng cũng có loại cấu trúc dữ liệu chỉ có thể có một cấu trúc lưu trữ duy nhất. Ví dụ cấu trúc ngăn xếp, hàng đợi, cây chỉ có một cách lưu trữ duy nhất là lưu trữ theo dạng kế tiếp.

<b> Vai trò của tổ chức dữ liệu và mối quan hệ giữa cấu trúc dữ liệu và giải thuật </b>

Việc triển khai một dự án trên máy tính có nghĩa là biến một vấn đề thực tế thành một vấn đề mà máy tính có thể giải quyết được. Một bài tốn bất kỳ trên máy tính đều bao gồm các đối tượng dữ liệu và các yêu cầu xử lý của các đối tượng đó.

Dữ liệu là những số liệu mơ tả tính chất của đối tượng, dữ liệu này rời rạc vì vậy cần được quản lý chặt chẽ. Ví dụ: Thơng tin của một nhân viên gồm: mã nhân viên, họ tên, địa chỉ, số điện thoại, mức lương, hệ số lương v.v…; Thông tin của một sản phẩm gồm: Mã sản phẩm, tên sản phẩm, giá, xuất xứ, ngày sản xuất…

Thao tác xử lý trên dữ liệu là các kỹ thuật xử lý trên dữ liệu đã được lưu trữ, các kỹ thuật này bao gồm: Tìm kiếm thơng tin, sửa đổi thơng tin, xóa thơng tin, biến đổi dữ liệu, lập báo cáo...Ví dụ:

- Tìm nhân viên có tên: “Nguyễn Văn A”

- Liệt kê sách nhân viên có lương trên 10 triệu theo thứ tự tăng/giảm dần - Liệt kê sách nhân viên có thâm niên cơng tác trên 20 năm.

<i><small>Hình 1. 1- Từ bài tốn thực tế đến chương trình trên máy tính </small></i>

Vì vậy, để tạo ra một mơ hình máy tính phản ánh được các vấn đề trong thế giới thực, chúng ta cần tập trung vào hai vấn đề:

<b>- Tổ chức biểu diễn đối tượng trong thế giới thực: các phần tử dữ liệu trong thế </b>

giới thực rất đa dạng, phong phú và thường xuyên có mối quan hệ qua lại với nhau.

</div><span class="text_page_counter">Trang 20</span><div class="page_container" data-page="20">

Do đó, trong việc mơ hình hóa bài tốn, cần phải phản ánh chính xác dữ liệu thực này và tổ chức, xây dựng một cấu trúc tối ưu để máy tính dễ dàng xử lý. Nhiệm vụ này

<i><b>được gọi là xây dựng cấu trúc dữ liệu cho bài toán trong thực tế. </b></i>

<b>- Xây dựng các thao tác xử lý trên dữ liệu: Bắt đầu từ nhu cầu xử lý thực tế của </b>

mình, chúng ta cần tìm giải thuật phù hợp để xác định trình tự các thao tác máy tính cần thực hiện để đạt được kết quả mong muốn. Bước này được gọi là xây dựng giải thuật cho bài toán.

Khi giải quyết các vấn đề thực tế trên máy tính, ta thường tập trung vào việc xây dựng các thuật tốn và ít chú trọng đến việc sắp xếp, tổ chức dữ liệu. Việc tổ chức dữ liệu đóng vai trị rất quan trọng trong tiến tình xây dựng chương trình. Các giải thuật phản ánh chính xác các thao tác xử lý trên dữ liệu trong khi đó đối tượng xử lý của giải thuật là dữ liệu. Bản thân dữ liệu chứa thông tin quan trọng để thực thi giải thuật. Như cơng thức [5] trong hình 1.2 cho thấy, giải thuật và cấu trúc dữ liệu ln ln có mối quan hệ với nhau trong các dự án tin học.

<i>Data structures + Algorithms = Programs. </i>

<i><small>Hình 1. 2-Mối quan hệ giữa cấu trúc dữ liệu và giải thuật</small></i>

Khi chọn lựa cấu trúc dữ liệu phù hợp với bài toán sẽ có giải thuật tương ứng với cấu trúc dữ liệu đó. Nếu cấu trúc dữ liệu thay đổi, thơng thường thuật tốn cũng thay đổi tương ứng. Ngồi ra, cấu trúc dữ liệu tốt góp phần khơng nhỏ nhằm giúp giải thuật hoạt động tốt hơn, chính vì vậy ta có thể kết luận cấu trúc dữ liệu sẽ quyết định giải thuật.

<b> Các kiểu dữ liệu cơ bản </b>

Các kiểu dữ liệu cơ bản thường là các kiểu dữ liệu phi cấu trúc, đơn giản, điển hình là các giá trị như số nguyên, số thực, ký tự, chuỗi... Các kiểu dữ liệu này được tích hợp sẵn trong hầu hết các ngơn ngữ lập trình do tính phổ biến và tính đơn giản của chúng, cho phép người lập trình thao tác với chúng một cách dễ dàng. Như vậy, chúng thường được gọi là các kiểu dữ liệu định sẵn (dữ liệu tiền định).

<b>Một số loại kiểu dữ liệu cơ bản sau: </b>

Kiểu dữ liệu số nguyên: Chứa số nguyên có dấu và số ngun khơng dấu, với các kích thước:1 byte, 2 bytes hoặc 4 bytes.

</div><span class="text_page_counter">Trang 21</span><div class="page_container" data-page="21">

Kiểu dữ liệu số thực: Đây là kiểu dữ liệu được tổ chức trong bộ nhớ và chứa dấu chấm động (số lẻ) thường có kích thước sau: 4 bytes, 6 bytes, 8 bytes hoặc 10 bytes. Kiểu dữ liệu ký tự: Dùng chuỗi 8 bit theo bộ mã ASCII để biểu diễn một ký tự trong máy tính. Kiểu ký tự có kích thước 1 byte và 2 bytes.

Kiểu dữ liệu chuỗi ký tự: Kiểu dữ liệu dạng chuỗi ký tự được tổ chức trong bộ nhớ máy tính bằng bảng mã ASCII của mỗi ký tự trong chuỗi đó. Kích thước của nó tùy vào ngơn ngữ lập trình hỗ trợ.

Kiểu luận lý: Đây là kiểu dữ liệu logic có giá trị true hoặc false, thường có kích thước 1 byte.

Các kiểu dữ liệu tiền định trong ngôn ngữ lập trình Python [13]:

<i><small>Bảng 1-Các kiểu dữ liệu định sẳn trong Python </small></i>

Kiểu int <sup>Kiểu số nguyên lưu trữ các giá trị số nguyên có dấu và không </sup><sub>dấu, giá trị không giới hạn. </sub>Kiểu float Lưu trữ các giá trị số thực.

Kiểu complex Lưu trữ số phức bao gồm hai phần: phần thực và phần ảo. Kiểu str Lưu trữ các kí tự tạo thành chuỗi ký tự

Kiểu list <sup>Lưu trữ tập các phần tử dữ liệu có thể thay đổi, nó thường lưu </sup>các phần tử cùng kiểu dữ liệu.

Kiểu tuple Lưu trữ tập các phần tử cố định không thể thay đổi.

Kiểu range <sup>Range tức là khoảng, nó đại diện cho tập các giá trị số nguyên </sup>không thể thay đổi, thường dùng trong vòng lặp for.

Kiểu dict <sup>Là một loại bảng băm, hoạt động giống mảng kết hợp lưu trữ dữ </sup><sub>liệu dạng key-value. </sub>Kiểu set <sup>Là tập hợp khơng có thứ tự của các đối tượng duy nhất. Đây là </sup><sub>một dạng bảng băm, ta có thể thêm hoặc xóa phần tử khỏi set. </sub>

Kiểu frozenset

Là kiểu set và không thể thay đổi được, các giá trị trong frozenset không thể thay đổi sau khi nó được tạo. Nó được sử dụng chủ yếu làm khóa trong dictionary hoặc phần tử trong các set khác.

Kiểu bool Lưu giá trị True hoặc False.

Kiểu bytes Dùng để chứa chuỗi byte đơn không thể thay đổi. Kiểu bytearray Chứa chuỗi các byte có thể thay đổi.

Kiểu memoryview <sup>Cho phép truy cập dữ liệu của một đối tượng hỗ trợ giao thức </sup>đệm mà không cần sao chép.

</div><span class="text_page_counter">Trang 22</span><div class="page_container" data-page="22">

Bảng 2 dưới đây mô tả các kiểu dữ liệu và các ví dụ minh họa đặc điểm của nó [13]:

<i><small>Bảng 2- Kiểu dữ liệu và ví dụ minh họa cho kiểu dữ liệu </small></i>

<b> Các kiểu dữ liệu có cấu trúc </b>

Kiểu dữ liệu có cấu trúc là kiểu dữ liệu được xây dựng trên một kiểu dữ liệu đã có, hoặc có thể xây dựng dựa trên một kiểu dữ liệu có cấu trúc khác.

Ví dụ: Để mơ tả một đối tượng sinh viên, thông tin và kiểu dữ liệu bao gồm:

<i><b>- Mã sinh viên: kiểu dữ liệu chuỗi ký tự - Tên sinh viên: kiểu dữ liệu chuỗi ký tự - Ngày sinh: kiểu dữ liệu ngày tháng - Nơi sinh: kiểu dữ liệu chuỗi ký tự - Điểm thi: kiểu dữ liệu số thực </b></i>

<b>Đối với thông tin điểm thi: kiểu số thực, mã sinh viên: kiểu chuỗi ký tự; tên sinh viên: kiểu chuỗi ký tự; nơi sinh: kiểu chuỗi ký tự, ngoài ra, các thơng tin khác địi hỏi phải sử dụng các kiểu có cấu trúc như ngày sinh: kiểu ngày tháng. Để thể </b>

hiện thông tin về ngày tháng năm sinh của một sinh viên ta cần phải xây dựng một cấu trúc dữ liệu trong ngơn ngữ lập trình Python như sau:

</div><span class="text_page_counter">Trang 23</span><div class="page_container" data-page="23">

Tiếp theo, ta có thể xây dựng kiểu dữ liệu thể hiện thông tin về một sinh viên như sau:

<b> Phân tích và thiết kế giải thuật </b>

Trong q trình giải một bài tốn trên máy tính, đối với những bài tốn khác nhau có thể có nhiều giải thuật khác nhau. Có những giải thuật được thiết kế đơn giản, dễ hiểu, dễ triển khai v.v… tuy nhiên thời gian thực hiện của giải thuật đó lớn và chiếm nhiều tài nguyên của máy tính. Ngược lại, với những giải thuật được thiết kế và lập trình rất phức tạp, nhưng thời gian thực thi chương trình cho kết quả nhanh hơn, ít chiếm dụng tài nguyên trên máy tính. Như vậy ta nên lựa chọn giải thuật nào để mang lại hiệu quả hơn?

Đối với những chương trình có tần suất sử dụng thấp thì thời gian thực thi chương trình khơng phải là yếu tố quan trọng. Các bài toán dạng này, thời gian để người phát triển chương trình xây dựng giải thuật là tiêu chí quan trọng hơn việc xem xét thời gian thực thi của chương trình cho nên những giải thuật có thiết kế đơn giản nên được lựa chọn. Ngược lại, có những chương trình có tần suất sử dụng cao thì thời gian thực thi của chương trình cần được chú trọng hơn nhiều so với thời gian được người lập trình sử dụng để thiết kế và xây dựng giải thuật. Khi đó, lựa chọn một giải thuật có thời gian thực thi nhanh hơn là một lựa chọn đúng đắn. Quá trình từ một bài tốn cần được giải quyết đến chương trình hồn chỉnh được thể hiện ở sơ đồ (hình 1.3) dưới đây:

</div><span class="text_page_counter">Trang 24</span><div class="page_container" data-page="24">

<i><small>Hình 1. 3- Q trình từ bài tốn thực tế đến chương trình </small></i>

Một vấn đề đặt ra là làm thế nào để đưa ra giải thuật để giải quyết bài toán? Sau đây là các phương pháp thiết kế giải thuật phổ biến:

- Chia-để-trị (divide-and-conquer)

- Quy hoạch động (dynamic programming)

- Quay lui (backtracking): Đây là kỹ thuật vét cạn

- Tham lam (greedy method): Được sử dụng trong trí tuệ nhân tạo (AI)

Mặc dù hiện nay có nhiều kỹ thuật thiết kế giải thuật, tuy nhiên trong tài liệu tham khảo này, chúng tơi chỉ trình bày chi tiết kỹ thuật chia để trị, còn các phương pháp khác chỉ được nêu khái quát, người học sẽ tự tìm hiểu trong các tài liệu khác.

<b>Phương pháp chia để trị (divide- and-conquer) </b>

Chia để trị là phương pháp quan trọng được sử dụng rộng rãi để thiết kế giải thuật. Ý tưởng của phương pháp này là chia bài toán lớn thành các bài toán nhỏ, rồi lại chia các bài toán nhỏ này thành các bài toán con nhỏ hơn cho đến khi ta được các bài toán đã biết cách giải. Sau đó ta tổng hợp lại kết quả để được lời giải của bài toán ban đầu [10].

Để thực hiện kỹ thuật này, thơng thường có hai cách thiết kế: • Thiết kế từ trên xuống (top-down design)

• Thiết kế tinh chỉnh từng bước (stepwise refinement)

<b>Kỹ thuật thiết kế Top-Down </b>

Đây là phương pháp được mơ tả dạng đệ quy dạng ngơn trình Python dưới đây:

<i>def DivideConquer (A,x): # tìm nghiệm x của bài toán A. </i>

if (A đủ nhỏ): # <i>nếu bài toán A đủ nhỏ </i>

Solve (A) <i># giải quyết bài toán A </i>

else: <i># Chia bài toán A thành các bài toán con A1, A2,…, Am; </i>

for i in range (1, m+1):

DivideConquer (Ai, xi);

Kết hợp các nghiệm xi của các bài toán con Ai (i=1, …, m) để nhận được nghiệm x của bài toán A.

</div><span class="text_page_counter">Trang 25</span><div class="page_container" data-page="25">

Ví dụ: Bài tốn tìm từ trong từ điển, QuickSort, Tháp Hà Nội là dạng bài toán sử dụng kỹ thuật chia để trị.

<b>Phương pháp tinh chỉnh từng bước: </b>

<i>for i in range(1,n): </i>

<i>- Chọn số bé nhất trong các số </i>

<i>- Đổi chỗ cho xi for i in range(1,n): </i>

<i>x[i] = x[j] x[j] = tg </i>

Ví dụ: Tìm tất cả các số tự nhiên có hai chữ số, khi đảo trật tự của hai số đó sẽ cho kết quả là một số nguyên tố cùng nhau với số đã cho:

</div><span class="text_page_counter">Trang 26</span><div class="page_container" data-page="26">

<b>Phương pháp quy hoạch động </b>

Nếu trong phương pháp chia để trị chúng ta thường sử dụng kỹ thuật đệ quy và giải bài tốn con nhiều lần vì độ phức tạp của nó là hàm mũ. Để tránh dư thừa một số bài toán con, chúng ta tạo ra bảng lưu các kết quả của bài toán con, khi nào cần ta sẽ tham chiếu đến kết quả trong bảng mà khơng giải lại bài tốn con đó. Để điền đầy trong bảng kết quả của các bài toán con để đạt được kết quả bài toán ban đầu được gọi là quy hoạch động.

<b>Phương pháp quay lui (backtracking) </b>

Phương pháp quay lui là một quá trình giải bài tốn bằng cách phân tích hướng xuống. Tức là tại mỗi bước phân tích ta chưa thể giải quyết bài tốn vì vậy ta phải phân tích cho đến khi đến điểm dừng (tức là đã biết lời giải hoặc không thể cho kết quả theo cách này). Từ các điểm này ta quay lui trở lại vết cũ mà ta đã đi qua để giải quyết bài toán, cuối cùng ta sẽ giải quyết được bài toán ban đầu. Có ba kỹ thuật quay lui đó là: vét cạn, cắt tỉa và nhánh cận.

<b> Ký hiệu BigO (Big-Oh Notation) </b>

Có thể kết luận: f(x)=x<small>2</small>+3x+2 là O(g(x))=x<sup>2 </sup>với mọi x>2

Một ví dụ khác, xét hàm f(n)=2n+6, g(n)=n và c=4, n0=3 ta có f(n)=O(n). Hình 1.4 cho thấy hàm f(n) bị chặn trên bởi hàm g(n) với c là hằng số.

</div><span class="text_page_counter">Trang 27</span><div class="page_container" data-page="27">

<i><small>Hình 1. 4- Đồ thị mô tả cấp độ tăng của hàm</small></i>

<b>Các quy tắc xác định độ phức tạp của giải thuật: </b>

Cho T1(n) và T2(n) là thời gian thực hiện của hai đoạn chương trình P1 và P2, trong đó T1(n) là O(f(n)) và T2(n) là O(g(n)). Ta có các quy tắc sau:

 Quy tắc nhân:

</div><span class="text_page_counter">Trang 28</span><div class="page_container" data-page="28">

Thời gian thực hiện của hai đoạn chương trình trình P1 và P2 lồng nhau thì tổng thời gian chạy của P1 và P2 sẽ là:

 Lệnh (3), (4), (5) và (6) có độ phức tạp là O(1)

 Ở vòng lặp thứ (2), thời gian thực hiện là (n-i) lần, mỗi lần có độ phức tạp là O(1) do đó vịng lặp (2) có độ phức tạp là O((n-i)*1) = O(n-i).

 Trong khi đó vịng lặp (1), chỉ số i chạy từ 1 đến (n-1)

Vậy độ phức tạp của giải thuật Bubble Sort là: <small>2</small> <sup>O(n</sup> <sup>)</sup><small>1)</small>

<small></small>Một số quy tắc khác:

- Độ phức tạp của các phép toán: gán, đọc, viết, goto: O(1)

<b>- Độ phức tạp của cấu trúc lựa chọn: if-else có dạng: if (<điều kiện>): </b>

<b>- Độ phức tạp của lệnh switch được có độ phức tạp như lệnh if-else. - Độ phức tạp của các lệnh lặp: for, while, do-while: </b>

</div><span class="text_page_counter">Trang 29</span><div class="page_container" data-page="29">

Các ví dụ minh họa: Ví dụ 1:

<i>for i in range (0,n): </i>

<i>for j in range (0,n): k=k+1 </i>

Đoạn lệnh trên có độ phức tạp là O(n<small>2</small>) Ví dụ 2:

<i>for i in range (0,n): k=k+1 </i>

<i>for i in range (0,n): </i>

<i> for j in range (0,n): k=k+1 </i>

Đoạn lệnh trên có độ phức tạp là O(n<small>2</small>) Ví dụ 3:

<i>for i in range (0,n-1): for j in range (0,i): </i>

<i>maxSum=thisSum return maxSum </i>

Đoạn lệnh trên có độ phức tạp là O(n<small>3</small>)

</div><span class="text_page_counter">Trang 30</span><div class="page_container" data-page="30">

Đoạn lệnh trên có độ phức tạp là O(n<small>2</small>) Sự phân lớp của các giải thuật:

<i><small>Hình 1. 5- Độ phức tạp về thời gian của giải thuật qua các hàm </small></i>

Tính tốn độ phức tạp của giải thuật trong các trường hợp: xấu nhất, tốt nhất, trung bình. Ví dụ xét thuật tốn tìm kiếm tuần tự sau:

 Trường hợp tốt nhất: phần tử đầu tiên là phần tử cần tìm, số lượng phép so sánh là 2. Vậy T(n) ~ O(2) = O(1)

 Trường hợp xấu nhất: thực hiện các thao tác so sánh đến phần tử cuối cùng, số lượng các phép toán so sánh là 2n. Vậy T(n) ~ O(n)

 Trường hợp trung bình: thực hiện việc so sánh đến phần tử thứ i, cần 2i phép so sánh, như vậy trường hợp trung bình ta có:

</div><span class="text_page_counter">Trang 31</span><div class="page_container" data-page="31">

Các phương pháp diễn đạt giải thuật Khái niệm BigO

Khái niệm về độ phức tạp của thuật toán và ba trường hợp xảy ra khi xét thời gian thực hiện giải thuật: tốt nhất, xấu nhất và trung bình.

Hai quy tắc xác định thời gian thực hiện chương trình là quy tắc cộng và quy tắc nhân

<b> Giới thiệu về ngôn ngữ lập trình Python </b>

Ngơn ngữ lập trình Python được tạo ra bởi Guido Van Rossum. Thiết kế bắt đầu vào cuối những năm 1980 và được phát hành lần đầu tiên vào tháng 2 năm 1991.

Python là ngơn ngữ lập trình đơn giản, nhưng mạnh mẽ và được trang bị những tính năng rất thích hợp cho việc xử lý dữ liệu dạng ngôn ngữ học. Ta có thể tải và cài đặt Python một cách hồn tồn miễn phí tại .

Python cũng là ngơn ngữ hướng đối tượng, và cũng đồng thời là ngôn ngữ động, nó được trang bị những thư viện tiêu chuẩn khổng lồ: từ web, xử lý số học, đến cả lập trình đồ hoạ, machine learning ( ). Python được sử dụng rộng rãi trong sản xuất, khoa học, hay giáo dục và ngày càng trở nên phổ biến và hồn thiện [7],[8].

<b>Các tính năng chính của Python: </b>

• Ngôn ngữ thông dịch cấp cao: Không giống như C/C++ (ngôn ngữ biên dịch), với Python, bạn không phải lo lắng những nhiệm vụ khó khăn như quản lý bộ nhớ, dọn dẹp những dữ liệu.

• Thư viện tiêu chuẩn lớn để giải quyết những tác vụ phổ biến

• Hướng đối tượng: Ngơn ngữ Python hỗ trợ lập trình hướng đối tượng Hạn chế:

• Python khơng có các thuộc tính như: protected, private hay public, khơng có vịng lặp do…while và switch….case.

• Python mặc dù nhanh hơn so với PHP, nhưng lại không nhanh hơn so với C/C++, Java.

</div><span class="text_page_counter">Trang 32</span><div class="page_container" data-page="32">

<b> Một số câu hỏi và bài tập có lời giải </b>

1. Hãy cho biết giải thuật là gì? Nêu các tính chất của giải thuật?

<b>Trả lời: </b>

Giải thuật (Algorithms) là tập hợp các câu lệnh được thể hiện chặt chẽ và rõ ràng bao gồm một trình tự các thao tác thực hiện trên một số đối tượng nào đó, sao cho sau khi thực thi với một số hữu hạn bước sẽ cho kết quả mong muốn. Với mỗi thuật tốn sẽ có dữ liệu vào (input) và dữ liệu ra (output) tương ứng.

Các tính chất của giải thuật: • Tính xác định

• Tính dừng (hữu hạn) • Tính đúng đắn

• Tính phổ dụng • Tính khả thi

2. Cơng cụ nào được dùng để diễn đạt thuật toán?

<b>Trả lời: Để diễn đạt giải thuật ta dùng công cụ: lưu đồ; ngơn ngữ tự nhiên; </b>

ngơn ngữ lập trình; mã giả.

3. Q trình giải quyết bài tốn được thực hiện bằng việc chia bài toán lớn thành các bài toán nhỏ hơn để giải quyết, được áp dụng theo chiến lược nào?

<b>Trả lời: Chiến lược chia để trị (divide- and-conquer) </b>

4. Khi đánh giá độ phức tạp của câu lệnh if ta cần đánh giá điều gì?

<b>Trả lời: Khi đánh giá độ phức tạp của câu lệnh if ta cần đánh giá độ phức tạp </b>

của việc kiểm tra điều kiện và độ phức tạp của câu lệnh bên trong thân lệnh If 5. Trong đoạn chương trình có hai vịng lặp for lồng nhau, quy tắc nào để đánh

giá độ phức tạp của thuật toán?

<b>Trả lời: Dùng quy tắc nhân </b>

6. Độ phức tạp của thuật tốn tính giá trị của biểu thức 1+2+3+...+n là gì?

<b>Trả lời: Biểu thức trên có độ phức tạp O(n) </b>

7. Cho biết độ phức tạp của biểu thức n² + 35n + 6

<b>Trả lời: Biểu thức trên có độ phức tạp O(n</b><small>2</small>)

8. Cho biết độ phức tạp của biểu thức (n - 2)*(n - 4) là gì?

<b>Trả lời: Biểu thức trên có độ phức tạp O(n</b><small>2</small>)

9. Thông thường ta xem T(n) là thời gian thực hiện chương trình trong trường hợp xấu nhất trên dữ liệu vào có kích thước n, vậy T(n) là gì?

</div><span class="text_page_counter">Trang 33</span><div class="page_container" data-page="33">

<b>Trả lời: T(n) là thời gian lớn nhất để thực hiện chương trình đối với mọi dữ liệu vào có cùng kích thước n </b>

<b> Một số câu hỏi và bài tập tự rèn luyện </b>

1. Hãy phân biệt sự khác nhau giữa cấu trúc dữ liệu và cấu trúc lưu trữ? Cho ví dụ? 2. Độ phức tạp đa thức là gì? Cho ví dụ?

3. So sánh O(2n) và O(3n+5)

4. Thời gian thực hiện của một thuật tốn được tính tốn ra kết quả là T(n) = 2*n + n*logn. Ký hiệu O của độ phức tạp thuật tốn trên là gì?

5. Nêu quy tắc cộng và nhân cấp độ tăng của hàm. Có ví dụ minh hoạ?

6. Thời gian thực hiện một chương trình thường phụ thuộc vào các yếu tố nào? Phân tích cụ thể từng yếu tố?

7. Thời gian thực hiện chương trình là T(n) = O(f(n)) có nghĩa là gì? Cho ví dụ minh hoạ?

</div><span class="text_page_counter">Trang 34</span><div class="page_container" data-page="34">

<b>CHƯƠNG 2. ĐỆ QUY </b>

<b>T</b>

rong chương này, người học sẽ nắm được định nghĩa về giải thuật đệ quy, cách thiết kế giải thuật đệ quy để giải một số bài toán. Chương 2 cũng giới thiệu một số dạng đệ quy thường gặp và phương pháp giải một số bài toán đệ quy phổ biến.

<b>Nội dung: </b>

- Giới thiệu đệ quy

- Giải thuật và chương trình đệ quy - Thiết kế giải thuật đệ quy

- Một số giải thuật đệ quy phổ biến

- Một số bài toán minh họa bằng giải thuật đệ quy - Câu hỏi và bài tập

</div><span class="text_page_counter">Trang 35</span><div class="page_container" data-page="35">

<b> Giới thiệu đệ quy Khái niệm: </b>

Đệ quy là một khái niệm cơ bản trong toán học và trong khoa học máy tính. Một đối tượng được gọi là đệ quy nếu nó bao hàm chính nó như bộ phận cấu thành. Nói một cách khác là đối tượng đó được định nghĩa thơng qua chính bản thân nó [3]. Một số ví dụ về định nghĩa đệ quy:

Ví dụ 1: Số 0 là một số tự nhiên, nếu x là một số tự nhiên thì x+1 cũng là số tự nhiên. Ví dụ 2: Cho n=0 thì giai thừa của 0 là 1, khi n>=1 thì n giai thừa bằng (n-1) giai thừa nhân với n. Giả sử tính 4!, ta có tính như sau:

<b> Giải thuật đệ quy và hàm đệ quy </b>

Nếu bài toán T được thực hiện bằng lời giải của bài toán T’ (tham số của T’ có kích thước nhỏ hơn) có dạng giống T là lời giải đệ quy. Giải thuật tương ứng với lời giải như vậy gọi là giải thuật đệ quy. Nguyên lý hoạt động của đệ quy là giảm bài toán lớn thành một hoặc nhiều bài tốn nhỏ hơn có cùng đặc điểm, từ bài toán nhỏ hơn này ta giảm thành nhiều bài toán nhỏ hơn nữa, cứ như vậy ta sẽ giảm bài tốn thành những bài tốn nhỏ nhất có thể đã có lời giải [3].

Hàm đệ quy gồm có hai phần:

 <b>Phần không đệ quy: Là phần cơ sở, đây là trường hợp bài tốn nhỏ nhất có </b>

thể được giải quyết mà không cần đệ quy (phần dừng đệ quy).

Ví dụ: tính n!, trường hợp n=0 thì khơng cần tính nữa gọi là phần cơ sở  <b>Phần đệ quy: Trường hợp này làm giảm một trường hợp thành một hoặc các </b>

trường hợp nhỏ hơn và sẽ giảm dần đến phần cơ sở (phần dừng đệ quy).  Ví dụ 1: tính n!, phần gọi đệ quy là những giá trị (n-1)!, (n-2)! …. và thường

được đặt trong điều kiện n>=1.

Hàm đệ quy của bài tốn tính giai thừa được cài đặt dưới đây bằng Python:

</div><span class="text_page_counter">Trang 36</span><div class="page_container" data-page="36">

 Ví dụ 2: Xét bài tốn tìm một từ trong quyển từ điển (theo cách diễn đạt tựa ngôn ngữ tự nhiên):

<b>Nếu từ điển là một trang: </b>

Tìm một từ trong trang này

<i><small>Hình 2. 1- Cơ chế hoạt động của giải thuật đệ quy </small></i>

Ví dụ 1: Minh họa giải thuật đệ quy của bài toán chuyển cơ số 10 sang cơ số 2. Trong ví dụ này, ta lấy số dư phép chia 7 cho 2 (7%2), đưa số dư này vào ngăn xếp còn phần nguyên của phép chia này ta tiếp tục % cho 2, ta lại đưa số dư này vào ngăn xếp. Thực hiện tương tự cho đến khi nào kết quả của phép chia lấy phần dư là 0, dừng giải thuật.

</div><span class="text_page_counter">Trang 37</span><div class="page_container" data-page="37">

Cài đặt chương trình:

Kết quả:

Ví dụ 2: Minh họa cơ chế hoạt động của bài tốn tính giai thừa của 6.

<i><small>Hình 2. 2 - Cơ chế hoạt động của bài tốn tính giai thừa của 6 </small></i>

<b> Thiết kế giải thuật đệ quy </b>

Để xây dựng giải thuật đệ quy, ta cần thực hiện tuần tự các bước sau:  Xác định bước đệ quy

 Tìm quy tắc dừng  Phác thảo giải thuật

- Dùng câu lệnh if để lựa chọn trường hợp.

</div><span class="text_page_counter">Trang 38</span><div class="page_container" data-page="38">

 Kiểm tra điều kiện ngừng

- Đảm bảo là giải thuật luôn dừng lại.  Vẽ cây đệ quy

- Chiều cao cây ảnh hưởng lượng bộ nhớ cần thiết. - Số nút chính là số lần bước đệ quy được thực hiện.

<b>Ưu điểm và nhược điểm của giải thuật đệ quy </b>

<b>Ưu điểm: Giải thuật đệ quy được thiết kế ngắn gọn cho nên lập trình viên viết chương </b>

trình nhanh và mã lệnh sáng sủa, do khả năng định nghĩa một tập hợp rất lớn các đối tượng bằng một số các tập lệnh hữu hạn.

<b>Khuyết điểm: Giải thuật đệ quy không xác định được bước lặp và không xác định </b>

được rõ ràng số bước thực hiện của giải thuật cho nên sẽ dễ xảy ra trường hợp tràn đệ quy (stack overhead).

Nếu có thể thay thế giải thuật đệ quy bằng một giải thuật khác (khơng đệ quy) thì giải

<i><b>thuật này được gọi là giải thuật khử đệ quy. </b></i>

<i>Chỉ khi nào không thể dùng giải thuật lặp ta mới nên sử dụng giải thuật đệ quy. </i>

<b> Phân loại giải thuật đệ quy Đệ quy tuyến tính </b>

Là đệ quy mà trong thân hàm có duy nhất một lời gọi hàm gọi lại chính nó một cách tường minh.

Cú pháp:

</div><span class="text_page_counter">Trang 39</span><div class="page_container" data-page="39">

Kết quả:

Ví dụ 2: In các dấu sao (*) bằng giải thuật đệ quy tuyến tính

Sau khi chạy chương trình, ta có kết quả là các dấu sao được in trên một hàng.

</div><span class="text_page_counter">Trang 40</span><div class="page_container" data-page="40">

Ví dụ minh họa đệ quy cho bài tốn Fibonacci:

<i><small>Hình 2. 3- Minh họa cơ chế hoạt động đệ quy của bài toán Fibonacci </small></i>

<b>Đệ quy phi tuyến </b>

Là loại đệ quy mà trong thân của hàm có lời gọi hàm gọi lại chính nó được đặt bên trong vòng lặp.

</div>

×