算法们

本文详细解读了插入排序和归并排序两种常见算法,通过图解演示了它们的工作原理,并提供了C语言的源码实例。插入排序通过逐个元素比较插入位置,适合小规模数据;归并排序则采用分治策略,将数组分为两半递归排序,适用于大规模数据。
摘要由CSDN通过智能技术生成

插入排序

1.1 图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GgERTk5w-1619107939233)(https://images.cnblogs.com/cnblogs_com/coding-996/1609484/o_200210053346482235d48a81823b830e50aaf5276c25.gif,size_16,color_FFFFFF,t_70)]

  • 现在抓到一张 7,把它和手里的牌从右到左依次比较,7 比 10 小,应该再往左插,7 比 5 大,好,就插这里。为什么比较了 10 和 5 就可以确定 7 的位置?为什么不用再比较左边的 4 和2 呢?因为这里有一个重要的前提:手里的牌已经是排好序的。现在我插了 7 之后,手里的牌仍然是排好序的,下次再抓到的牌还可以用这个方法插入
  • 编程对一个数组进行插入排序也是同样道理,但和插入扑克牌有一点不同,不可能在两个相邻的存储单元之间再插入一个单元,因此要将插入点之后的数据依次往后移动一个单元

1.2 分析

在这里插入图片描述

1.3 源码

#include <stdio.h>
#define LEN 5
int a[LEN] = { 10, 5, 2, 4, 7 };
void insertion_sort(void)
{
	int i, j, key;
	for (j = 1; j < LEN; j++) {
		printf("%d, %d, %d, %d, %d\n",
				a[0], a[1], a[2], a[3], a[4]);
		key = a[j];
		i = j - 1;
		while (i >= 0 && a[i] > key) {
			a[i+1] = a[i];
			i--;
		}
		a[i+1] = key;
	}
	printf("%d, %d, %d, %d, %d\n",
			a[0], a[1], a[2], a[3], a[4]);
}
int main(void)
{
	insertion_sort();
	return 0;
}

归并排序

2.1 图解

在这里插入图片描述

sort 函数把 a[start…end]平均分成两个子序列,分别是 a[start…mid]和a[mid+1…end],对这两个子序列分别递归调用 sort 函数进行排序
 
然后调用merge 函数将排好序的两个子序列合并起来,由于两个子序列都已经排好序了,合并的过程很简单,每次循环取两个子序列中最小的元素进行比较将较小的元素取出放到最终的排序序列中如果其中一个子序列的元素已取完,就把另一个子序列剩下的元素都放到最终的排序序列中。为了便于理解程序,我在 sort 函数开头和结尾插了打印语句,可以看出调用过程是这样的

2.2 分析

sort函数的定义(递归调用sort)
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.3 源码

int a[LEN] = { 5, 2, 4, 7, 1, 3, 2, 6 };
void merge(int start, int mid, int end)
{
	int n1 = mid - start + 1;
	int n2 = end - mid;
	int left[n1], right[n2];
	int i, j, k;
	for (i = 0; i < n1; i++) /* left holds a[start..mid] 
							  */
		left[i] = a[start+i];
	for (j = 0; j < n2; j++) /* right holds a[mid+1..end] 
							  */
		right[j] = a[mid+1+j];
	i = j = 0;
	k = start;
	while (i < n1 && j < n2)
		if (left[i] < right[j])
			a[k++] = left[i++];
		else
			a[k++] = right[j++];
	while (i < n1) /* left[] is not exhausted */
		a[k++] = left[i++];
	while (j < n2) /* right[] is not exhausted */
		a[k++] = right[j++];
}
void sort(int start, int end)
{
	int mid;
	if (start < end) {
		mid = (start + end) / 2;
		printf("sort 
				(%d-%d, %d-%d) %d %d %d %d %d %d %d %d\n", 
				start, mid, mid+1, end, 
				a[0], a[1], a[2], a[3], a[4], a[5], a[6], 
				a[7]);
		sort(start, mid);
		sort(mid+1, end);
		merge(start, mid, end);
		printf("merge (%d-%d, %d-%d) 
				to %d %d %d %d %d %d %d %d\n", 
				start, mid, mid+1, end, 
				a[0], a[1], a[2], a[3], a[4], a[5], a[6], 
				a[7]);
	}
}
int main(void)
{
	sort(0, LEN-1);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值