KHOA CÔNG NGHỆ THÔNG TIN
BỘ MÔN KHOA HỌC MÁY TÍNH
Đề ôn tập số 01
ĐỀ ÔN TẬP GIỮA KỲ HỌC PHẦN DSA
Môn: Cấu trúc dữ liệu và Giải thuật
Thời gian làm bài: 60 phút (không kể thời gian phát đề)
PHẦN I. TRẮC NGHIỆM (3,0 điểm)
Thí sinh chọn một phương án đúng duy nhất cho mỗi câu hỏi sau:
Câu 1. Trong thuật toán Quick-Find, độ phức tạp thời gian trong trường hợp tồi nhất của thao tác `union(p, q)` trên tập phần tử là:
A.
B.
C.
D.
Câu 2. Cho một Stack rỗng. Thực hiện chuỗi thao tác: `push(3)`, `push(5)`, `pop()`, `push(7)`, `push(9)`, `pop()`. Giá trị còn lại ở đỉnh Stack là:
A.
B.
C.
D.
Câu 3. Thuật toán Sắp xếp Chèn (Insertion Sort) thực hiện số phép so sánh ít nhất khi dãy đầu vào có đặc điểm gì?
A. Đã được sắp xếp giảm dần
B. Đã được sắp xếp tăng dần (hoặc gần như đã sắp xếp)
C. Các phần tử ngẫu nhiên
D. Nửa đầu tăng dần, nửa sau giảm dần
Câu 4. Đâu là phát biểu ĐÚNG về thuật toán Mergesort?
A. Thuật toán sắp xếp tại chỗ (In-place) không tốn bộ nhớ phụ
B. Độ phức tạp thời gian trường hợp tồi nhất là
C. Thuật toán có tính chất ổn định (Stable) và cần bộ nhớ phụ
D. Chạy nhanh nhất khi mảng đầu vào đã sắp xếp ngược
Câu 5. Cho Max Heap nhị phân biểu diễn dưới dạng mảng (chỉ số bắt đầu từ ). Nút ở chỉ số () có nút cha nằm ở chỉ số nào?
A.
B.
C.
D.
Câu 6. Để thu được danh sách các khóa theo thứ tự tăng dần từ một Cây tìm kiếm nhị phân (BST), ta thực hiện duyệt cây theo thứ tự nào?
A. Preorder (Tiền tự)
B. Inorder (Trung tự)
C. Postorder (Hậu tự)
D. Level-order (Theo tầng)
Câu 7. Cấu trúc dữ liệu Weighted Quick-Union đảm bảo chiều cao tối đa của bất kỳ cây nào chứa phần tử không vượt quá:
A.
B.
C.
D.
Câu 8. Thuật toán Quickselect dùng để tìm phần tử nhỏ thứ trong mảng phần tử có độ phức tạp thời gian trung bình (khi đã shuffle) là:
A.
B.
C.
D.
Câu 9. Thuật toán sắp xếp nào dưới đây KHÔNG phải là thuật toán sắp xếp tại chỗ (In-place)?
A. Selection Sort
B. Insertion Sort
C. Mergesort
D. Heapsort
Câu 10. Khi thêm một phần tử mới vào Max Heap nhị phân chứa phần tử, số phép so sánh nhiều nhất cần thực hiện (thao tác `swim`) là:
A.
B.
C.
D.
Câu 11. Biểu thức Tilde () xấp xỉ cho hàm khi rất lớn là:
A.
B.
C.
D.
Câu 12. Cho Danh sách liên kết đơn có hai con trỏ `head` và `tail`. Thao tác nào sau đây có độ phức tạp thời gian tồi nhất là ?
A. Thêm phần tử vào đầu danh sách (`addFirst`)
B. Thêm phần tử vào cuối danh sách (`addLast`)
C. Xóa phần tử ở đầu danh sách (`removeFirst`)
D. Xóa phần tử ở cuối danh sách (`removeLast`)
Câu 13. Thuật toán Sắp xếp Chọn (Selection Sort) có đặc điểm nào sau đây?
A. Số phép đổi chỗ (exchange) luôn là trong mọi trường hợp
B. Là thuật toán sắp xếp ổn định (Stable)
C. Số phép so sánh phụ thuộc nhiều vào dữ liệu đầu vào
D. Bộ nhớ phụ cần dùng là
Câu 14. Trong thuật toán Dijkstra 2-stack để tính giá trị biểu thức số học, khi gặp toán tử (ví dụ `+`, `*`), ta xử lý như thế nào?
A. Pop hai giá trị ra tính toán ngay
B. Đẩy toán tử vào stack toán tử (`ops`)
C. Bỏ qua toán tử
D. Đẩy toán tử vào stack giá trị (`vals`)
Câu 15. Chiều cao tồi nhất (worst-case height) của một cây BST chứa phần tử là:
A.
B.
C.
D.
PHẦN II. TỰ LUẬN (7,0 điểm)
Câu 1 (1,5 điểm - Phân tích độ phức tạp).
Cho đoạn mã nguồn C++ / Java sau:
int countPairs(int a[], int N) {
int count = 0;
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
if (a[i] == a[j]) {
count++;
}
}
}
return count;
}
a) Hãy tính chính xác số lần thực hiện phép so sánh `a[i] == a[j]` theo .
b) Cho biết độ phức tạp tính toán theo ký hiệu và ký hiệu Tilde () của thuật toán trên.
Câu 2 (1,5 điểm - Stack & Queue).
a) Cho một Queue rỗng. Cho chuỗi thao tác:
Hãy cho biết trạng thái của Queue sau mỗi thao tác và giá trị trả về của các thao tác `dequeue()`, `isEmpty()` (Quy ước bên phải là đầu ra / đầu lấy phần tử của Queue).
b) Viết hàm bằng mã giả hoặc Java `void reverseK(Queue<Integer> q, int k)` sử dụng đúng Stack phụ để đảo ngược thứ tự phần tử đầu tiên của Queue , giữ nguyên thứ tự tương đối của các phần tử còn lại.
Câu 3 (1,5 điểm - Sắp xếp & Heap).
a) Cho dãy số . Minh họa từng bước quá trình sắp xếp dãy tăng dần bằng thuật toán Insertion Sort.
b) Cho mảng Max Heap nhị phân hiện tại: `[-, T, S, R, A, C, B]` (ô đầu tiên để trống ở chỉ số 0). Minh họa từng bước quá trình thêm khóa `U` vào heap.
Câu 4 (1,5 điểm - Cây tìm kiếm nhị phân BST).
a) Vẽ cây nhị phân tìm kiếm thu được sau khi thêm lần lượt chuỗi khóa `E, C, G, A, D, F, H` vào cây rỗng.
b) Viết hàm đệ quy tính chiều cao (`height`) của cây BST.
Câu 5 (1,0 điểm - Bài toán ứng dụng).
Hãy thiết kế cấu trúc dữ liệu `MinMaxStack` hỗ trợ các thao tác `push(x)`, `pop()`, `getMin()`, `getMax()` đều đạt độ phức tạp thời gian trong trường hợp tồi nhất và bộ nhớ phụ . Mô tả ý tưởng và mã giả.
--------- HẾT ĐỀ SỐ 1 ---------
KHOA CÔNG NGHỆ THÔNG TIN
BỘ MÔN KHOA HỌC MÁY TÍNH
Đề ôn tập số 02
ĐỀ ÔN TẬP GIỮA KỲ HỌC PHẦN DSA
Môn: Cấu trúc dữ liệu và Giải thuật
Thời gian làm bài: 60 phút (không kể thời gian phát đề)
PHẦN I. TRẮC NGHIỆM (3,0 điểm)
Thí sinh chọn một phương án đúng duy nhất cho mỗi câu hỏi sau:
Câu 1. Thao tác `connected(p, q)` trong thuật toán Quick-Union cơ bản có độ phức tạp tồi nhất là:
A.
B.
C.
D.
Câu 2. Hàng đợi (Queue) là cấu trúc dữ liệu hoạt động theo nguyên tắc nào?
A. LIFO (Last In First Out)
B. FIFO (First In First Out)
C. Random Access
D. Highest Priority First
Câu 3. Thuật toán Sắp xếp Nổi bọt (Bubble Sort) cải tiến (dừng khi không có phép đổi chỗ) có độ phức tạp tốt nhất (Best case) là:
A.
B.
C.
D.
Câu 4. Trong thuật toán Mergesort Top-down, mảng phụ `aux` nên được cấp phát bộ nhớ ở đâu để tối ưu hiệu năng?
A. Bên trong hàm đệ quy `sort()`
B. Tạo một lần duy nhất ở hàm khởi tạo / hàm gọi ngoài cùng
C. Cấp phát động tại hàm `merge()`
D. Không cần dùng mảng phụ
Câu 5. Cho mảng biểu diễn Max Heap: `[-, 90, 70, 80, 30, 40, 50, 60]`. Khóa con trái và con phải của nút có giá trị lần lượt là:
A.
B.
C.
D.
Câu 6. Khi xóa một nút có đầy đủ con trong cây BST, ta thay thế bằng nút nào để giữ nguyên tính chất BST?
A. Nút gốc của cây
B. Nút nhỏ nhất trên cây con bên trái hoặc nút lớn nhất trên cây con bên phải
C. Nút lớn nhất trên cây con bên trái (Predecessor) hoặc nút nhỏ nhất trên cây con bên phải (Successor)
D. Nút lá bất kỳ
Câu 7. Thuật toán 3-way Quicksort (phân chia 3 đoạn) đạt hiệu năng vượt trội khi mảng đầu vào có đặc điểm gì?
A. Đã được sắp xếp hoàn toàn
B. Chứa rất nhiều khóa trùng lặp (nhiều phần tử bằng nhau)
C. Mảng có kích thước rất nhỏ
D. Mảng giảm dần
Câu 8. Đối với Danh sách liên kết kép (Doubly Linked List) có con trỏ `head` và `tail`, thao tác xóa phần tử ở cuối danh sách (`removeLast`) có độ phức tạp thời gian là:
A.
B.
C.
D.
Câu 9. Thuật toán sắp xếp nào dưới đây KHÔNG có tính ổn định (Unstable)?
A. Insertion Sort
B. Mergesort
C. Quicksort
D. Selection Sort (khi cài trên DSLK)
Câu 10. Phép toán `sink(k)` (hạ xuống) trong Max Heap được sử dụng trong thao tác nào?
A. Thêm phần tử mới (`insert`)
B. Xóa phần tử lớn nhất (`delMax`) và dựng Heap
C. Lấy giá trị lớn nhất (`getMax`)
D. Kiểm tra heap rỗng
Câu 11. Số phép so sánh nhiều nhất trong trường hợp tồi nhất của thuật toán Tìm kiếm nhị phân (Binary Search) trên mảng phần tử là:
A.
B.
C.
D.
Câu 12. Trong cài đặt Stack bằng mảng tự điều chỉnh kích thước (Resizing Array), mảng sẽ gấp đôi dung lượng khi nào?
A. Stack bị rỗng
B. Số phần tử bằng kích thước mảng ()
C. Số phần tử bằng
D. Số phần tử bằng
Câu 13. Biểu thức Trung tố khi chuyển sang biểu thức Hậu tố (Postfix) là:
A.
B.
C.
D.
Câu 14. Nếu thêm lần lượt các khóa đã sắp xếp tăng dần vào một cây BST rỗng, cây thu được sẽ có dạng gì?
A. Cây cân bằng hoàn hảo
B. Cây bị suy biến thành danh sách tuyến tính lệch phải
C. Cây nhị phân đầy đủ
D. Heap max
Câu 15. Kỹ thuật "Shuffle" (tráo ngẫu nhiên mảng) trước khi chạy Quicksort nhằm mục đích gì?
A. Tăng tính ổn định của thuật toán
B. Đảm bảo thời gian chạy với xác suất cực cao, tránh trường hợp tồi nhất
C. Giảm bộ nhớ phụ
D. Chuyển mảng thành Max Heap
PHẦN II. TỰ LUẬN (7,0 điểm)
Câu 1 (1,5 điểm - Phân tích thuật toán).
Cho đoạn code Java sau tính tổng các phần tử mảng:
void processArray(int a[], int N) {
int sum = 0;
for (int i = 1; i < N; i *= 2) {
for (int j = 0; j < i; j++) {
sum += a[j];
}
}
}
a) Tính số lần thực hiện lệnh `sum += a[j]` theo khi .
b) Xác định cấp phát triển (Order of growth) theo của đoạn code trên.
Câu 2 (1,5 điểm - Stack & Queue).
a) Cho một Stack rỗng. Cho chuỗi thao tác:
Cho biết tình trạng Stack sau mỗi thao tác và kết quả trả về của các hàm `pop()`, `isEmpty()`.
b) Viết hàm `boolean isBalanced(String expr)` sử dụng Stack để kiểm tra tính hợp lệ của các cặp dấu ngoặc `()`, `[]`, `{}` trong chuỗi `expr`.
Câu 3 (1,5 điểm - Sắp xếp & Heap).
a) Cho mảng chưa sắp xếp . Hãy minh họa quá trình dựng Max Heap tại chỗ (`buildHeap` bằng phương pháp bottom-up / dùng `sink`).
b) Cho mảng Max Heap hiện tại: `[-, U, T, S, B, D, C]`. Minh họa từng bước xóa phần tử lớn nhất khỏi heap.
Câu 4 (1,5 điểm - Cây BST).
a) Cho chuỗi khóa `M, B, D, C, A, S, H, P, E`. Vẽ cây BST thu được sau khi thêm chuỗi khóa trên vào cây rỗng.
b) Viết hàm đệ quy `int countLeaves(Node root)` đếm số lượng nút lá (nút không có con) trong cây BST.
Câu 5 (1,0 điểm - Bài toán ứng dụng).
Cho một mảng chứa số nguyên, trong đó có một phần tử xuất hiện nhiều hơn lần (phần tử đa số - Majority Element). Hãy đề xuất thuật toán tìm phần tử này với thời gian hoặc và bộ nhớ phụ (gợi ý: dùng Quickselect hoặc Boyer-Moore Voting).
--------- HẾT ĐỀ SỐ 2 ---------
KHOA CÔNG NGHỆ THÔNG TIN
BỘ MÔN KHOA HỌC MÁY TÍNH
Đề ôn tập số 03
ĐỀ ÔN TẬP GIỮA KỲ HỌC PHẦN DSA
Môn: Cấu trúc dữ liệu và Giải thuật
Thời gian làm bài: 60 phút (không kể thời gian phát đề)
PHẦN I. TRẮC NGHIỆM (3,0 điểm)
Thí sinh chọn một phương án đúng duy nhất cho mỗi câu hỏi sau:
Câu 1. Trong thuật toán Weighted Quick-Union với Path Compression, độ phức tạp thời gian amortized cho mỗi thao tác find/union là:
A.
B. (Gần như hằng số, là hàm Inverse Ackermann)
C.
D.
Câu 2. Cấu trúc dữ liệu nào phù hợp nhất để quản lý chức năng "Undo" (Hoàn tác) trong trình soạn thảo văn bản?
A. Queue
B. Stack
C. Priority Queue
D. Binary Search Tree
Câu 3. Thuật toán Selection Sort thực hiện bao nhiêu phép đổi chỗ (swap/exchange) trong trường hợp tồi nhất đối với mảng phần tử?
A.
B.
C. (Tuyến tính )
D.
Câu 4. Nhược điểm lớn nhất của Mergesort so với Quicksort là gì?
A. Độ phức tạp trường hợp tồi nhất lớn hơn
B. Cần bộ nhớ phụ cho mảng trộn
C. Không có tính ổn định
D. Chạy chậm trên dữ liệu lớn
Câu 5. Chiều cao của một Cây nhị phân hoàn chỉnh (Complete Binary Tree) chứa nút là:
A.
B.
C.
D.
Câu 6. Trong cây BST, thao tác `select(k)` trả về thông tin gì?
A. Khóa có giá trị bằng
B. Khóa có xếp hạng (rank) đúng bằng (khóa nhỏ thứ )
C. Độ sâu của nút
D. Chiều cao của cây con tại
Câu 7. Trong thuật toán Quicksort tiêu chuẩn (hoặc Lomuto/Hoare partition), sau bước phân chia (partitioning) đầu tiên với chốt , vị trí của chốt có đặc điểm gì?
A. Nằm ở đầu mảng
B. Nằm ở cuối mảng
C. Đã đứng đúng vị trí chính xác của nó trong mảng sau khi sắp xếp
D. Luôn nằm chính giữa mảng
Câu 8. Thuật toán Heapsort có độ phức tạp thời gian trong trường hợp tồi nhất là:
A.
B.
C.
D.
Câu 9. Cho mảng Max Heap: `[-, 95, 80, 75, 30, 40, 50, 60]`. Sau khi thực hiện 1 thao tác `delMax()`, giá trị ở gốc Heap mới là bao nhiêu?
A.
B.
C.
D.
Câu 10. Trong Danh sách liên kết đơn, để chèn một nút mới vào ngay sau nút , ta cần thực hiện các lệnh nào (theo thứ tự)?
A. `P.next = newNode; newNode.next = P.next;`
B. `newNode.next = P.next; P.next = newNode;`
C. `P.next = newNode; newNode.next = null;`
D. `newNode.next = P; P = newNode;`
Câu 11. Vòng lặp `for (int i = N; i > 0; i /= 2)` thực hiện bao nhiêu lần lặp?
A.
B.
C.
D.
Câu 12. Cho biểu thức Hậu tố (Postfix): `5 3 2 * + 4 -`. Giá trị của biểu thức là:
A.
B.
C.
D.
Câu 13. Trong mảng vòng (Circular Array) dùng cài đặt Queue kích thước , vị trí tiếp theo của chỉ số `rear` sau khi tăng được tính theo công thức nào?
A. `(rear + 1) % M`
B. `rear + 1`
C. `(rear % M) + 1`
D. `rear % (M + 1)`
Câu 14. Thao tác `floor(key)` trong cây BST trả về:
A. Khóa nhỏ nhất trong cây
B. Khóa lớn nhất trong cây nhỏ hơn hoặc bằng `key`
C. Khóa nhỏ nhất trong cây lớn hơn hoặc bằng `key`
D. Chiều sâu của `key`
Câu 15. Thuật toán sắp xếp nào sau đây hoạt động theo mô hình Chia để trị (Divide and Conquer)?
A. Selection Sort
B. Insertion Sort
C. Mergesort
D. Heapsort
PHẦN II. TỰ LUẬN (7,0 điểm)
Câu 1 (1,5 điểm - Phân tích thuật toán).
Cho đoạn code sau kiểm tra mảng:
void checkMatch(int a[], int N) {
int count = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (i < j && a[i] == a[j]) {
count++;
}
}
}
}
a) Tính chính xác số lần phép so sánh `a[i] == a[j]` được thực hiện.
b) Tính số lần phép so sánh `i < j` được thực hiện. Độ phức tạp của thuật toán là gì?
Câu 2 (1,5 điểm - Stack & Queue / Danh sách liên kết).
a) Cho Queue rỗng. Thực hiện:
Trình bày trạng thái Queue sau mỗi bước và kết quả các hàm.
b) Viết hàm bằng Java/mã giả `Node removeAllX(Node head, int x)` xóa tất cả các nút có giá trị bằng khỏi Danh sách liên kết đơn.
Câu 3 (1,5 điểm - Sắp xếp & Heap).
a) Cho mảng . Minh họa từng bước quá trình sắp xếp mảng tăng dần bằng Mergesort Top-down (vẽ cây đệ quy trộn).
b) Cho mảng Max Heap nhị phân: `[-, 90, 80, 70, 20, 40, 30]`. Minh họa từng bước quá trình thêm khóa vào Heap.
Câu 4 (1,5 điểm - Cây BST).
a) Thêm các khóa vào cây BST rỗng. Vẽ cây kết quả. Sau đó vẽ cây thu được sau khi xóa khóa .
b) Viết hàm đệ quy `Key maxKey(Node root)` trả về giá trị khóa lớn nhất trong cây BST.
Câu 5 (1,0 điểm - Bài toán ứng dụng).
Thiết kế thuật toán độ phức tạp tìm chỉ số của phần tử đầu tiên trong mảng đã sắp xếp chỉ chứa các số và (giả sử mảng có dạng ). Viết mã giả dựa trên Tìm kiếm nhị phân.
--------- HẾT ĐỀ SỐ 3 ---------
KHOA CÔNG NGHỆ THÔNG TIN
BỘ MÔN KHOA HỌC MÁY TÍNH
Đề ôn tập số 04
ĐỀ ÔN TẬP GIỮA KỲ HỌC PHẦN DSA
Môn: Cấu trúc dữ liệu và Giải thuật
Thời gian làm bài: 60 phút (không kể thời gian phát đề)
PHẦN I. TRẮC NGHIỆM (3,0 điểm)
Thí sinh chọn một phương án đúng duy nhất cho mỗi câu hỏi sau:
Câu 1. Trong bài toán Dynamic Connectivity, tập hợp các phần tử liên thông tạo thành một:
A. Quan hệ thứ tự toàn phần
B. Quan hệ tương đương (Equivalence relation)
C. Cây nhị phân
D. Đồ thị có hướng không chu trình (DAG)
Câu 2. Chuyển biểu thức Trung tố sang biểu thức Hậu tố (Postfix):
A.
B.
C.
D.
Câu 3. Thuật toán sắp xếp nào có số phép truy nhập mảng (Array accesses) ít nhất trong trường hợp tồi nhất đối với mảng đã sắp xếp ngược?
A. Insertion Sort
B. Selection Sort
C. Quicksort
D. Bubble Sort
Câu 4. Trong thuật toán 3-way Quicksort, sau khi phân chia mảng theo chốt , mảng được chia thành 3 đoạn nào?
A. , ,
B. , ,
C. , ,
D. Trái, Giữa, Phải
Câu 5. Trong một Min Heap nhị phân, phần tử nhỏ nhất luôn nằm ở vị trí nào?
A. Nút lá cuối cùng
B. Nút gốc (chỉ số 1)
C. Nút con trái của gốc
D. Nút bất kỳ ở tầng cuối
Câu 6. Nút gốc (Root) của một cây nhị phân có đặc điểm gì?
A. Không có con
B. Không có nút cha (Parent is null)
C. Luôn có 2 con
D. Có độ sâu bằng chiều cao cây
Câu 7. Nếu chạy Quicksort tiêu chuẩn (chọn chốt là phần tử đầu tiên, không shuffle) trên mảng đã sắp xếp tăng dần, độ phức tạp thời gian sẽ là:
A.
B.
C.
D.
Câu 8. Kỹ thuật "Bồi hoàn" (Amortized Analysis) cho thao tác `push` trên Stack dùng mảng tự gấp đôi kích thước cho kết quả độ phức tạp trung bình là:
A.
B.
C.
D.
Câu 9. Thuật toán Sắp xếp Chèn (Insertion Sort) chạy mất thời gian khi mảng đầu vào có số cặp nghịch đảo (inversions) là:
A.
B.
C. (Mảng gần như đã sắp xếp)
D.
Câu 10. Trong Max Heap nhị phân (mảng từ index 1), thao tác `swim(k)` thực hiện so sánh khóa ở vị trí với nút nào?
A.
B.
C.
D.
Câu 11. Số lượng liên kết null trong một cây nhị phân có nút là bao nhiêu?
A.
B.
C.
D.
Câu 12. Mảng gồm phần tử có số lượng cặp nghịch đảo (inversions) nhiều nhất là bao nhiêu?
A.
B.
C.
D.
Câu 13. Trong cây BST, thao tác `ceiling(key)` trả về khóa nào?
A. Khóa nhỏ nhất trong cây lớn hơn hoặc bằng `key`
B. Khóa lớn nhất trong cây nhỏ hơn hoặc bằng `key`
C. Khóa ở tầng trên cùng
D. Khóa gốc
Câu 14. Cấu trúc dữ liệu Túi (Bag) khác Stack và Queue ở điểm cơ bản nào?
A. Không cho phép chứa các phần tử trùng lặp
B. Không hỗ trợ thao tác xóa phần tử chỉ định (chỉ hỗ trợ thêm và duyệt)
C. Có dung lượng cố định
D. Chỉ lưu trữ kiểu dữ liệu số nguyên
Câu 15. Độ phức tạp không gian (Auxiliary Space) của thuật toán Quicksort tiêu chuẩn (do bộ nhớ stack đệ quy) trong trường hợp trung bình là:
A.
B.
C.
D.
PHẦN II. TỰ LUẬN (7,0 điểm)
Câu 1 (1,5 điểm - Phân tích thuật toán).
Cho thuật toán Tìm kiếm nhị phân (Binary Search).
a) Tính số lần gọi hàm `compare` trong trường hợp tốt nhất và tồi nhất theo .
b) Giải thích ý nghĩa của công thức `mid = lo + (hi - lo) / 2` thay vì `(lo + hi) / 2`.
Câu 2 (1,5 điểm - Stack & Queue).
a) Cho Queue rỗng. Cho chuỗi thao tác:
Cho biết tình trạng Queue và giá trị trả về.
b) Viết hàm `String infixToPostfix(String exp)` chuyển biểu thức Trung tố có ngoặc sang Hậu tố bằng thuật toán Dijkstra 2-stack.
Câu 3 (1,5 điểm - Sắp xếp & Heap).
a) Cho Max Heap nhị phân hiện tại: `[-, 85, 75, 60, 40, 50, 30]`. Minh họa từng bước quá trình thêm khóa vào Heap.
b) Tiếp tục với Heap thu được ở câu a, minh họa từng bước xóa phần tử lớn nhất (`delMax`).
Câu 4 (1,5 điểm - Cây BST).
a) Cho chuỗi khóa . Vẽ cây BST thu được sau khi thêm lần lượt chuỗi khóa trên vào cây rỗng.
b) Viết hàm đệ quy `int sumKeys(Node root)` tính tổng giá trị tất cả các khóa số nguyên trong cây BST.
Câu 5 (1,0 điểm - Bài toán ứng dụng).
Thiết kế cấu trúc dữ liệu `UniStack` chứa các chuỗi String hỗ trợ `push(x)` và `pop()` như Stack thông thường nhưng đảm bảo không chứa phần tử trùng lặp. Yêu cầu: `push` và `pop` tốn thời gian hoặc , bộ nhớ .
--------- HẾT ĐỀ SỐ 4 ---------
ĐÁP ÁN VÀ LỜI GIẢI CHI TIẾT ĐỀ SỐ 4
1. Đáp án trắc nghiệm Đề số 4
Câu | Đáp án | Giải thích tóm tắt |
|---|---|---|
1 | B | Tính liên thông có tính phản xạ, đối xứng và bắc cầu nên lập thành quan hệ tương đương. |
2 | A | Thứ tự ưu tiên ngoặc: , nhân với , chia cho . |
3 | B | Selection Sort luôn thực hiện đúng phép đổi chỗ trong mọi trường hợp, ít truy nhập mảng hơn Insertion/Bubble khi mảng ngược. |
4 | A | 3-way partitioning chia mảng thành các đoạn , , để xử lý hiệu quả các khóa trùng lặp. |
5 | B | Tính chất Min Heap: Nút cha luôn nhỏ hơn hoặc bằng nút con, do đó gốc (chỉ số 1) luôn là phần tử nhỏ nhất. |
6 | B | Nút gốc là nút duy nhất không có con trỏ trỏ tới từ nút khác (Parent is null). |
7 | C | Khi mảng đã sắp xếp, chọn chốt ở đầu mảng khiến cây đệ quy bị suy biến thành độ sâu , thời gian . |
8 | A | Mảng tự gấp đôi kích thước có chi phí bồi hoàn (amortized cost) cho thao tác `push` là . |
9 | C | Thời gian chạy của Insertion Sort xấp xỉ với là số cặp nghịch đảo. Khi , thời gian chạy là . |
10 | C | Trong mảng đánh số từ 1, nút cha của nút nằm tại chỉ số . |
11 | C | Mỗi nút có 2 con trỏ, nút có con trỏ. Đúng nút có cha (được trỏ tới), nên số con trỏ null là . |
12 | B | Mảng sắp xếp ngược hoàn toàn có số cặp nghịch đảo tối đa là . |
13 | A | `ceiling(key)` trả về khóa nhỏ nhất trong tập khóa lớn hơn hoặc bằng `key`. |
14 | B | Bag là tập hợp chỉ cho phép thêm (`add`) và duyệt (`iterator`), không hỗ trợ xóa phần tử chỉ định. |
15 | B | Cây đệ quy của Quicksort có độ sâu trung bình là , tiêu tốn bộ nhớ Stack. |
2. Lời giải tự luận Đề số 4
Câu 1 (1,5 điểm)
a) Số lần gọi `compare`:
- Trường hợp tốt nhất: lần (khi `a[mid] == key` ngay lần thử đầu tiên tại điểm giữa).
- Trường hợp tồi nhất: lần (khi không tìm thấy khóa hoặc khóa ở tận nhánh con chia đôi cuối cùng).
b) Ý nghĩa công thức `mid = lo + (hi - lo) / 2`:
- Về mặt đại số, .
- Trong ngôn ngữ lập trình (Java/C++), nếu và lớn, tổng có thể vượt quá giá trị cực đại của số nguyên 32-bit có dấu (), dẫn đến hiện tượng tràn số (integer overflow) làm kết quả bị âm.
- Biểu thức thực hiện phép trừ trước () nên không bao giờ xảy ra tràn số.
Câu 2 (1,5 điểm)
a) Trạng thái Queue qua từng thao tác (quy ước bên phải là đầu ra):
-
-
-
- Trả về giá trị , trạng thái
- Trả về `false`, trạng thái
b) Hàm `infixToPostfix` bằng Java:
public static String infixToPostfix(String exp) {
Stack<String> ops = new Stack<>();
StringBuilder postfix = new StringBuilder();
String[] tokens = exp.split("\\s+");
for (String token : tokens) {
if (token.equals("(")) {
// Bỏ qua dấu mở ngoặc
} else if (token.equals("+") || token.equals("-") ||
token.equals("*") || token.equals("/")) {
ops.push(token);
} else if (token.equals(")")) {
postfix.append(ops.pop()).append(" ");
} else {
postfix.append(token).append(" ");
}
}
return postfix.toString().trim();
}
Câu 3 (1,5 điểm)
a) Thêm khóa vào Max Heap `[-, 85, 75, 60, 40, 50, 30]`:
- Bước 1: Thêm vào vị trí cuối mảng (chỉ số 7): `[-, 85, 75, 60, 40, 50, 30, 68]`.
- Bước 2: Gọi `swim(7)`: Nút cha tại chỉ số có giá trị . Do , hoán đổi và .
Mảng: `[-, 85, 75, 68, 40, 50, 30, 60]`.
- Bước 3: Gọi `swim(3)`: Nút cha tại chỉ số có giá trị . Do , điều kiện Max Heap thỏa mãn. Dừng.
Kết quả: `[-, 85, 75, 68, 40, 50, 30, 60]`.
b) Xóa phần tử lớn nhất (`delMax`) từ Heap trên:
- Bước 1: Đổi chỗ gốc ( tại index 1) với phần tử cuối ( tại index 7), giảm kích thước mảng còn . Xóa .
Mảng tạm: `[-, 60, 75, 68, 40, 50, 30]`.
- Bước 2: Gọi `sink(1)`: Gốc có con trái là (index 2) và con phải là (index 3). Con lớn nhất là . Do , hoán đổi và .
Mảng: `[-, 75, 60, 68, 40, 50, 30]`.
- Bước 3: Xét nút tại index 2: có con trái là (index 4) và con phải là (index 5). Con lớn nhất là . Do , điều kiện Max Heap thỏa mãn. Dừng.
Kết quả: `[-, 75, 60, 68, 40, 50, 30]`.
Câu 4 (1,5 điểm)
a) Cây BST sau khi thêm chuỗi khóa `80, 20, 40, 30, 10, 100, 70, 90, 50`:
80
/ \
20 100
/ \ /
10 40 90
/ \
30 70
/
50
- là gốc.
- rẽ trái.
- rẽ phải của .
- rẽ trái của .
- rẽ trái của .
- rẽ phải của .
- rẽ phải của .
- rẽ trái của .
- rẽ trái của .
b) Hàm đệ quy tính tổng các khóa:
int sumKeys(Node root) {
if (root == null) return 0;
return root.key + sumKeys(root.left) + sumKeys(root.right);
}
Câu 5 (1,0 điểm)
Thiết kế cấu trúc `UniStack`:
- Cấu trúc kết hợp:
- Danh sách liên kết kép (Doubly Linked List - DLL): Nút chứa giá trị chuỗi và 2 con trỏ `prev`, `next`. Con trỏ `head` trỏ tới đỉnh Stack.
- Bảng băm (`HashMap<String, Node>`): Lưu ánh xạ từ chuỗi giá trị tới nút chứa nó trong DLL.
- Thao tác `push(x)`:
- Kiểm tra `map.containsKey(x)`. Nếu đã tồn tại, lấy nút ra và ngắt liên kết khỏi DLL trong .
- Tạo nút mới chứa `x`, chèn lên đầu DLL (`head`) trong .
- Cập nhật địa chỉ nút vào `map.put(x, newNode)`.
- Thao tác `pop()`:
- Lấy giá trị chuỗi tại `head.val`.
- Xóa nút `head` khỏi DLL và xóa khóa tương ứng trong `map`.
- Trả về giá trị đã lấy.
- Độ phức tạp: Thời gian cho mỗi thao tác, bộ nhớ phụ đáp ứng hoàn toàn yêu cầu đề bài.
KHOA CÔNG NGHỆ THÔNG TIN
BỘ MÔN KHOA HỌC MÁY TÍNH
Đề ôn tập số 05
ĐỀ ÔN TẬP GIỮA KỲ HỌC PHẦN DSA
Môn: Cấu trúc dữ liệu và Giải thuật
Thời gian làm bài: 60 phút (không kể thời gian phát đề)
PHẦN I. TRẮC NGHIỆM (3,0 điểm)
Thí sinh chọn một phương án đúng duy nhất cho mỗi câu hỏi sau:
Câu 1. Giả sử thực hiện thao tác union/find trên cấu trúc dữ liệu Quick-Union có trọng số (Weighted Quick-Union) với đối tượng. Thời gian chạy tồi nhất tỉ lệ với:
A.
B. (hoặc )
C.
D.
Câu 2. Cấu trúc dữ liệu Hàng đợi (Queue) thường được ứng dụng trong thuật toán nào sau đây?
A. Thuật toán Duyệt theo chiều rộng (BFS)
B. Thuật toán Duyệt theo chiều sâu (DFS)
C. Đánh giá biểu thức bằng Stack
D. Sắp xếp Heapsort
Câu 3. Thuật toán sắp xếp nào sau đây có thời gian chạy trường hợp tốt nhất (Best case) là ?
A. Selection Sort
B. Insertion Sort
C. Mergesort Top-down
D. Quicksort tiêu chuẩn
Câu 4. Giáo viên cần sắp xếp danh sách sinh viên: đầu tiên theo Nhóm thực hành, sau đó trong từng nhóm sắp xếp theo Tên ABC. Hỏi thuật toán sắp xếp được chọn bắt buộc phải có đặc tính gì nếu ta sắp xếp theo Tên trước rồi mới sắp xếp theo Nhóm thực hành?
A. Tính tại chỗ (In-place)
B. Tính ổn định (Stable)
C. Chạy trong thời gian
D. Đệ quy
Câu 5. Mức (Level) hay Độ sâu (Depth) của nút gốc trong cây nhị phân theo quy ước thông thường bằng bao nhiêu?
A.
B.
C.
D.
Câu 6. Kết quả duyệt cây BST theo thứ tự Postorder (Hậu tự) luôn thăm nút gốc ở vị trí nào?
A. Đầu tiên
B. Chính giữa
C. Cuối cùng
D. Tùy thuộc vào chiều cao cây
Câu 7. Phương pháp sắp xếp Trộn Bottom-up Mergesort thực hiện sắp xếp mảng mà KHÔNG sử dụng:
A. Mảng phụ `aux`
B. Phép so sánh
C. Đệ quy (sử dụng vòng lặp duyệt kích thước mảng con )
D. Phép gán
Câu 8. Cho mảng biểu diễn Min Heap: `[-, 5, 12, 10, 15, 20, 25]`. Giá trị của nút con phải của nút gốc là:
A.
B.
C.
D.
Câu 9. Trong thuật toán Quicksort, bước Phân chia mảng (Partitioning) tiêu chuẩn mất thời gian:
A.
B.
C.
D.
Câu 10. Trong cài đặt Stack bằng Danh sách liên kết đơn, thao tác `push(x)` và `pop()` thực hiện ở đầu danh sách có độ phức tạp thời gian là:
A.
B.
C.
D.
Câu 11. Cho hai hàm và . Phát biểu nào sau đây đúng về cấp tăng?
A. tăng nhanh hơn
B. tăng nhanh hơn
C. Hai hàm có cùng cấp tăng
D. Không so sánh được
Câu 12. Cấu trúc Priority Queue cài đặt bằng Mảng đã sắp xếp tăng dần có độ phức tạp của thao tác `insert` và `delMax` lần lượt là:
A. và
B. và
C. và
D. và
Câu 13. Trong cây BST, thao tác `rank(key)` trả về giá trị gì?
A. Số lượng khóa trong cây nhỏ hơn `key`
B. Chiều sâu của `key`
C. Số lượng khóa trong cây lớn hơn `key`
D. Số con của nút chứa `key`
Câu 14. Trong thuật toán Dijkstra 2-stack để tính giá trị biểu thức số học, khi gặp dấu đóng ngoặc `)`, ta thực hiện thao tác gì?
A. Đẩy dấu `)` vào stack toán tử
B. Pop 1 toán tử từ stack toán tử, pop 2 giá trị từ stack giá trị, thực hiện phép tính rồi push kết quả trở lại stack giá trị
C. Bỏ qua dấu `)`
D. Xóa toàn bộ stack
Câu 15. Sự khác biệt cơ bản về nguyên lý giữa Selection Sort và Insertion Sort là gì?
A. Selection Sort tìm phần tử nhỏ nhất trong phần chưa sắp xếp để đưa về đúng vị trí; Insertion Sort chèn phần tử hiện tại vào vị trí đúng trong phần đã sắp xếp
B. Selection Sort có tính ổn định còn Insertion Sort thì không
C. Insertion Sort dùng bộ nhớ phụ còn Selection Sort dùng
D. Selection Sort chạy còn Insertion Sort chạy
PHẦN II. TỰ LUẬN (7,0 điểm)
Câu 1 (1,5 điểm - Phân tích thuật toán).
Cho hàm `mergeTwo` dưới đây:
void mergeTwo(int a[], int aux[], int N) {
int lo = 0, mid = N / 2, hi = N - 1;
for (int k = lo; k <= hi; k++) aux[k] = a[k];
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++];
else if (j > hi) a[k] = aux[i++];
else if (aux[j] < aux[i]) a[k] = aux[j++];
else a[k] = aux[i++];
}
}
a) Tính chính xác số lần truy nhập mảng (đọc/ghi trên `a` và `aux`) theo .
b) Cho biết độ phức tạp thời gian theo và Tilde () trong trường hợp tốt nhất và tồi nhất.
Câu 2 (1,5 điểm - Stack & Queue).
a) Cho Queue (đầu lấy phần tử là ) và Stack rỗng. Viết đoạn code đảo ngược thứ tự các phần tử trong .
b) Viết hàm `boolean areEqualStacks(Stack<Integer> s1, Stack<Integer> s2)` kiểm tra xem 2 Stack có giống hệt nhau về nội dung và thứ tự không mà không làm thay đổi trạng thái ban đầu của .
Câu 3 (1,5 điểm - Sắp xếp & Heap).
a) Cho mảng . Minh họa bước Partition đầu tiên của Quicksort tiêu chuẩn (chốt là phần tử đầu tiên ).
b) Minh họa các bước sắp xếp mảng bằng Insertion Sort.
Câu 4 (1,5 điểm - Cây BST).
a) Thêm các khóa vào cây BST rỗng. Vẽ cây kết quả.
b) Viết hàm đệ quy `int countSingleChildNodes(Node root)` đếm số lượng nút trong cây BST chỉ có đúng 1 nút con.
Câu 5 (1,0 điểm - Bài toán ứng dụng).
Thiết kế cấu trúc dữ liệu `Tournament` lưu trữ thông tin đấu thủ: `insert(name, score)`, `getScore(name)`, `getLead()`. Yêu cầu cả 3 hàm chạy thời gian , bộ nhớ .
--------- HẾT ĐỀ SỐ 5 ---------











