二路归并算法

二路归并算法

二路归并排序就是将两个有序子表归并成一个有序表。首先我们得有一个算法用于归并:两个有序表放在同一数组的相邻位置上,a[low]到arr[mid]为第一个有序表,a[mid+1]到arr[high]是第二个有序表。每次从两端中取出一个进行比较,小的先放在一个temp数组,最后将比较剩下的直接放到temp中去,最后将temp又复制回arr。这是“治”。
下面说“分”,只需要递归地将前半部分和后半部分的数据各自归并排序即可。

#include 
#include 


/* 
功能:
	输出数组
*/
void disp_arr(int a[],int n)
{
	for (int k = 0; k<n;k++)
			printf("%d ",a[k]);
		printf("\n");
	
}

/*
功能:
	将a[low:mid]和a[mid+1:high] 两个相邻的有序子序列归并为一个有序的子序列a[low:high]
参数:
	a[]: 		被归并数组
	low: 		左	
	mid:		中
	high:		右
	
*/
void Merge(int a[], int low, int mid, int high)
{
	int *tmpa;
	int i = low, j = mid + 1, k = 0;
	tmpa = (int *)malloc((high - low + 1) * sizeof(int));
	while (i <= mid && j <= high)
		if (a[i]<=a[j]){
			tmpa[k] = a[i];
			i++;
			k++;
		}
		else{
			tmpa[k] = a[j];
			j++;
			k++;
		}
		
	while (i <= mid){
			tmpa[k] = a[i];
			i++;
			k++;
		}
	while (j <= high){
			tmpa[k] = a[j];
			j++;
			k++;
		}
	for (k=0, i=low; i<=high; k++, i++){
		a[i] = tmpa[k];
	}
	free(tmpa);
	
}
/* 
功能:

	一趟二路归并排序
参数:
	a[]: 		被归并数组
	length:		子表的长度
	n:			a[]的边界,a的长度-1
*/
void MergePass(int a[], int length, int n)
{
	int i;
	for(i=0;i+2*length-1<n;i=i+2*length)  //归并length长的两个相等的相邻子表
		Merge(a, i, i+length-1, i+2*length-1); 
	if(i+length-1<n)                      //余下两个子表,后者的长度小于length
		Merge(a, i, i+length-1, n-1);
}

/* 
功能:

	二路归并排序
参数:
	a[]: 		被归并数组
	n:			a[]的边界,a的长度-1
*/

void MergeSore(int a[], int n)
{
	int length;
	for (length=1;length<n;length*=2)
		MergePass(a,length,n);
}

int main()
{
	int n = 10;
	int a[] = {1,2,4,6,8,0,9,4,3,5};
	MergeSore(a, n);
	disp_arr(a, 10);
}

你可能感兴趣的:(算法,排序算法,数据结构)