You are on page 1of 11

Student Name: Student’s ID:

DSA - TAKE AWAY COFFEE 12


Câu 1. Chọn thuật ngữ tiếng Anh và tiếng Việt tương ứng: (3 phút)
Thuật ngữ tiếng Việt English Terminologies Trả lời
1. Sắp xếp bằng phương pháp chọn A. Merge Sort 1.C
2. Sắp xếp bằng phương pháp nổi bọt B. Quick Sort 2.D
3. Sắp xếp bằng phương pháp chèn C. Selection Sort 3.F
4. Sắp xếp bằng phương pháp trộn D. Bubble Sort 4.A
5. Sắp xếp dựa vào phần tử chốt E. Heap Sort 5.B
6. Sắp xếp dựa vào heap F. Insertion Sort 6.E
Câu 2. Một định nghĩa hình thức (formal) về bài toán xếp thứ tự (sorting problem):
Trong máy tính, cho trước một dãy N đối tượng. Mỗi đối tượng được lưu trữ thành một trường
dữ liệu (record): R1 , R 2 , … , R N . Mỗi đối tượng R j được đặc trưng bởi một thuộc tính gọi là
khóa (key) K j. Ngoài thuộc tính khóa, các đối tượng còn có thêm các loại dữ liệu khác. Gọi
a , b , c là các giá trị thuộc miền trị của K j. Quan hệ “¿”gọi là có thứ tự trên thuộc tính K j khi các
điều sau được thỏa:
1. Khi so sánh K i và K j (i , j bất kỳ), chỉ một trong ba điều sau là đúng: a< b, a=b , a> b.
2. Nếu a< b và b< c thì a< c .
Ứng dụng cần sắp thứ tự các đối tượng dữ liệu này sao cho các R j có thứ tự “¿” theo thuộc tính
K j. Bài toán sắp xếp được phát biểu một cách hình thức như sau:

Sorting Problem
Input: dãy ⟨ Ri (K i , datai ) , R j (K j , data j ) ,… , R N ( K N , data N ) ⟩ với K i , K j , … , K N có thứ tự bất kỳ.
Output: ⟨ R1 (K 1 , data), R2 ( K 2 , data) , … , R N (K N , data) ⟩ thỏa R1 . K 1 < R2 . K 2< …< R N . K N .
Sorting Problem là một trong những bài toán quan trọng trong lĩnh vực khoa học máy tính vì
nhiều ứng dụng1 sử dụng kết quả của bài toán này như một bước trung gian để giải quyết vấn
đề của ứng dụng đó. Ví dụ các công cụ tìm kiếm sách trong thư viện cần sắp xếp các kết quả trả
về theo thứ tự bảng chữ cái trước khi hiển thị với người dùng.

public static void sort1(int[] a) {


for (int i = a.length-1; i >= 1; i--) {
int index = i; // i is the last item position and
// index is the largest element position
// loop to get the largest element
for (int j = 0; j < i ; j++) {
if (a[j] < a[index])
index = j; // j is the current largest item
}
// Swap the largest item a[index] with the last item a[i]
int temp = a[index];
a[index] = a[i];
a[i] = temp;
}
}

1
Các bạn đọc The Art of Computer Programming - Tập 3: Sorting and Searching.
Câu 3. SelectionSort, BubbleSort và InsertionSort: (100 phút)
1. Điền vào dấu “…” để hoàn thiện thuật toán SelectionSort, BubbleSort và InsertionSort.
Cho biết tên của từng thuật toán.

public static void sort2(int[] a) {


for (int i=1;i < a.length;i++) { //Q: Why i starts from 1?
// a[i] is the next data to insert
int next = a[i];
// Scan backwards to find a place. Q: Why not scan forwards?
int j; // Q: Why is j declared here?
// Q: What if a[j] <= next?
for (j=i-1; j>=0 && a[j]>next; j--)
a[j+1] = a[i];
// Now insert the value next after index j at the end of loop
a[j+1] = next;
}
}

public static void sort3(int[] a) {


for (int i = 1; i < a.length; i++) {
boolean b = true;
for (int j = 0; j < a.length - i; j++) {
if (a[j] > a[j+1]) { //the larger item bubbles down (swap)
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
b = false;
}
}
If(b == true)
return;
}
}

2. Minh họa từng bước từng thuật toán vừa viết trên dãy số sau: 5 , 2 , 4 , 6 , 3 ,1 và trả lời câu hỏi:
Selection sort:
5,2,4,6,3,1 – 1,2,4,6,3,5 – 1,2,4,6,3,5 – 1,2,3,4,6,5 – 1,2,3,4,6,5 – 1,2,3,4,5,6
Bubble sort:
5,2,4,6,3,1 – 2,5,4,6,3,1 – 2,4,5,6,3,1 – 2,4,5,6,3,1 – 2,4,5,3,6,1 – 2,4,5,3,1,6 – 2,4,5,3,1,6 –
2,4,5,3,1,6 – 2,4,3,5,1,6 – 2,4,3,1,5,6 – 2,4,3,1,5,6 – 2,3,4,1,5,6 – 2,3,1,4,5,6 – 2,3,1,4,5,6 –
2,3,1,4,5,6 – 2,3,1,4,5,6 – 2,1,3,4,5,6 - 2,1,3,4,5,6 - 2,1,3,4,5,6 - 2,1,3,4,5,6 – 1,2,3,4,5,6
Insertion sort:
5,2,4,6,3,1 – 2,5,4,6,3,1 – 2,4,5,6,3,1 – 2,4,5,6,3,1 – 2,3,4,5,6,1 – 1,2,3,4,5,6

3. Trường hợp xấu nhất, tốt nhất của mỗi thuật toán xảy ra khi nào? Giải thích?
Selection sort:
-TH xấu nhất : dãy ngược chiều mong muốn.(sort cả dãy )
-TH tốt nhất : dãy cùng chiều mong muốn. ( không cần phải sort )
Bubble sort:
-TH xấu nhất : dãy ngược chiều mong muốn.(sort cả dãy )
-TH tốt nhất : dãy cùng chiều mong muốn. ( không cần phải sort )
Insertion sort:
-TH xấu nhất : dãy ngược chiều mong muốn.(sort cả dãy )
-TH tốt nhất : dãy cùng chiều mong muốn. ( không cần phải sort )

4. Ứng với trường hợp xấu nhất của mỗi thuật toán, hãy:
a. Phân tích và xác định số lần so sánh các phần tử theo n .
Selection sort: O(n^2)
Bubble sort: O(n^2)
Insertion sort: O(n^2)
b. Phân tích và xác định số lần đổi chỗ các phần tử theo n .
Selection sort: O(1)

Bubble sort: O(1)

Insertion sort: O(1)


c. Từ đó, bạn hãy rút ra kết luận gì giữa SelectionSort so với BubbleSort.
Bubble sort tốn nhiều lần so sánh hơn là Selection Sort
5. *Bạn hãy thử tinh chỉnh thuật toán vừa viết và đặt tên là SelectionSort_EarlyAbandon,
BubbleSort_EarlyAbandon để phát hiện và kết thúc sớm hai thuật toán này khi dãy đã có
thứ tự như mong muốn? Việc tinh chỉnh này có làm ảnh hưởng đến Big-O trong trường xấu
nhất hay không? Giải thích? Không, Selection sort với Bubble sort đều sắp xếp theo kiểu
tăng dần nên không ảnh hưởng gì đến Big Oh trong trường hợp xấu nhất.
6. *InsertionSort có thể tinh chỉnh gì thêm để hạn chế số lần đổi chổ các phần tử trong trường
hợp xấu nhất hay không? Giải thích?
- Có, khi mà thực hiện sắp xếp nhanh (Quick Sort) hoặc sắp xếp hợp nhất (Merge Sort), khi
kích thước mảng con trở nên nhỏ hơn (giả sử <=25 phần tử), tốt nhất là sử dụng sắp xếp
chèn nhị phân (Binary Insertion Sort).
7. *InsertionSort có thể tinh chỉnh gì thêm để hạn chế số lần so sánh các phần tử trong trường
hợp xấu nhất hay không? Giải thích? Chi phí phải trả cho sự tinh chỉnh là bao nhiêu?
- Có, chúng ta có thể sử dụng thuật toán sắp xếp chèn nhị phân ( Binary Insertion Sort) khi
số lần so sánh giữa các khóa đủ cao. Trong trường hợp xấu là khi ta muốn lọc ra nhiều chuỗi
thì hiệu suất so sánh của hai chuỗi sẽ cao hơn. O(log N).

8. *Bạn hãy thử lý giải vì sao thuật toán có tên là SelectionSort? BubbleSort? InsertionSort?

Selection Sort : Dùng để đưa phần tử nhỏ nhất về đúng vị trí đầu tiên của dãy hiện hành.
Bubble Sort: so sánh 2 phần tử kề nhau, nếu chúng chưa đứng đúng thứ tự thì swap.Có thể
tiến hành từ trên xuống ( bên trái sang) hoặc từ dưới lên (bên phải sang)
Insertion Sort : giống như cách thức xếp quân bài , khi muốn sắp một bộ dài theo trật tự
người chơi bài rút lần lượt từ quân thứ 2, so với các quân đứng trước nó để chèn vào vị trí
thích hợp.

Câu 4. **Tính đúng đắn của SelectionSort, BubbleSort và InsertionSort:


1. Google phỏng vấn: căn cứ vào đâu mà bạn biết chắc rằng SelectionSort, BubbleSort và
InsertionSort cho kết quả đúng để từ đó tin dùng. Vì nhỡ như sau khi thực thi thuật toán, có
vài phần tử chưa có thứ tự thì sao? => Đáp án: suy nghĩ 2 phút trước khi đọc câu kế tiếp.
-Dựa vào tính bất biến của vòng lặp. Hoặc chia mảng thành nhiều phần và tìm kiếm song song .
Dựa vào tính bất biến của vòng lặp (loop invariant) hãy chứng minh tính đúng đắn của
SelectionSort, và InsertionSort. Gợi ý về tính bất biến: muốn chứng minh thuật toán sắp xếp là
đúng đắn, ta có thể tiến hành 3 bước như sau:
Khởi tạo (initalization): dãy có thứ tự trước khi thực thi lần lặp đầu tiên.
Duy trì (maintenance): dãy vẫn có thứ tự trong suốt quá trình thực thi vòng lặp.
Kết thúc (termination): dãy vẫn có thứ tự sau khi vòng lặp cuối cùng kết thúc.
Đây cũng là cách phổ biến để chứng minh một thuật toán là đúng đắn (correctness).
SelectionSort:
- Trong SelectionSort có 2 điều kiện bất biến của vòng lặp:
+Trong vòng lặp ngoài, mảng được sắp xếp cho i phần tử đầu tiên
+Trong vòng lặp bên trong, min luôn là giá trị nhỏ nhất trong A [i đến j].
BubbleSort:
- Trong thuật toán BubbleSort , sau mỗi lần lặp của vòng lặp, phần tử lớn nhất của mảng luôn
được đặt ở vị trí bên phải nhất, Do đó, điều kiện bất biến của vòng lặp là:
+Ở cuốn lần lặp thứ i.
InsertionSort:
- Trong InsertionSort , điều kiện bất biến của vòng lặp :
+Mảng con a[0 đến i – 1] luôn được sắp xếp
Câu 5. Mã giả của thuật toán HEAPSORT được viết như sau (mảng bắt đầu từ 1):

1. Làm tương tự ví dụ như hình


bên cạnh, hãy minh họa từng
bước thuật toán HEAPSORT
trên dãy số sau:
5 ; 13 ; 2; 25 ; 7 ; 17 ; 20 ; 8 ; 4 .

ANS:
5,13,2,25,7,17,20,8,4 – 5,25,2,13,7,17,20,8,4 – 5,25,20,13,7,17,2,8,4 –
25,5,20,13,7,17,2,8,4 – 4,5,20,13,7,17,2,8,25 (removed) – 4,5,20,13,7,17,2,8 –
4,13,20,8,7,17,2,5 – 20,13,4,8,7,17,2,5 – 5,13,4,8,7,17,2,20 –
5,13,4,8,7,17,2 – 5,13,17,8,7,4,2 – 17,13,5,8,7,4,2 – 2,13,5,8,7,4,17 –
2,13,5,8,7,4 - 13,2,5,8,7,4 – 13,8,5,2,7,4 - 4,8,5,2,7,13 – 4,8,5,2,7 – 8,4,5,2,7 –
8,7,5,2,4 – 4,7,5,2,8 – 4,7,5,2 – 7,4,5,2 – 2,4,5,7 - …

 2,4,5,7,8,13,17,20,25

2. Nếu dãy A có n phần tử đã được xếp thứ tự tăng dần thì thời gian thực thi của HEAPSORT
như thế nào? Cùng câu hỏi này cho trường hợp dãy A có thứ tự giảm dần? thời gian thực thi
gần như nhau.
O(n log n)
3. Có phải big-O về thời gian thực thi trong trường hợp xấu nhất của HEAPSORT là nlg n hay
không? Giải thích? Biết rằng thủ tục MAX_HEAPIFY có chi phí về thời gian tỷ lệ với lgn.
Có,vì giả sử bạn đang sử dụng một đống tối đa được biểu thị dưới dạng một mảng và chèn các phần
tử tối đa của bạn ngược lại vào mảng đầu ra của bạn / vào mặt sau của mảng nếu bạn đang thực hiện
nó tại chỗ, đầu vào trường hợp xấu nhất cho heapSort là bất kỳ đầu vào nào buộc bạn "bong bóng
xuống" hoặc làm nóng lại mỗi khi bạn loại bỏ một phần tử. Điều này xảy ra mỗi khi bạn đang cố
gắng sắp xếp một tập hợp không có bản sao. Nó vẫn sẽ là Θ (n log n).Lý do trường hợp xấu nhất là
Θ (log n) cho một phần tử là vì chiều cao của cây sẽ là log n, và việc phải đi ngang qua toàn bộ
chiều cao là trường hợp xấu nhất, và do đó nó là log n. Chiều cao là log n vì chúng ta có một cây nhị
phân đầy đủ trong đó mọi cha mẹ đều có hai con, và do đó chiều cao của n nút trở thành log n.

Thuộc tính này ngụ ý rằng trường hợp tốt nhất của heapSort là khi tất cả các phần tử đều bằng nhau
(Θ (n), vì bạn không phải chuẩn hóa lại sau mỗi lần xóa, mất thời gian log (n) vì chiều cao tối đa
của heap là log (n )). Tuy nhiên, đây là một trường hợp tệ hại / không thực tế, đó là lý do tại sao
trường hợp thực sự tốt nhất cho heapsort là Θ (n log n).

Câu 6. MergeSort:
1. Một ứng dụng cần trộn hai dãy số B và C đã có thứ tự thành dãy số mới A vẫn có thứ tự. Ví
dụ dãy B={1, 4 , 7 , 8 ,9 }, C={2 , 3 , 5 ,6 } thì dãy A={1 , 2, 3 , 4 ,5 , 6 , 7 , 8 , 9} . Giả sử các giá trị
được lưu trong mảng một chiều.
a. Viết mã giả của thuật toán trộn cho bài toán trên.
b. Phân tích và xác định Big-Oh của thuật toán vừa viết.
Big Oh: nlog(n)

2. Kết hợp với thao tác trộn của câu trước, thuật toán MergeSort được viết như sau:

a. Thực thi từng bước thuật toán MergeSort trên dãy số sau: 21,7,84,19,22,78,6,30 .

b. Thiết lập hệ thức hồi qui của thuật toán MergeSort.


c. Phân tích và xác định Big-O của thuật toán MergeSort.
Big oh: nlog(n)

Câu 7. So sánh MergeSort và InsertionSort:


Với bài toán sắp xếp một dãy bất kỳ trở nên có thứ tự, xét hai giải thuật đã được công bố là sắp
xếp chèn (InsertionSort) và sắp xếp trộn (MergerSort). Thời gian chạy của InsertionSort và
MergeSort được biết như trong bảng sau:
Thời gian Thời gian
Thuật toán Ghi chú
phân tích xấp xỉ
2
Insertion Sort c1 n n
2
n : số lượng phần tử cần sắp xếp
Merge Sort c 2 .n . lgn n . lgn c 1 , c2 : hằng số có thể bỏ qua khi so sánh

Giả sử máy tính A thực hiện giải thuật InsertionSort. Máy tính B thực hiện giải thuật MergeSort
và một số tham số khác được biết như trong bảng sau:
Tốc độ xử lý Giải thuật Số lượng phần tử Ghi chú
Máy tính A 10 lệnh/giây Insertion Sort (2.n )
10 2
c1 = 2
n = 107
Máy tính B 107 lệnh/giây Merge Sort (50.n.lgn) c2 = 50

Với dữ liệu trên thì:


a. Máy A có tốc độ nhanh hơn máy B bao nhiêu lần trong mỗi giây tính toán? 1000 lần
b. Cả hai máy cùng sắp xếp n=107 phần tử. Tính thời gian chạy của mỗi máy?
A: 2 * (10^14/10^10) = 2*10^4

B: 35*10^8
c. Máy tính nào chạy nhanh hơn khi n tăng thêm? Giải thích?
Máy B chạy nhanh hơn. Vì nó có tốc độ xử lý theo số lượng phần tử nhanh hơn máy A.
d. *Bạn thử đoán xem tác giả có tâm ý gì khi soạn bài tập này? Kiểm tra kiến thức về Big O
notation,

Câu 8. Quick Sort có mã giả được viết như sau:


Algorithm QuickSort (left, right: integer);
var j, k: integer;
begin
if right > left then
begin
j = left;
k = right+1;
//Bắt đầu phân hoạch
do
do j=j+1 while a[j] >= a[left];
do k=k-1 while a[k]<= a[left];
if j< k then swap(a[j],a[k]) //Hoán đổi a[j] và a[k]
while j>k;
swap(a[left], a[k]); //Hoàn thành phân hoạch
QuickSort (left, k-1); //Sắp thứ tự các số bé hơn pivot
QuickSort (k+1, right); // Sắp thứ tự các số lớn hơn pivot
end; // Kết thúc if
end;
1. Thực thi thuật toán QuickSort trên dãy số: 66 , 33 , 40 , 22 ,55 , 88 , 60 ,11 , 80 , 20 ,50 , 44 ,77 , 30.
Biết rằng thuật toán luôn chọn phần tử trái nhất làm phần tử chốt (pivot).

2. Trường hợp tốt nhất của QuickSort xảy ra khi nào?


O(Log n)
3. Hệ thức hồi qui của QuickSort trong trường hợp tốt nhất là gì?

Câu 9.
1. Trường hợp xấu nhất của QuickSort xảy ra khi nào?
Khi mà mảng array đã được sort rồi
2. Độ phức tạp tính toán của QuickSort trong trường hợp xấu nhất là bao nhiêu?
O(n^2 )
3. Phân tích và xác định Big-O của QuickSort trong trường hợp trung bình.
O(n logn)
4. *Bạn thử giải thích (theo ý kiến cá nhân của mình) tại sao thuật toán này có tên là
QuickSort? Gợi ý: quan sát độ phức tạp của QuickSort trong trường hợp tốt nhất, xấu nhất và
trung bình để thấy rằng nó có đặc điểm gì đặc biệt so với các thuật toán sắp xếp khác.
Có thể dùng nhanh cho mảng phụ hoặc ít phần tử. Thuật toán này mang tên QuickSort theo em
nghĩ là khi mình chọn 1 điểm then chốt (pivot) có thể chọn bất kỳ tại điểm nào trên mảng. Như
là chọn điểm đầu, điểm cuối, điểm giữa hoặc điểm bất kỳ.Quick sort trong mọi trường hợp đều
mang tính ổn định hơn so với các loại sort khác. Thường sẽ có độ phức tạp tương đương với
(nLogn).
Câu 10. Hãy điền vào bảng sau các ô còn trống:
Thời gian Ý tưởng
Thuật toán Tốt nhất Xấu nhất Trung bình Bộ nhớ chính của
(Best case) (Worst case) (Average case) thuật toán
Selection Sort Ω(n^2) O(n^2) θ(n^2) O(1) Tìm giá trị lớn
nhất hoặc nhỏ
nhất từ các
phần tử và
thay thế với
phần tử cuối
cùng của dãy
Dùng phương
pháp trao đổi
Bubble Sort Ω(n) O(n^2) θ(n^2) O(1)
liền kề
(exchange)
Dự trên so
Insertion Sort Ω(n) O(n^2) θ(n^2) O(1) sánh in-place
để sắp xếp
Dùng kỹ thuật
sắp xếp dựa
Ω(n log(n)) O(n log (n)) trên so sánh
Heap Sort θ(n log(n)) O(1)
dựa trên cấu
trúc dữ liệu
Binary Heap
Khi merge
nhiều phần tử
đã được sắp
xếp sẵn vào 1
dãy mà sap91
O(n log (n)) θ(n log(n))
Merge Sort Ω(n log(n)) O(n) xếp theo thứ
tự từ nhỏ đến
lớn, thì dãy
mới cũng
được sắp xếp
lại.
Sử dụng cách
Quick Sort Ω(n log(n)) O(n^2) Ω(n log(n)) O(n) thức chia để
trị
Câu 11. Bạn có biết?
1. Có một thuật toán sắp xếp tinh tế và độc đáo (chỉ ý kiến cá nhân) có tên là Radix Sort2.
Thuật toán sort xét về các digits từ 0 đến 9 của các hàng đơn vị, hàng chục và hàng nghìn và bỏ
từng cái vào cái xô để đựng (chắc cái này cũng tương tự như stack). Khi xét hàng đơn vị xong
rồi quăng ra các phần tử ra rồi xét hàng chục và tương tự.

2. Một ứng dụng về cách trực quan hóa các thuật toán sắp xếp, bạn có thể xem tại ĐÂY3.
3. Bài viết tổng quan khá đầy đủ về các thuật toán sắp xếp bạn có thể đọc tại ĐÂY4.

2
https://en.wikipedia.org/wiki/Radix_sort
3
https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html
4
https://en.wikipedia.org/wiki/Sorting_algorithm

You might also like