归并排序

归并排序算法的基本思想是:将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成所要求的排好序的集合。

 

代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef int TYPE;
#define PRINT_FORMAT "%-3d "
#define ARR_LEN 100

int main(void) {

	void get_random_arr(TYPE arr[], int len);
	void print_arr(TYPE arr[], int len);
	void merge_sort(TYPE arr[], int len);

	TYPE arr[ARR_LEN];

	get_random_arr(arr, ARR_LEN);

	printf("Befor Sorting:\n");
 	print_arr(arr, ARR_LEN);

	merge_sort(arr, ARR_LEN);

	printf("After Sorting:\n");
	print_arr(arr, ARR_LEN);

	return EXIT_SUCCESS;
}

/*
** 归并排序
*/
void merge_sort(TYPE arr[], int len) {

	void merge_pass(TYPE src[], TYPE dst[], int size, int len);

	TYPE *arr_tmp;
	int size = 1;

	arr_tmp = (TYPE*) malloc(sizeof(int) * len);
	if (arr_tmp == NULL) {
		perror("malloc");
		exit(EXIT_FAILURE);
	}

	while (size < len) {
		merge_pass(arr, arr_tmp, size, len);	// 合并到临时数组
		size += size;
		merge_pass(arr_tmp, arr, size, len);	// 再合并回原数组
		size += size;
	}

	free(arr_tmp);
}

/*
** 合并大小为size的相邻子数组
*/
void merge_pass(TYPE src[], TYPE dst[], int size, int len) {

	void merge(TYPE src[], TYPE dst[], int r, int s, int t);

	int i;
	
	for (i = 0; i <= len - size*2; i += size*2) {
		merge(src, dst, i, i+size-1, i+size*2-1);
	}

	/*
	** 剩下的元素,个数小于2*size
	*/
	if (i + size < len) {
		/*
		** 剩下的元素,如果个数大于size,则再合并一次
		*/
		merge(src, dst, i, i+size-1, len-1);
	} else {
		/*
		** 剩下的元素,如果个数不大于size,则直接复制过去
		*/
		while (i <= len-1) {
			dst[i] = src[i];
			i++;
		}
	}
}

/*
** 合并src[r:s]和src[s+1:t]到dst[r:t]中
*/
void merge(TYPE src[], TYPE dst[], int r, int s, int t) {
	int i = r;
	int j = s + 1;
	int k = r;

	while ( (i <= s && j <= t) ) {
		
		if (src[i] <= src[j])
			dst[k++] = src[i++];
		else
			dst[k++] = src[j++];
	}

	if (i > s) {
		while (j <= t)
			dst[k++] = src[j++];
	} else {
		while (i <= s)
			dst[k++] = src[i++];
	}
}

/*
** 简单地获取随机数组
*/
void get_random_arr(TYPE arr[], int len) {
	int i;
	
	srand((unsigned int)time(NULL));
	for (i = 0; i < len; i++) {
		arr[i] = rand() % 100;
	}
}

/*
** 打印数组
*/
void print_arr(TYPE arr[], int len) {
	int i;
	for (i = 0; i < len; i++) {
		printf(PRINT_FORMAT, arr[i]);

		if ((i + 1) % 10 == 0) 
			putchar('\n');
	}
	putchar('\n');
}
结果输出:

Befor Sorting:
41  67  34  0   69  24  78  58  62  64
5   45  81  27  61  91  95  42  27  36
91  4   2   53  92  82  21  16  18  95
47  26  71  38  69  12  67  99  35  94
3   11  22  33  73  64  41  11  53  68
47  44  62  57  37  59  23  41  29  78
16  35  90  42  88  6   40  42  64  48
46  5   90  29  70  50  6   1   93  48
29  23  84  54  56  40  66  76  31  8
44  39  26  23  37  38  18  82  29  41

After Sorting:
0   1   2   3   4   5   5   6   6   8
11  11  12  16  16  18  18  21  22  23
23  23  24  26  26  27  27  29  29  29
29  31  33  34  35  35  36  37  37  38
38  39  40  40  41  41  41  41  42  42
42  44  44  45  46  47  47  48  48  50
53  53  54  56  57  58  59  61  62  62
64  64  64  66  67  67  68  69  69  70
71  73  76  78  78  81  82  82  84  88
90  90  91  91  92  93  94  95  95  99


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值