You are on page 1of 4

Thuyết trình Merge sort + cấu trúc priority queue ( dùng heap )

I. Merge sort
- Định nghĩa : Merge sort là một thuật toán sắp xếp đệ quy, hoạt động bằng cách chia mảng thành
các phần nhỏ hơn, sắp xếp từng phần đó rồi kết hợp chúng lại để có một dãy đã được sắp xếp. Thuật
toán này được đặt tên là merge sort vì nó sử dụng việc kết hợp (merge) các dãy con được sắp xếp
thành một dãy lớn được sắp xếp.
- Quá trình merge sort được thực hiện theo các bước sau :
1.Chia mảng ban đầu thành các phần nhỏ hơn đến khi mỗi phần chỉ còn một phần tử.
2.Sắp xếp từng phần nhỏ đó.
3.Kết hợp các phần đã được sắp xếp để tạo ra một mảng đã được sắp xếp hoàn chỉnh.
Ví dụ minh họa :

Nếu nhìn kỹ hơn vào sơ đồ này, chúng ta có thể thấy:


+ Mảng ban đầu được lặp lại hành động chia cho tới khi kích thước các mảng sau chia là 1.
+ Khi kích thước các mảng con là 1, tiến trình gộp sẽ bắt đầu.
+ Thực hiện gộp lại các mảng này cho tới khi hoàn thành và chỉ còn một mảng đã sắp xếp.
- Phân tích độ phức tạp của merge sort :
+ Độ phức tạp thời gian : O(N log(N)), Merge Sort là một thuật toán đệ quy có độ
phức tạp thời gian có thể được biểu thị dưới dạng quan hệ lặp lại sau :
T(n) = 2T(n/20) + O(n)
Sau khi giải quan hệ lặp lại này bằng cách sử dụng định lý thợ (master’s theorem)
hoặc phương pháp đệ quy (recurrence tree), bạn sẽ nhận được nghiệm (solution) là
O(n log(n)). Do đó, độ phức tạp về thời gian ( time complexity ) của thuật toán
Merge Sort là O(n log(n)).
Độ phức tạp thời gian trong trường hợp tốt nhất của merge sort : O(n log(n)).
Độ phức tạp thời gian trong trường hợp trung bình của merge sort : O(n log(n)).
Độ phức tạp thời gian trong trường hợp trung bình của merge sort : O(n log(n)).
Độ phức tạp của bộ nhớ phụ ( auxiliary space complexity ) của thuật toán merge
sort là O(n) vì n bộ nhớ phụ được yêu cầu trong việc thực hiện merge sort.
- Triển khai thuật toán Merge Sort trong C++:
#include<iostream>
using namespace std;
// This function merges two subarrays of arr[]
// Left subarray : arr[leftIndex..middleIndex]
// Right subarray : array[middleIndex+1..rightIndex]
void merge(int arr[], int leftIndex, int middleIndex, int rightIndex)
{
int leftSubarraySize = middleIndex - leftIndex + 1;
int rightSubarraySize = rightIndex - middleIndex;
// create temporary arrays
int L[leftSubarraySize], R[rightSubarraySize];
// Copying data to temporary arrays L[] and R[]
for(int i=0; i < leftSubarraySize; i++)
L[i] = arr[leftIndex + i];
for(int j = 0; j < rightSubarraySize; j++)
R[j] = arr[middleIndex + 1 + j];
// Merge the temporary arrays back in to arr[leftIndex..rightIndex]
// Initial index of Left subarray
int i = 0;
// Initial index of Right subarray
int j = 0;
// Initial index of merged subarray
int k = leftIndex;
while( i < leftSubarraySize && j < rightSubarraySize )
{
if (L[i] <= R[j] )
{
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}
}
void mergesort(int arr[], int leftIndex, int rightIndex)
{
if(leftIndex >= rightIndex)
{
return ;
}
int middleIndex = leftIndex + ( rightIndex - leftIndex)/2;
mergesort(arr, leftIndex, middleIndex);
mergesort(arr, middleIndex+1, rightIndex);
merge(arr, leftIndex, middleIndex, rightIndex);
}
// Function to print the elements of the array;
void printArray (int arr[], int size)
{
for (int i=0; i < size; i++ )
{
cout << arr[i] << " ";
}
cout << endl;
}
int main () {
int arr[] = { 16, 12, 15, 13, 19, 17, 11 ,18 };
int size = sizeof(arr) / sizeof(arr[0]);
cout << "Unsorted array : " << endl;
printArray(arr, size);
mergesort(arr, 0, size - 1);
cout << " Sorted array : " << endl;
printArray(arr, size );
return 0;
}
- Các ứng dụng của merge sort :
+ Sắp xếp các tập dữ liệu lớn : Sắp xếp hợp nhất đặc biệt phù hợp để sắp xếp các tập dữ liệu lớn
do độ phức tạp về thời gian trong trường hợp xấu nhất được đảm bảo là O(n log n).
+ Sắp xếp bên ngoài : Sắp xếp hợp nhất thường được sử dụng trong sắp xếp bên ngoài, trong đó
dữ liệu cần sắp xếp quá lớn để vừa với bộ nhớ.
+ Sắp xếp tùy chỉnh : Sắp xếp hợp nhất có thể được điều chỉnh để xử lý các phân phối đầu vào
khác nhau, chẳng hạn như dữ liệu được sắp xếp một phần, gần như được sắp xếp hoặc chưa được
sắp xếp hoàn toàn.
+ Inversion count ( đếm đảo ngược ) : Số lần đảo ngược cho một mảng cho biết – mảng đó được
sắp xếp bao xa ( hoặc gần ) bao nhiêu. Nếu mảng đã được sắp xếp thì số lần đảo ngược là 0,
nhưng nếu mảng được sắp xếp theo thứ tự ngược lại thì số lần đảo ngược là tối đa.

You might also like