您的位置:首页 > 其它

排序算法(五)--归并排序

2016-10-13 19:27 183 查看
归并排序

归并排序是一种借助归并进行排序的方法,归并的含义是将两个或两个以上的有序序列归并成一个有序序列的过程。

归并排序的主要思想是:将若干个有序序列逐步归并,最终成为一个有序序列.

二路归并排序是归并排序中最简单的排序方法,其基本思想是:将若干个有序序列进行两两归并,直至所有有序序列都在一个序列中为止。

假设待排序序列中有n个记录,则可将整个序列看成是长度为1的n个有序序列.其中一次归并的算法如下:

一次归并算法Merge

void Merge(int r[], int r1[], int s, int m, int t)
{
int i = s;
int j = m+1;
int k = s;
while (i<=m && j<=t)
{
if (r[i] > r[j])
{
r1[s++] = r[j++];
}else
{
r1[s++] = r[i++];
}
}
if (i <= m)
{
for (i; i<=m; i++)
{
r1[s++] = r[i];
}
}
if (j <= t)
{
for (j; j<=t; j++)
{
r1[s++] = r[j];
}
}
}如何确定一趟归并的结束?在一趟归并中,除最后一个有序序列外,其他有序序列长度相同,用h表示.现在是把若干个长度

为h的有序序列和最后一个长度可能小于h序列两两归并,将结果存放到r1[0]~r1[n-1]中.

初始时i=0,显然归并的步长为2h.

若此时有i+2h<=n,则可以进行下一次归并.i<=n-2h

若此时有i<n-h,则仍有两个有序序列,一个长度为h,一个长度小于h.完成一次并归.

若有i>=n-h,则表明只剩下一个有序序列,则将其放到相应位置.
// 一趟归并算法MergePass
// r[]带排数组,r1[]存放归并后的数组,n数组长度,归并步长
void MergePass(int r[], int r1[], int n, int h)
{
int i = 0;
while (i<=n-2*h) // 可以保证两个h长度的数组归并
{
Merge(r, r1, i, i+h-1, i+2*h-1);
i += 2*h;
}
// 如果仍有两个有序序列
if (i<n-h)
{
Merge(r, r1, i, i+h-1, n-1);
}else // 否则直接放入数组
{
for (int k = i; k<n; k++)
{
r1[k] = r[k];
}
}
}
// 如何确定归并结束?
// 初始步长为1,结束时有序序列长度为n.可以用步长控制归并结束.
void MergeSort(int r[], int r1[], int n)
{
int h = 1;
int k = 0;
while (h<n)
{
MergePass(r, r1, n, h);
k++;
h = 2*h;
MergePass(r1, r, n, h);
h = 2*h;
k++;
}
if (k%2 != 0) // 利用归并次数奇偶判断排序好的在哪个数组里,并移回r[]
{
for (int i = 0; i<n; i++)
{
r[i] = r1[i];
}
}
}
一趟归并算法需要n/2h次归并,并把结果存放到r1[0]~r1[n-1]中,需要耗费O(n)的时间.这个算法需要进行log2N趟.所以算法的复杂度为O(nlog2n).这是归并排序算法最好,最坏,平均的时间性能.

二路归并排序在归并过程中需要与原始记录序列相同数量的存储空间,以便存放归并结构,因此其空间复杂度为O(n)

二路归并排序是一种稳定的排序方法.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息