全排列(递归)

  在学习算法分析的时候,一开始会接触到递归算法,递归算法案例往往很容易理解。但是如何根据实际情况去设计递归算法往往是难题。接下来通过全排列案例来讲述一下递归的用法。

1.全排列

    给定一串无重复的字符或数字,输出其有所有排列,并统计其共有排列个数。

    例:给定个数n(n<10),=输入n个数字或字符,输出其所有排列及其排列个数

例 :    输入:3

                     123

     输出:123  132  213  231  321  312

                       6

    算法思想:递归

    数学归纳法分析:

N =1;排列个数 1  

 N =2;排列个数 3  = 2 * 1

 N =3;排列个数 6  = 3 * 2 * 1

 N=4;排列个数24   = 4 * 3 * 2 * 1 

 …..

N = n;排列个数n * (n-1)* (n-2) *(n-3) ….* 1

以1234为例:

fe2601b8f2b548f78c6d3a29da0d244d.png2aae3746d70648e19c0de674e1a40ee1.png

由图可以发现:

首位有四种数字交换,第二位有三种交换,第三位有两种,最后一位无交换(也可以是一种交换)。

 这样我们就从理解了全排列的排列方式,从而就更方便的写代码了。

以123为例:从最高位开始循环,

第三层有3个循环

第二层有2个循环

 第一层有1个循环

如果有4层循环,就是依次第四层有4个循环,依次向下嵌套。

如果有n层循环,就是依次第n层有n个循环,依次向下嵌套。

就像金字塔一样,依次向上叠加。

以123全排列为例就是:

最高位可以有3个数交换

94169e0ed8624f468300f897f202cf0c.png

 代码实现:递归

void perm(char list[],int k,int m)
{
	if(k==m) //当循环到最后一层时(末尾),输出排列 
	{
		count++;
		printf("%s\n",list);
	}
	for(int i=k;i<=m;i++)   
	{	
			swap(&list[k],&list[i]);  //交换位置 
			perm(list,k+1,m);        //递归调用 
			swap(&list[k],&list[i]);
	}
}

上述代码就是关键递归函数,但是很不容易看懂。

下图图解更方便理解这个递归调用的核心。

 以字符串list =“123”为例子:

c332a5212adb4071ba6102202a792f8c.png

 

 当循环到最后一层时输出循环。

正好符合排序个数 N=3 时

排序个数等于  3 *  2 *  1 。

2. 完整代码如下:

#include <stdio.h>
#include <string.h>
int count=0;
void swap(char *a,char *b) 
{
	char temp;
	temp=*a;
	*a=*b;
	*b=temp;
}
int finish(char list[],int k,int i)   
{
	if(i>k)
	{
		for(int j=k;j<i;j++)
			if(list[j]==list[i])
				return 0;
	}
	return 1;
}
void perm(char list[],int k,int m)
{
	if(k==m) //当循环到最后一层时(末尾),输出排列 
	{
		count++;
		printf("%s\n",list);
	}
	for(int i=k;i<=m;i++)   
	{	
			swap(&list[k],&list[i]);  //交换位置 
			perm(list,k+1,m);        //递归调用 
			swap(&list[k],&list[i]);
	}
}
int main()
{
    char a[10];
    scanf("%s",a); 
    int n =strlen(a);
    printf("排序序列为:\n"); 
	perm(a,0,n-1); 
	printf("总排序个数为\n"); 
	printf("%d",count); 
	return 0;
}

 3.总结:递归

递归简单来说:就是在运行过程中不断调用自己,直到碰到终止条件,返回结果的过程。

核心就是三点:

1.大问题拆分成小问题

2.原问题和子问题求解思路相同,数据规模不同

3.存在递归终止条件

实际做题中也存在第四点:

当不满足终止条件时,要如何缩小函数值并让其进入下一层循环中

递归的根本思想就是数学归纳法分析。

上述递归条件:

1.循环递归,无返回值,递归到最深处k =m 处停止递归。

 

 

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年12月19日
下一篇 2023年12月19日

相关推荐