归并排序 递归和非递归

一  递归 :


/**  递归版本
*  采用分治的方法,将n个元素自顶向下分成两个n/2的子问题, 再将子问题进行划分,
*  最终将整个问题分解成每个字表长度为 1 的有序表,然后自底向上成对归并。
**/

#include <stdio.h>

int b[100]; //中间过程数组

void merge(int a[], int low, int mid, int high){
	// 此时a[] 的a[low,mid] 和a[mid+1,high]各自都是有序的,属于成对的两个子问题
	//需要合并成一个有序表
	int i, j, k;
	i = low;
	j = mid + 1;
	k = 0;
	for (k=0; i <= mid&&j <= high; k++){
		//将较小的先放入b[]
		if (a[i] < a[j])
			b[k] = a[i++];
		else
			b[k] = a[j++];
	}

	while (i <= mid)  b[k++] = a[i++];
	while (j <= high) b[k++] = a[j++];

	// 将已有序的数据b[0,k-1]拷贝到a[low,high]中
	for (i = low,j=0; i <= high; i++,j++){
		a[i] = b[j];
	}
}

void mergeSort(int a[], int low, int high){
	if (low < high){//划分
		int mid = (low + high) / 2;
		mergeSort(a, low, mid); //左子问题
		mergeSort(a, mid + 1, high);//右子问题
		merge(a, low, mid, high);//归并两个子问题
	}
}

int main(){

	int a[8] = {
		1, 6, 3, 2, 9, 8, 7, 5
	};

	//8个元素
	int n = 8;

	mergeSort(a, 0, n - 1);

	for (int i = 0; i < n; i++){
		printf("%d ", a[i]);
	}

	printf("\n");

	return 0;
}


二 非递归:

整个思想如下图,和递归方法思想是一致的。


/**  非递归版本
*	同样对数据进行划分,每一趟从左到右,从上到下,依次归并
*   merge()函数和递归版本一样。主要区别在于mergeSort()里的每次步长的计算和归并。
**/

#include <stdio.h>

int b[100]; //中间过程数组

void merge(int a[], int low, int mid, int high){
	// 此时a[] 的a[low,mid] 和a[mid+1,high]各自都是有序的,属于成对的两个子问题
	//需要合并成一个有序表
	int i, j, k;
	i = low;
	j = mid + 1;
	k = 0;
	for (k=0; i <= mid&&j <= high; k++){
		//将较小的先放入b[]
		if (a[i] < a[j])
			b[k] = a[i++];
		else
			b[k] = a[j++];
	}

	while (i <= mid)  b[k++] = a[i++];
	while (j <= high) b[k++] = a[j++];

	// 将已有序的数据b[0,k-1]拷贝到a[low,high]中
	for (i = low,j=0; i <= high; i++,j++){
		a[i] = b[j];
	}
}

void mergeSort(int a[],int n){
	int step = 1;//步长 分别是1,2,4,8...

	while (step <= n){
		int low = 0;
		while (low + step <= n){
			int mid = low + step - 1;
			int high = mid + step;
			if (high > n){
				high = n;  //数据个数不是2的整数次方,最后的数据可能不足step个。
			}

			merge(a,low, mid, high);
			low = high + 1; //按照上图 ,从左到右
		}

		step *= 2; //按照上图 ,从上到下
	}
}

int main(){

	int a[8] = {
		1, 6, 3, 2, 9, 8, 7,5
	};

	//8个元素
	int n = 8;

	mergeSort(a,n - 1);

	for (int i = 0; i < n; i++){
		printf("%d ", a[i]);
	}

	printf("\n");

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值