You are on page 1of 17

BÀI 4: THUẬT TOÁN SẮP XẾP VÀ CÀI ĐẶT

Câu 1. Thực hiện các yêu cầu sau đây:


Trình bày ý tưởng của thuật toán sắp xếp Quicksort
- Lập trình thuật toán Quicksort
Câu 2. Thực hiện các yêu cầu sau đây:
- Trình bày ý tưởng của thuật toán sắp xếp HeapSort
- Lập trình thuật toán Quicksort
Câu 3. Thực hiện các yêu câu sau đây:
Trình bày ý tưởng của thuật toán sắp xếp MergeSort
- Lập trình thuật toán Merge Sort
Câu 4. Thực hiện các yêu cầu sau đây:
- Trình bày ý tưởng của thuật toán sắp xếp chèn (InsertionSort)
- Lập trình thuật toán sắp xếp chèn
Câu 5. Thực hiện các yêu cầu sau đây:
Trình bày ý tưởng của thuật toán sắp xếp chọn (SelectionSort)
- Lập trình thuật toán sắp xếp chọn
Câu 6. Thực hiện các yêu cầu sau đây:
Trình bày ý tưởng của thuật toán sắp xếp nổi bọt (Bubble Sort)
- Lập trình thuật toán sắp xếp nổi bọt

Câu 1
Ý Tưởng của Thuật Toán Sắp Xếp Quicksort:
Thuật toán sắp xếp Quicksort là một thuật toán sắp xếp đệ quy dựa
trên chia để trị. Ý tưởng cơ bản của Quicksort là chọn một phần tử gọi
là "pivot" từ mảng và phân hoạch mảng thành hai phần, sao cho các
phần tử nằm bên trái pivot đều nhỏ hơn pivot và các phần tử bên phải
pivot đều lớn hơn pivot. Sau đó, áp dụng đệ quy để sắp xếp đồng thời
hai phần đã phân hoạch.

Thuật Toán Quicksort:

1. Chọn Pivot: Chọn một phần tử từ mảng làm pivot. Cách lựa chọn pivot
có thể là chọn phần tử ở giữa mảng hoặc sử dụng một chiến lược khác.
2. Phân Hoạch (Partition): Phân hoạch mảng thành hai phần sao cho các
phần tử nhỏ hơn pivot nằm bên trái và các phần tử lớn hơn pivot nằm
bên phải. Có nhiều cách thực hiện phân hoạch, một cách phổ biến là sử
dụng hai biến con trỏ lặp (i và j) để duyệt qua mảng từ đầu đến cuối và
hoán đổi các phần tử nếu chúng không đúng vị trí.
3. Đệ Quy: Áp dụng thuật toán Quicksort đệ quy cho cả hai phần đã phân
hoạch.
4. Kết Hợp Các Phần: Sau khi thực hiện đệ quy, các phần tử sẽ đã được
sắp xếp đúng thứ tự.

Lập Trình Thuật Toán Quicksort:

Dưới đây là một ví dụ cơ bản về lập trình thuật toán Quicksort bằng
ngôn ngữ C++:

#include <iostream>
#include <vector>
template <typename T>
int partition(std::vector<T>& arr, int low, int high) {
T pivot = arr[high];
int i = low - 1;
for (int j = low; j <= high - 1; j++) {
if (arr[j] < pivot) {
i++;
std::swap(arr[i], arr[j]);
}
}
std::swap(arr[i + 1], arr[high]);
return i + 1;
}

template <typename T>


void quicksort(std::vector<T>& arr, int low, int high) {
if (low < high) {
int pivotIndex = partition(arr, low, high);
quicksort(arr, low, pivotIndex - 1);
quicksort(arr, pivotIndex + 1, high);
}
}
int main() {
std::vector<int> arr = {12, 4, 5, 6, 7, 3, 1, 15};
int n = arr.size();
std::cout << "Original array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
quicksort(arr, 0, n - 1);
std::cout << "Sorted array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
Câu 2
Ý Tưởng của Thuật Toán Sắp Xếp HeapSort:

Thuật toán sắp xếp HeapSort là một thuật toán sắp xếp dựa trên cấu
trúc dữ liệu heap (đôi khi được gọi là "binary heap"). Ý tưởng cơ bản
của HeapSort bao gồm hai pha chính: xây dựng heap và triển khai heap.

1. Xây Dựng Heap (Build Heap): Mảng được coi là một cây nhị phân và
được chuyển đổi thành một heap. Quá trình này bắt đầu từ phần tử
cuối cùng của mảng và di chuyển lên đầu mảng. Đối với mỗi phần tử,
nếu nó lớn hơn phần tử cha của nó, chúng ta hoán đổi chúng và tiếp tục
kiểm tra và hoán đổi đến khi mảng thành heap.
2. Triển Khai Heap (Heapify): Sau khi xây dựng heap, phần tử lớn nhất
(phần tử ở đầu heap) được đưa ra khỏi heap và đặt vào cuối mảng. Sau
đó, heap được giảm kích thước đi một và quá trình heapify được áp
dụng để đảm bảo rằng phần tử lớn nhất trong heap mới lại là phần tử
đầu tiên. Quá trình này được lặp lại cho đến khi heap chỉ còn một phần
tử.
3. Kết quả là một mảng đã được sắp xếp tăng dần (hoặc giảm dần) sau cả
hai pha xây dựng heap và triển khai heap.

4. Lập Trình Thuật Toán HeapSort:


5. Dưới đây là một ví dụ lập trình thuật toán HeapSort bằng ngôn
ngữ C++:

#include <iostream>
#include <vector>
template <typename T>
void heapify(std::vector<T>& arr, int n, int i) {
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
std::swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}
template <typename T>
void heapSort(std::vector<T>& arr) {
int n = arr.size();
// Build heap
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// Perform heap sort
for (int i = n - 1; i > 0; i--) {
std::swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
int main() {
std::vector<int> arr = {12, 4, 5, 6, 7, 3, 1, 15};
int n = arr.size();
std::cout << "Original array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
heapSort(arr);
std::cout << "Sorted array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}

Câu 3
Ý Tưởng của Thuật Toán Sắp Xếp MergeSort:

Thuật toán sắp xếp MergeSort là một thuật toán sắp xếp đệ quy dựa
trên ý tưởng chia để trị. Thuật toán này chia mảng thành hai phần bằng
cách chọn phần tử giữa, sau đó đệ quy sắp xếp từng phần con. Cuối
cùng, các phần tử được "hợp nhất" (merge) lại với nhau để tạo ra một
mảng đã được sắp xếp.

Bước Cơ Bản của Thuật Toán:

1. Chia Mảng: Chia mảng ban đầu thành hai phần bằng cách chọn phần tử
giữa.
2. Sắp Xếp Đệ Quy: Áp dụng thuật toán MergeSort đệ quy cho cả hai phần
con được tạo ra từ bước trước.
3. Hợp Nhất (Merge): Hợp nhất hai phần đã được sắp xếp để tạo ra một
mảng đã được sắp xếp. Bước hợp nhất này là bước quan trọng nhất của
thuật toán.

Lập Trình Thuật Toán MergeSort:

Dưới đây là một ví dụ lập trình thuật toán MergeSort bằng ngôn ngữ C+
+:

#include <iostream>
#include <vector>
template <typename T>
void merge(std::vector<T>& arr, int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;
// Tạo mảng tạm để lưu các phần tử con
std::vector<T> leftArr(n1);
std::vector<T> rightArr(n2);
// Copy dữ liệu vào mảng tạm
for (int i = 0; i < n1; i++) {
leftArr[i] = arr[left + i];
}
for (int j = 0; j < n2; j++) {
rightArr[j] = arr[mid + 1 + j];
}
// Hợp nhất các mảng tạm lại mảng gốc
int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (leftArr[i] <= rightArr[j]) {
arr[k] = leftArr[i];
i++;
} else {
arr[k] = rightArr[j];
j++;
}
k++;
}
// Sao chép các phần tử còn lại của leftArr và rightArr (nếu có)
while (i < n1) {
arr[k] = leftArr[i];
i++;
k++;
}
while (j < n2) {
arr[k] = rightArr[j];
j++;
k++;
}
}
template <typename T>
void mergeSort(std::vector<T>& arr, int left, int right) {
if (left < right) {
int mid = left + (right - left) / 2;
// Sắp xếp đệ quy cho hai nửa
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// Hợp nhất hai nửa đã sắp xếp
merge(arr, left, mid, right);
}
}
int main() {
std::vector<int> arr = {12, 4, 5, 6, 7, 3, 1, 15};
int n = arr.size();
std::cout << "Original array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
mergeSort(arr, 0, n - 1);
std::cout << "Sorted array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}

Câu 4
Ý Tưởng của Thuật Toán Sắp Xếp Chèn (Insertion Sort):

Thuật toán sắp xếp chèn là một thuật toán đơn giản dựa trên ý tưởng
"chèn" phần tử vào đúng vị trí của nó trong một dãy đã sắp xếp. Thuật
toán này thực hiện việc sắp xếp mảng một cách tăng dần bằng cách chia
nó thành hai phần: một phần đã sắp xếp và một phần chưa sắp xếp.
Thuật toán này duyệt qua từng phần tử chưa sắp xếp và chèn nó vào
đúng vị trí trong phần đã sắp xếp.

Bước Cơ Bản của Thuật Toán:

1. Bắt Đầu từ Phần Tử Đầu Tiên: Giả sử phần đầu của mảng đã sắp xếp
chỉ có một phần tử (chính là phần tử đầu tiên).
2. Chèn Phần Tử Chưa Sắp Xếp: Duyệt qua các phần tử chưa sắp xếp một
cách lần lượt. Với mỗi phần tử, so sánh nó với các phần tử trong phần
đã sắp xếp và chèn nó vào đúng vị trí.
3. Lặp Lại Quá Trình: Lặp lại quá trình trên cho đến khi toàn bộ mảng
được sắp xếp.

Lập Trình Thuật Toán Sắp Xếp Chèn:


Dưới đây là một ví dụ lập trình thuật toán sắp xếp chèn bằng ngôn ngữ
C++:

#include <iostream>
#include <vector>
template <typename T>
void insertionSort(std::vector<T>& arr) {
int n = arr.size();
for (int i = 1; i < n; i++) {
T key = arr[i];
int j = i - 1;
// Di chuyển các phần tử lớn hơn key về phía trước
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
// Chèn key vào đúng vị trí
arr[j + 1] = key;
}
}
int main() {
std::vector<int> arr = {12, 4, 5, 6, 7, 3, 1, 15};
int n = arr.size();
std::cout << "Original array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
insertionSort(arr);
std::cout << "Sorted array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}

Câu 5
Ý Tưởng của Thuật Toán Sắp Xếp Chọn (Selection Sort):

Thuật toán sắp xếp chọn là một thuật toán đơn giản dựa trên ý tưởng
chọn phần tử nhỏ nhất (hoặc lớn nhất) từ phần chưa sắp xếp và đặt nó
vào đầu (hoặc cuối) của mảng đã sắp xếp. Thuật toán này thực hiện việc
sắp xếp mảng một cách tăng dần bằng cách tìm kiếm phần tử nhỏ nhất
từ phần chưa sắp xếp và đặt nó vào đầu mảng đã sắp xếp. Quá trình
này được lặp lại cho đến khi toàn bộ mảng được sắp xếp.

Bước Cơ Bản của Thuật Toán:


1. Bắt Đầu từ Phần Tử Đầu Tiên: Giả sử phần đầu của mảng đã sắp xếp là
rỗng.
2. Tìm Phần Tử Nhỏ Nhất: Tìm phần tử nhỏ nhất từ phần chưa sắp xếp.
3. Chuyển Phần Tử Đã Chọn: Di chuyển phần tử nhỏ nhất vào đầu (hoặc
cuối) của mảng đã sắp xếp.
4. Lặp Lại Quá Trình: Lặp lại quá trình trên cho đến khi toàn bộ mảng
được sắp xếp.

Lập Trình Thuật Toán Sắp Xếp Chọn:

Dưới đây là một ví dụ lập trình thuật toán sắp xếp chọn bằng ngôn ngữ
C++:

#include <iostream>
#include <vector>
template <typename T>
void selectionSort(std::vector<T>& arr) {
int n = arr.size();
for (int i = 0; i < n - 1; i++) {
// Tìm phần tử nhỏ nhất từ phần chưa sắp xếp
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// Hoán đổi phần tử nhỏ nhất với phần tử ở vị trí i
std::swap(arr[i], arr[minIndex]);
}
}
int main() {
std::vector<int> arr = {12, 4, 5, 6, 7, 3, 1, 15};
int n = arr.size();
std::cout << "Original array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
selectionSort(arr);
std::cout << "Sorted array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}

Câu 6

Ý Tưởng của Thuật Toán Sắp Xếp Nổi Bọt (Bubble Sort):
Thuật toán sắp xếp nổi bọt là một thuật toán đơn giản dựa trên ý tưởng
so sánh và hoán đổi các phần tử liên tiếp nếu chúng không ở đúng thứ
tự. Thuật toán này lặp lại quá trình này cho đến khi không còn phần tử
nào cần hoán đổi, tức là mảng đã được sắp xếp. Mỗi lần lặp đều đưa
phần tử lớn nhất (hoặc nhỏ nhất) về cuối mảng.

Bước Cơ Bản của Thuật Toán:

1. Lặp Qua Tất Cả Các Phần Tử: Bắt đầu từ đầu mảng, lặp qua tất cả các
phần tử.
2. So Sánh và Hoán Đổi: So sánh phần tử hiện tại với phần tử kế tiếp. Nếu
chúng không ở đúng thứ tự, hoán đổi chúng.
3. Lặp Lại Quá Trình: Lặp lại quá trình trên cho đến khi không còn phần tử
nào cần hoán đổi.
4. Lặp Lại Từ Đầu: Lặp lại toàn bộ quá trình cho đến khi mảng được sắp
xếp.

Lập Trình Thuật Toán Sắp Xếp Nổi Bọt:

Dưới đây là một ví dụ lập trình thuật toán sắp xếp nổi bọt bằng ngôn
ngữ C++:

#include <iostream>
#include <vector>
template <typename T>
void bubbleSort(std::vector<T>& arr) {
int n = arr.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
// So sánh và hoán đổi nếu cần
if (arr[j] > arr[j + 1]) {
std::swap(arr[j], arr[j + 1]);
}
}
}
}
int main() {
std::vector<int> arr = {12, 4, 5, 6, 7, 3, 1, 15};
int n = arr.size();
std::cout << "Original array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
bubbleSort(arr);
std::cout << "Sorted array: ";
for (const auto& elem : arr) {
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}

You might also like