递归经典问题

1.汉诺塔问题

问题描述:相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。
分析:我们先把盘子的个数设置为3。盘子数为3时,我们可以很容易计算出操作步骤数是7。步骤是:

  • A-C
  • A-B
  • C-B
  • A-C
  • B-A
  • B-C
  • A-C
    我们可以发现,不管盘子数量是多少,都必须先得把最大的盘上面的所有盘移动到B杆才行,然后移动最大的盘,再把剩下的盘从B杆移动到C杆。
    这样可以总结出:当盘子数量为n时,我们需要把1到n-1号盘挪到B杆上,再把n号盘移动至C杆,再把B杆上的1到n-1号盘移动C杆。
    具体步骤可以分为:
    1.以C盘为中介,从A杆将1至n-1号盘移至B杆;
    2.将A杆中剩下的第n号盘移至C杆;
    3.以A杆为中介;从B杆将1至n-1号盘移至C杆。
    在进行第一个步骤时,我们可以利用递归的思想,直至n=1,说明第一步完成,步骤三类似。
#include<stdio.h>
void hanoi(int n, char x, char y, char z)
{
	if (n == 1)
	{
		printf("%c---> %c\n", x, z);
	}
	else
	{
		hanoi(n - 1, x, z, y);//第一个步骤
		printf("%c---> %c\n", x, z);//把最大的盘移动到C杆
		hanoi(n - 1, y, x, z);//把B杆上的盘移动到C杆。
	}
}
int main(void)
{
	int n;
	scanf("%d", &n);
	hanoi(n, 'X', 'Y', 'Z');
	return  0;
}

2.快速排序

快速排序算法的基本思想是:通过一趟排序将待排序数据分割成独立的两部分,其中一部分的所有元素均比另一部分的元素小,然后分别对这两部分继续进行排序,重复上述步骤直到排序完成。
步骤:

  • 先找一个基准点数,一般设为序列的中间数
  • 然后设置两个标记变量i,j。i从左往右找比基准点数大的值,j从右往左找比基准点小的值。
  • 找到后互相比较a[i]和a[j]的值,如果a[i]比a[j]大则互换元素,直到i>j,即i的位置超过了j的位置;

经过第一堂寻找排序,数组被分为了2个子序列,左边的值都小于基准点值,右边的值都大于等于基准点的值。再对这两个子序列再次使用上面的方法,直到子序列就剩下一个元素,递归结束。

#include<stdio.h>

void quicksort(int a[], int left, int right)
{
	int i = left, j = right;
	int temp;
	int middle;

	middle = a[(left + right) / 2];
	while (i<=j)
	{
		//从左到右找到大于基准点的元素
		while (a[i] < middle)
		{
			i++;
		}
		//从右到左找到小于等于基准点的元素
		while (a[j] > middle)
		{
			j--;
		}
		//如果i<=j,则互换
		if (i <= j)
		{
			temp = a[i];
			a[i] = a[j];
			a[j] = temp;
			i++;
			j--;
		}
	}
	if (left < j)//左边子序列再次使用上述方法
	{
		quicksort(a, left, j);
	}
	if (i < right)
	{
		quicksort(a, i, right);//右边也使用上述方法,直到子序列就剩下一个元素,排序结束
	}
}
int main(void)
{
	int array[] = { 73,108,111,119,101,70,105,115,104,67,46,99,111,109 };
	int i, length;
	length = sizeof(array) / sizeof(array[0]);
	quicksort(array, 0, length - 1);
	for (int i = 0; i < length; i++)
	{
		printf("%d ", array[i]);
	}
	return 0;
}

还有后续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值