归并排序(Merge Sort)
相关概念
- 任何情况下归并排序都是稳定的,并且时间复杂度为O(NlogN)
- 递归实现的思想采用分而治之的思想
- 归并排序一般用于外排序
- 小知识:在内存中进行的排序称为内部排序,而在许多实际应用中,经常需要对大文件进行排序,因为文件中的记录很多,信息量庞大,无法将整个文件拷贝进内存进行排序。因此,需要将带排序的记录存储在外存上,排序时再把数据一部分一部分的调入内存进行排序,在排序中需要多次进行内外存的交互,对外存文件中的记录进行排序后的结果仍然被放到原有文件中。这种排序方法就称外部排序。
实现描述
- 递归方法
首先实现有序子列的归并
template<typename T>
void Merge(vector<T>& vec, vector<T>& tmp, int left, int right, int rightEnd) {
int leftEnd = right - 1, pos = left, numTotal = rightEnd - left + 1;
while (left <= leftEnd && right <= rightEnd) {
if (vec[left] > vec[right])
tmp[pos++] = vec[right++];
else
tmp[pos++] = vec[left++];
}
while (left <= leftEnd)
tmp[pos++] = vec[left++];
while (right <= rightEnd)
tmp[pos++] = vec[right++];
for (int i = 0; i < numTotal; i++, rightEnd--) {
vec[rightEnd] = tmp[rightEnd];
}
}
接着采用分而治之的方式实现递归
template<typename T>
void MSort(vector<T>& vec, vector<T>& tmp, int left, int rightEnd) {
int center;
if (left < rightEnd) {
center = (left + rightEnd) >> 1;
MSort(vec, tmp, left, center);
MSort(vec, tmp, center + 1, rightEnd);
Merge(vec, tmp, left, center + 1, rightEnd);
}
}
template<typename T> // 接口
void MergeSort(vector<T>& vec) {
const int N = vec.size();
vector<T> tmp(N, 0);
MSort<T>(vec, tmp, 0, N - 1);
}
- 非递归方式
这里将Merge最后的赋值操作注释,因为在上层会进行交换
template<typename T>
void Merge(vector<T>& vec, vector<T>& tmp, int left, int right, int rightEnd) {
int leftEnd = right - 1, pos = left, numTotal = rightEnd - left + 1;
while (left <= leftEnd && right <= rightEnd) {
if (vec[left] > vec[right])
tmp[pos++] = vec[right++];
else
tmp[pos++] = vec[left++];
}
while (left <= leftEnd)
tmp[pos++] = vec[left++];
while (right <= rightEnd)
tmp[pos++] = vec[right++];
//for (int i = 0; i < numTotal; i++, rightEnd--) {
// vec[rightEnd] = tmp[rightEnd];
//}
}
template<typename T>
void MergePass(vector<T>& vec, vector<T>& tmp, int length) {
const int N = vec.size();
for (int i = 0; i < N - 2 * length; i += 2 * length) {
Merge(vec, tmp, i, i + length, i + 2 * length - 1);
}
if (i + length < N)
Merge(vec, tmp, i, i + length, N - 1);
else
for (int j = i; j < N; j++) tmp[j] = vec[j];
}
template<typename T>
void MergeSort(vector<T>& vec) {
const int N = vec.size();
int length = 1;
vector<T> tmp(vec.size(), 0);
while (length < N) {
MergePass(vec, tmp, length);
length *= 2;
MergePass(tmp, vec, length);
length *= 2;
}
}