算法分析之递归算法

选择排序为例
在这里插入图片描述
选择排序的思路就是找最小排在最前面。

问题分析:
设f(a,n,i+1)用于对a(i…n-1)元素序列(共n-i-1个元素)进行简单选择排序,是“大问题”。
f(a,n,i+1)用于对a[i+1…n-1]元素序列(共n-i-1个元素)进行简单选择排序,是“小问题”。
当i=n-1时所有元素有序,算法结束。

递归模型:
当i=n-1; f(a,n,i)=不做任何事情,算法结束
否则 f(a,n,i)=通过简单比较挑选a[i…n-1]中最小元素a[k]放在a[i]的位置;f(a,n,i+1)
选择排序递归实现:

#include<stdio.h>
void swap(int &x,int &y)
{
	int t = x;
	x = y;
	y = t;
}
//a:待排序的整型数组
//n:a中元素的数量
//i:参与选择排序的起始元素的下标
//算法作用:对a[i],a[i+1],...,a[n-1]这些元素进行选择排序
void SelextSort(int a[], int n, int i)
{
	int j,k;
	if(i == n - 1)//即待排序的元素只有a[n-1]1个元素,无需排序,为递归出口 
		return;
	k = i;//默认a[i]是a[i...n-1]中最小的元素 
	for(int j = i + 1;j < n;j ++)//循环遍历a[]中从a[i]后一个开始的所有数据 
	{
		if(a[j] < a[k])//如果找到一个比a[i]小的数据,说明a[i]不是最小的 
			k = j;//更新k的值 
	}
	//至此,a[i...n-1]中最小元素的下标已求出,为k 
	
	if(k != i)//如果最小元素不是a[i]
		swap(a[i],a[k]); //将a[k]换到a[i]的位置
	SelextSort(a, n, i + 1); //递归体,待排序的元素减少1个
							//问题规模减1
}

void display(int a[],int n)
{
	for(int i = 0; i < n; i++)
		printf("%d ",a[i]);
	printf("\n");
}
 
int main()
{
	int a[10]= {3,1,2,7,4,5,8,6,9,10};
	printf("排序前:");
	display(a,10);
	
	SelextSort(a,10,0);
	printf("排序后:"); 
	display(a,10);
} 

冒泡排序为例
对于给定的含有n个元素的数组a,采用冒泡排序方法对其按元素值递增排序。
在这里插入图片描述
冒泡排序的思路是通过比较,一趟比较把最小的浮动到最前面,每一趟结束就确定一个数的位置。
问题分析
设f(a,n,i)用于对a[i…n-1]元素序列(共n-i个元素)进行冒泡排序,是“大问题”。
f(a,n,i+1)用于对a[i+1…n-1]元素序列(共n-i-1个元素)进行冒泡排序,是"小问题"。
当i=n-1时所有元素有序,算法结束。
递归模型
当 i=n-1 f(a,n,i)=不做任何事情,算法结束
否则 f(a,n,i)=对于a[i…n-1]元素序列,从a[n-1]开始进行相邻元素比较;若相邻两元素反序则将两者交换;若没有反序则返回,否则执行f(a,n,i+1)
冒泡排序递归实现:

#include<stdio.h>
void swap(int &x,int &y)
{
	int t = x;
	x = y;
	y = t;
}
//a:待排序的整型数组
//n:a中元素的数量
//i:参与冒泡排序的起始元素的下标
//算法作用:对a[i],a[i+1],...,a[n-1]这些元素进行冒泡排序(从小到大)
void BubbleSort(int a[], int n, int i)
{
	int j;
	bool exchange;//用于记录一趟冒泡排序中是否发生过元素交换
	
	if(i == n - 1)//如果待排序元素只有a[n-1]1个,无需排序,为递归出口 
		return; 
	exchange=false;
	
	for(j = n - 1; j > i; j --)//从后往前,让小元素往前移动 
	{
		if(a[j] < a[j - 1])
		{
			swap(a[j],a[j-1]);
			exchange=true;//标记已经发生过交换 
		}
	}
	if(exchange==false)//如果在上面的循环中没有交换元素,说明顺序已经对了,排序提前完成 
		return;
	BubbleSort(a, n, i+1);//递归体,待排序的元素减少到a[i+1...n-1]
						//问题规模减1 
}

void display(int a[],int n)
{
	for(int i = 0; i < n; i++)
		printf("%d ",a[i]);
	printf("\n");
}
 
int main()
{
	int a[]= {1,3,2,7,6,4,5,9,8,10};
	printf("排序前:");
	display(a,10);
	
	BubbleSort(a,10,0);
	printf("排序后:"); 
	display(a,10);
	
	return 0;
} 

求解n皇后问题
在这里插入图片描述
结果我们用一个*整型数组q[]*来保存,q[i]表示第i行的皇后摆在第几(q[i]的值)列。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
C语言递归实现:

#include<stdio.h>
#include<stdlib.h>
#define N 20   //最多皇后个数
int q[N];      //存放各皇后所在的列号,即(i,q[i])为一个皇后位置
int count = 0; //累计解的个数

void dispasolution(int n)//输出n皇后问题的一个解
{
	printf("   第%d个解:",++count);
	for(int i = 1; i <= n; i ++)
		printf("(%d,%d)",i,q[i]);
	printf("\n");
} 

bool place(int i, int j)  //猜测是(i,j)位置能否拜访皇后 
{
	if(i == 1)//第一个皇后总是可以放置的
		return true;
	
	int k = 1;
	while(k < i)  //k = 1~i-1是已放置了皇后的行
	{
		if(q[k] == j||abs(q[k]-j) == abs(i-k))//构成等腰三角形,两个皇后将在对角线上
			return false;
		k ++;
	}
	return true;
}

//i:要放置皇后的起始行
//n:要放置皇后的结束行
//算法作用:在n*n的棋盘上的第i行,第i+1行,...,第n行各放置一个皇后
//在任意第k行放置的皇后,都不能喝第1行,第二行,。。。,第k-1行
//所放置的皇后形成互相攻击的形态
void queen(int i, int n)
{
	if(i > n) // n个皇后已经防止完毕,递归出口 
		dispasolution(n);//输出刚得到的解
	else
	{
		for(int j = 1; j <= n; j ++)//在第i行上试探每一个列j 
		{
			if(place(i, j) == true)//在第i行上找到一个合适位置(i,j) 
			{
				q[i] = j;
				queen(i + 1, n); //递归调用,在第i+1,i+2,...,n行各放置一个皇后
			}
		}
	} 
} 

int main()
{
	int n;//n为存放世纪皇后个数
	printf("皇后问题(n<20) n=");
	scanf("%d",&n);
	
	if(n > 20)
	{
		printf("n值太大,不能求解\n");
	} 
	else
	{
		printf("%d皇后问题求解如下 :\n",n);
		queen(1, n);//放置1~n的皇后 
	}
	
	return 0; 
}

在这里插入图片描述

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岁月辰星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值