您的位置:首页 > 其它

算法导论 归并排序解决逆序数

2011-07-06 01:24 253 查看
算法导论上对归并排序的算法描述如下

基本思想是将序列分成两部分 L R,然后合并,L R 是有序的
算法的合并过程:
Pseudocode:
MERGE(A, p, q, r )
n1 ← q − p + 1
n2 ←r − q
create arrays L[1 . . n1 + 1] and R[1 . . n2 + 1]
for i ← 1 to n1
do L[i ] ← A[p + i − 1]
for j ← 1 to n2
do R[ j ] ← A[q + j ]
L[n1 + 1]←∞
R[n2 + 1]←∞
i ← 1
j ← 1
for k ← p to r
do if L[i ] ≤ R[ j ]
then A[k] ← L[i ]
i ←i + 1
else A[k] ← R[ j ]
j ← j + 1
归并排序:

MERGE-SORT(A, p, r )
if p < r  Check for base case
then q ←	(p + r)/2
 Divide
MERGE-SORT(A, p, q) // Conquer
MERGE-SORT(A, q + 1, r ) // Conquer
MERGE(A, p, q, r )  //combine
c 语言的实现过程 数组下标从1(算法导论上的描述数组下标均从1开始)开始,0位置为0

#include"stdio.h"
#define Type int
#define MAX 1000
#define false 0
#define true 1
//0--1--2--3--4--5--6--7--8--9--10--11--12--13--14--15--16--17--18--19
int a1[20] = {0, 4, 6, 9, 0, 3, 4, 8, 16,2,  4, 5,   7,  1,  2, 3,   6,  20, 31, 9 };
void merge(int a[],int p,int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q;
int L[n1 + 2];
int R[n2 + 2];
L[0] = 0;
R[0] = 0;
int i,j,k;
for(i = 1; i <= n1; i++)
{
L[i] = a[i+p-1];
}
for(j = 1; j <= n2;j++)
{
R[j] = a[q+j];
}
L[n1 + 1] = MAX;
R[n2 + 1] = MAX;
for(i = 0;i<n1+2;i++)
{
printf("L[%d]:%d--",i,L[i]);
}
for(j = 0; j < n2+2;j++)
{
printf("R[%d]:%d--",j,R[j]);
}
printf("\n");
i = 1;
j = 1;
for(k = p; k <= r;k++)
{
if(L[i] <= R[j])
{
a[k] = L[i];
i++;
}
else
{
a[k] = R[j];
j++;
}
printf("a[%d]:%d\n",k,a[k]);
}
}
int merge_sort(int *a,int p,int r)
{
int q;
if(p < r)
{
q = (p+r)/2;
merge_sort(a,p,q);
merge_sort(a,q+1,r);
merge(a,p,q,r);
}
else return 0;

}
void main()
{
int i;
printf("\n");
for(i = 0; i < 19; i++)printf("%d:%d,",i,a1[i]);
printf("\n");
merge(a1,9,12,16);
for(i = 0; i < 19; i++)printf("%d:%d,",i,a1[i]);

}



归并排序的应用: 计算逆序数

int a2[6] = {0,5,3,2,1,7};
int merge_inversions(int a[],int p,int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q;
int inversions,counted;
int L[n1 + 2];
int R[n2 + 2];
L[0] = 0;
R[0] = 0;
int i,j,k;
for(i = 1; i <= n1; i++)
{
L[i] = a[i+p-1];
}
for(j = 1; j <= n2;j++)
{
R[j] = a[q+j];
}
L[n1 + 1] = MAX;
R[n2 + 1] = MAX;
i = 1;
j = 1;
inversions = 0;
counted = false;
for(k = p; k <= r;k++)
{
if(counted == false && R[j] < L[i])
{
inversions = inversions + n1 - i + 1;
counted = true;
}

if(L[i] <= R[j])
{
a[k] = L[i];
i++;
}
else
{
a[k] = R[j];
j++;
counted = false;
}
//printf("a[%d]:%d\n",k,a[k]);
}
return inversions;
}
计算逆序数的个数




int count_inversions(int *a,int p,int r)
{
int inversions = 0;
int q;
if(p < r)
{
q = (p+r)/2;
inversions = inversions + count_inversions(a,p,q);
inversions = inversions + count_inversions(a,q+1,r);
inversions = inversions + merge_inversions(a,p,q,r);
}
return inversions;
}

void main()
{
int m = count_inversions(a2,1,5);
printf("inversions:%d",m);
}




归并排序的另一种写法,用一个temp数组存储归并的结果,最后将temp里的值赋给a数组

#include <iostream>
using namespace std;
void merge(int a[],int left,int mid,int right,int temp[])
{
int l_n = left;
int l_end = mid;
int r_n = mid+1;
int r_end = right;
int k = 0;
while (l_n <= l_end && r_n <= r_end)
{
if (a[l_n] <= a[r_n])
{
temp[k++] = a[l_n++];
}
else
{
temp[k++] = a[r_n++];
}
}

while(l_n <= l_end)temp[k++] = a[l_n++];
while(r_n <= r_end)temp[k++] = a[r_n++];
for (int i = 0; i < k; i++)
{
a[left+i] = temp[i];
cout<<"["<<left+i<<"]:"<<a[left+i];
}
cout<<endl;
}
void mergesort(int a[],int l,int r)
{
if(l < r){
int mid = (l + r)/2;
mergesort(a,l,mid);
mergesort(a,mid+1,r);
int *temp = new int[r-l+1];
merge(a,l,mid,r,temp);
}
else return;
}

int a1[20] = {0, 4, 10, 9, 32, 3, 14, 8, 16,2,  19, 5,   7,  1,  37, 17,   6,  20, 31, 9 };
int main()
{
mergesort(a1,0,19);
for (int i = 0; i < 20; i++)
{
cout<<"-"<<a1[i];
}
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: