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

来源:互联网 发布:周末网络个人理财申请 编辑:程序博客网 时间:2024/06/03 17:41

算法导论上对归并排序的算法描述如下

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

MERGE-SORT(A, p, r )if p < r  Check for base casethen q ←(p + r)/2  DivideMERGE-SORT(A, p, q) // ConquerMERGE-SORT(A, q + 1, r ) // ConquerMERGE(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--19int 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;}



原创粉丝点击