Bài giảng Cấu trúc dữ liệu và thuật toán - Chương 1: Các khái niệm cơ bản - Nguyễn Khánh Phương

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI  
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG  
Cấu trúc dữ liệu và thuật toán  
Nguyễn Khánh Phƣơng  
Computer Science department  
School of Information and Communication technology  
E-mail: [email protected]n  
Nội dung khóa học  
Chương 1. Các khái niệm cơ bản  
Chương 2. Các sơ đồ thuật toán  
Chương 3. Các cấu trúc dữ liệu cơ bản  
Chương 4. Cây  
Chương 5. Sắp xếp  
Chương 6. Tìm kiếm  
Chương 7. Đồ thị  
2
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI  
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG  
Chương 1. Các khái niệm cơ bản  
Nguyễn Khánh Phƣơng  
Computer Science department  
School of Information and Communication technology  
E-mail: [email protected]n  
Nội dung  
1.1. Ví dụ mở đầu  
1.2. Thuật toán và độ phức tạp  
1.3. Kí hiệu tiệm cận  
1.4. Giả ngôn ngữ (Pseudo code)  
1.5. Một số kĩ thuật phân tích thuật toán  
1.6. Giải công thức đệ quy  
4
Nội dung  
1.1. Ví dụ mở đầu  
1.2. Thuật toán và độ phức tạp  
1.3. Kí hiệu tiệm cận  
1.4. Giả ngôn ngữ (Pseudo code)  
1.5. Một số kĩ thuật phân tích thuật toán  
1.6. Giải công thức đệ quy  
5
Ví dụ: Tìm dãy con lớn nhất  
(The maximum subarray problem)  
6
Ví dụ: Tìm dãy con lớn nhất  
(The maximum subarray problem)  
1.1.1. Duyệt toàn bộ (Brute force)  
1.1.2. Duyệt toàn bộ có cải tiến  
1.1.3 Thuật toán đệ quy (Recursive algorithm)  
1.1.4. Thuật toán quy hoạch động (Dynamic programming)  
NGUYỄN KHÁNH PHƢƠNG7  
Bộ môn KHMT – ĐHBK HN  
Ví dụ: Tìm dãy con lớn nhất  
(The maximum subarray problem)  
1.1.1. Duyệt toàn bộ (Brute force)  
1.1.2. Duyệt toàn bộ có cải tiến  
1.1.3 Thuật toán đệ quy (Recursive algorithm)  
1.1.4. Thuật toán quy hoạch động (Dynamic programming)  
8
1.1.1. Thuật toán duyệt toàn bộ giải bài toán dãy con lớn nhất  
• Thuật toán đơn giản đầu tiên có thể nghĩ để giải bài toán đặt  
ra là: Duyệt tất cả các dãy con có thể :  
ai, ai+1 , …, aj với 1 ≤ i ≤ j ≤ n,  
và tính tổng của mỗi dãy con để tìm ra trọng lượng lớn nhất.  
• Trước hết nhận thấy rằng, tổng số các dãy con có thể của  
dãy đã cho là:  
C(n, 1) + C(n, 2) = n2/2 + n/2  
9
Ví dụ ứng dụng  
• Giả sử ta biết giá của cổ phiếu của công ty A từ ngày i đến ngày j như sau:  
Ngày  
1
2
3
4
5
6
7
8
9
10  
11  
12  
13  
14  
15  
16  
17  
Giá  
100 112 109 85  
105 102 86  
63  
81  
101 94  
106 101 79  
93  
89  
95  
• Ta cần mua một số cổ phiếu, duy nhất 1 lần, rồi bán ra tại một ngày nào đó sau đấy.  
• Làm thế nào để tối đa hóa lợi nhuận ?  
– Chiến lược: mua vào lúc giá thấp, bán ra lúc giá cao [buy low, sell high] không phải lúc nào cũng  
cho lợi nhuận cao nhất  
Ví dụ: Cho giá cổ phiếu như ở đồ thị. Ta thu được lợi nhuận cao nhất là 3$ nếu mua vào ở thứ 2 với giá  
7$, và bán ra ở ngày thứ 3 với giá 10$. Giá 7$ mua vào ở ngày 2 không phải là giá thấp nhất, và giá 10$  
bán ra ở ngày 3 cũng không phải là giá cao nhất  
– Lời giải: Ta dễ dàng tìm được bằng cách duyệt hết tất cả các khả năng:  
• Có bao nhiêu cặp ngày mua/bán có thể có trong khoảng thời gian n ngày?  
• Tính lợi nhuận thu được cho mỗi cặp ngày, để tìm cặp ngày có lợi nhuận cao nhất  
– Liệu ta có thể làm tốt hơn hay không?  
10  
• Câu t,rảbằlnờgi: cCáóch quy về bài toán dãy con lớn nhất  
Quy về bài toán dãy con lớn nhất  
Ngày  
1
2
3
4
5
6
7
8
9
10  
11  
12  
13  
14  
15  
16  
17  
Giá  
100 112 109 85  
105 102 86  
63  
81  
101 94  
106 101 79  
93  
89  
95  
• Tìm dãy các ngày liên tiếp sao cho:  
– Tổng lượng giá thay đổi ở ngày cuối so với ngày đầu là lớn nhất  
• Nhìn vào giá của từng ngày  
– Lượng giá thay thay đổi vào ngày i: giá cổ phiếu ngày i trừ đi giá cổ phiếu ngày i-1  
– Ta có mảng giá thay đổi như sau:  
Ngày  
1
2
3
4
5
6
7
8
9
10  
101 94  
20 -7  
11  
12  
106 101 79  
12 -5 -22  
13  
14  
15  
93  
14  
16  
89  
-4  
17  
95  
6
Giá  
100 112 109 85  
12 -3 -24  
105 102 86  
20 -3 -16  
63  
-23  
81  
18  
Thay  
đổi  
– Tìm dãy con liên tiếp có tổng lớn nhất  
• Dãy con lớn nhất  
e.g.: 12,-3,-24,20,-3,-16,-23,18,20,-7,12,-5,-22,14,-4,6  
Dãy con lớn nhất: 18+20+(-7)+12 = 43  
Mua sau ngày thứ 7, bán ra sau ngày thứ 11: mua với giá = 63, bán ra với lúc = 106  
Lợi nhuận =106-63=43  
11  
Thuật toán duyệt toàn bộ: duyệt tất cả các dãy con  
Chỉ số i  
0
1
2
3
4
5
a[i]  
-2  
11  
-4  
13  
-5  
2
i = 0: (-2), (-2, 11), (-2,11, -4), (-2,11,-4,13), (-2,11,-  
4,13,-5), (-2,11,-4,13,-5,2)  
i = 1: (11), (11, -4), (11, -4, 13), (11, -4, 13, -5), (11, -4,  
13, -5, 2)  
i = 2: (-4), (-4, 13), (-4, 13, -5), (-4,13,-5,2)  
i = 3: (13), (13,-5), (13, -5,2)  
int maxSum = 0;  
i = 4: (-5), (-5, 2)  
for (int i=0; i<n; i++) {  
i = 5: (2)  
for (int j=i; j<n; j++) {  
Với mỗi chỉ số i : duyệt tất cả các dãy con bắt đầu từ phần tử  
a[i] có 1 phần tử, có 2 phần tử, … :  
int sum = 0;  
for (int k=i; k<=j; k++)  
sum += a[k];  
•
i = 0: tất cả các dãy con bắt đầu từ a[0] có 1 phần tử, 2 phần  
tử, … 6 phần tử  
i = 1: tất cả các dãy con bắt đầu từ a[1] có 1 phần tử, 2 phần  
tử, … 5 phần tử  
•
if (sum > maxSum)  
maxSum = sum;  
•
•
…
i = 5: tất cả các dãy con bắt đầu từ a[5] có 1 phần tử  
}
12  
}
Thuật toán duyệt toàn bộ: duyệt tất cả các dãy con  
• Phân tích thuật toán: Ta sẽ tính số lượng phép cộng mà thuật toán phải thực hiện, tức là đếm  
xem dòng lệnh  
sum += a[k]  
phải thực hiện bao nhiều lần. Số lượng phép cộng là:  
n
i
2
i
0
j
i
0
i
0
n
1
2
2
k
1
k
1
k
1
n 3  
n 2  
n
int maxSum = 0;  
6
2
3
for (int i=0; i<n; i++) {  
for (int j=i; j<n; j++) {  
int sum = 0;  
for (int k=i; k<=j; k++)  
sum += a[k];  
if (sum > maxSum)  
maxSum = sum;  
}
13  
}
Ví dụ: Tìm dãy con lớn nhất  
(The maximum subarray problem)  
1.1.1. Duyệt toàn bộ (Brute force)  
1.1.2. Duyệt toàn bộ có cải tiến  
1.1.3 Thuật toán đệ quy (Recursive algorithm)  
1.1.4. Thuật toán quy hoạch động (Dynamic programming)  
14  
1.1.2. Duyệt toàn bộ có cải tiến  
Thuật toán duyệt toàn bộ: duyệt tất cả các dãy con  
Chỉ số i  
0
1
2
3
4
5
a[i]  
-2  
11  
-4  
13  
-5  
2
i = 0: (-2), (-2, 11), (-2,11, -4), (-2,11,-4,13), (-2,11,-4,13,-5), (-2,11,-  
4,13,-5,2)  
i = 1: (11), (11, -4), (11, -4, 13), (11, -4, 13, -5), (11, -4, 13, -5, 2)  
i = 2: (-4), (-4, 13), (-4, 13, -5), (-4,13,-5,2)  
i = 3: (13), (13,-5), (13, -5,2)  
i = 4: (-5), (-5, 2)  
i = 5: (2)  
int maxSum = 0;  
for (int i=0; i<n; i++) {  
for (int j=i; j<n; j++) {  
int sum = 0;  
int maxSum = a[0];  
for (int i=0; i<n; i++) {  
int sum = 0;  
for (int j=i; j<n; j++) {  
sum += a[j];  
for (int k=i; k<=j; k++)  
sum += a[k];  
if (sum > maxSum)  
maxSum = sum;  
}
if (sum > maxSum)  
maxSum = sum;  
}
5  
}
}
1.1.2. Duyệt toàn bộ có cải tiến  
Thuật toán duyệt toàn bộ: duyệt tất cả các dãy con  
• Cài đặt cải tiến:  
Nhận thấy, ta có thể tính tổng các phần tử từ vị trí i đến j từ tổng của các phần  
tử từ i đến j-1 chỉ bằng 1 phép cộng:  
j
j
k
i
k
i
Tổng các phần tử từ i đến j  
Tổng các phần tử từ i đến j-1  
int maxSum = 0;  
for (int i=0; i<n; i++) {  
for (int j=i; j<n; j++) {  
int sum = 0;  
int maxSum = a[0];  
for (int i=0; i<n; i++) {  
int sum = 0;  
for (int j=i; j<n; j++) {  
sum += a[j];  
for (int k=i; k<=j; k++)  
sum += a[k];  
if (sum > maxSum)  
maxSum = sum;  
}
if (sum > maxSum)  
maxSum = sum;  
}
}
16  
}
1.1.2. Duyệt toàn bộ có cải tiến  
Thuật toán duyệt toàn bộ: duyệt tất cả các dãy con  
• Phân tích thuật toán. Ta lại tính số lần thực hiện phép cộng:  
Sum += a[j]  
Và thu được kết quả:  
n 2  
n
n
( n 1) ... 1  
2
2
i
0
• Để ý rằng số này là đúng bằng số lượng dãy con. Dường như thuật toán thu được là  
rất tốt, vì ta phải xét mỗi dãy con đúng 1 lần.  
int maxSum = a[0];  
for (int i=0; i<n; i++) {  
int sum = 0;  
for (int j=i; j<n; j++) {  
sum += a[j];  
if (sum > maxSum)  
maxSum = sum;  
}
17  
}
Ví dụ: Tìm dãy con lớn nhất  
(The maximum subarray problem)  
1.1.1. Duyệt toàn bộ (Brute force)  
1.1.2. Duyệt toàn bộ có cải tiến  
1.1.3 Thuật toán đệ quy (Recursive algorithm)  
1.1.4. Thuật toán quy hoạch động (Dynamic programming)  
18  
1.1.3. Thuật toán đệ quy giải bài toán dãy con lớn nhất  
• Ta còn có thể xây dựng thuật toán tốt hơn nữa bằng kỹ thuật chia để trị  
(divide-and-conquer). Kỹ thuật này bao gồm các bước sau:  
– Chia bài toán cần giải ra thành các bài toán con cùng dạng  
– Giải mỗi bài toán con một cách đệ qui  
• Trường hợp cơ sở: khi bài toán con có kích thước đủ nhỏ, ta giải  
nó bằng phương pháp duyệt toàn bộ.  
– Tổ hợp lời giải của các bài toán con để thu được lời giải của bài toán  
xuất phát.  
• Để giải bài toán dãy con lớn nhất:  
– Sử dụng phần tử chính giữa để chia đôi dãy đã cho thành hai dãy con (gọi tắt là  
dãy nửa trái và dãy nửa phải) với độ dài giảm đi một nửa  
low  
mid  
high  
mid +1  
Nửa trái A[low..mid]  
Nửa phải A[mid+1..high]  
19  
1.1.3. Thuật toán đệ quy giải bài toán dãy con lớn nhất  
• Để tổ hợp lời giải, nhận thấy rằng dãy con lớn nhất A[i..j] của dãy A[low..high] chỉ có thể xảy ra một  
trong 3 trường hợp (với mid = (low+high)/2 ):  
– Dãy con lớn nhất nằm ở dãy nửa bên trái A[low..mid] (low i j mid)  
– Dãy con lớn nhất nằm ở dãy nửa bên phải A[mid+1..high] (mid < i j high)  
– Giao điểm giữa mid (low i mid < j high) {dãy con lớn nhất bắt đầu ở nửa trái và kết thúc ở nửa  
phải}  
• Do đó, nếu kí hiệu trọng lượng của dãy con lớn nhất ở nửa trái là wL, ở nửa phải làwR, và giao điểm giữa  
là wM, thì trọng lượng lớn nhất cần tìm là max(wL, wR, wM)  
20  
Tải về để xem bản đầy đủ
pdf 173 trang yennguyen 13620 Free
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Cấu trúc dữ liệu và thuật toán - Chương 1: Các khái niệm cơ bản - Nguyễn Khánh Phương", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • pdfbai_giang_cau_truc_du_lieu_va_thuat_toan_chuong_1_cac_khai_n.pdf