您的位置:首页 > 其它

排序 - 归并排序

2015-07-06 10:27 344 查看
归并:将两个或两个以上的有序序列合并成一个新的有序序列,这种归并方法称为2路归并;

将3个有序序列归并为一个新的有序序列,称为3路归并;

将多个有序序列归并为一个新的有序序列,称为多路归并。



合并过程:

1、设置i,j 和 p 三个指针,其初值分别指向这三个记录区的起始位置;

2、合并时依次比较R[i]和R[j]的关键字,取关键字较小的记录复制到R1[p]中;

3、然后将被复制记录的指针 i 或 j 加1,以及指向复制位置的指针 p 加1;

4、重复这一过程直至两个输入的子文件有一个已全部复制完毕(不妨称其为空),此时将另一非空的子文件中剩余记录一次复制到R1中即可。

时间复杂度O(nlogn)。



代码:

#include <iostream>
#include <cstdio>
#include <ctime>
#include <iomanip>
using namespace std;

int arr[10000];

inline void mySwap(int &a, int &b)
{
int t = a;
a = b;
b = t;
}

void merge(int A[], int tmpA[], int leftPos, int rightPos, int rightEnd)
{
int leftEnd = rightPos - 1;
int tmpPos = leftPos;
int num = rightEnd - leftPos + 1;

// 从大到小放到临时矩阵中
while (leftPos <= leftEnd && rightPos <= rightEnd) {
if (A[leftPos] <= A[rightPos]) {
tmpA[tmpPos++] = A[leftPos++];
}
else {
tmpA[tmpPos++] = A[rightPos++];
}
}

// 剩下的
while (leftPos <= leftEnd) {
tmpA[tmpPos++] = A[leftPos++];
}
while (rightPos <= rightEnd) {
tmpA[tmpPos++] = A[rightPos++];
}

for (int i = 0; i < num; i++, rightEnd--) {
A[rightEnd] = tmpA[rightEnd];
}
}

void MSort(int A[], int tmpA[], int L, int R)
{
int mid;
if (L < R) {
mid = (L + R) / 2;
MSort(A, tmpA, L, mid);
MSort(A, tmpA, mid + 1, R);
merge(A, tmpA, L, mid + 1, R);
}
}

void mergeSort(int A[], int len)
{
int *tmpA = new int[len];
if (tmpA != NULL) {
MSort(A, tmpA, 0, len - 1);
delete [] tmpA;
}
else {
cout << "No space for tmp array!!!\n";
}
}

void printArray(int *a, int len)
{
for (int i = 0; i < len; i++) {
if (i != 0 && i % 10 == 0) {
cout << endl;
}
cout << setw(3) << a[i] << ' ';
}
cout << endl;
}

int main()
{
srand(time(0));
cout << "Please input length of array: ";
int len;
cin >> len;
for (int i = 0; i < len; i++) {
arr[i] = rand() % 100;
}
cout << "Before sorting:\n";
printArray(arr, len);
mergeSort(arr, len);
cout << "After sorting:\n";
printArray(arr, len);

return 0;
}

/*
Please input length of array: 20
Before sorting:
55  89  51  31  24  86  41  82  83  58
36  41  84  88  99   1  38  96  31  27
After sorting:
1  24  27  31  31  36  38  41  41  51
55  58  82  83  84  86  88  89  96  99
*/


虽然归并排序的运行时间是O(nlogn),但是它很难用于主存排序,主要问题在于合并两个排序的表需要线性附加内存,在整个算法中还需要花费将数据拷贝靠临时数组再拷贝回来这样一些附加的工作,其结果严重放慢了排序的速度。对于重要的内部排序应用而言,人们还是选择快速排序。而合并是大多少外部排序算法的基石。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: