关于数组的递归全排列问题

本文通过递归方法解决了数组的全排列问题,并详细解释了递归与循环的运用,帮助读者理解全排列的计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进入大学后每天似乎都在努力学习,但是感觉总是学不会什么东西。昨天在健身房跟同学聊天,提到学了东西之后可以自己写一些东西来巩固记忆和理解。今天刚刚接触到一个关于数组递归全排列的问题,看了别人写的相关介绍,自己根据理解也来献丑一下。

我这里写的数组全排列问题主要用的就是递归的方法来实现这个数组的全排列问题。

array[4]={1,2,3,4},对这个数组进行全排列。主要思路是:

1.将这个全排列理解为往四个xxxx中填充数字问题,第一个x处有四种选择,第二个x处有三个选择,第三个x处有两个选择,第四个x处只有一种选择。这样就将这个问题分解为几个性质相同的小问题,可以采用递归的方法来解决。

2.将上面的思路用编程的思想来考虑。

由上面分析可得,首先将问题分解为四个小问题,然后第二步中将第一步中的每个小问题分解为三个小问题,第三步将第二步中的每个子问题又分解为两个问题。其中每个子问题的性质都是与原问题相似的,先是四个数的全排列,然后是三个数的全排列,然后是两个数的排列,最后将最后一个数放在最后的位置。所以是一个递归问题,需要完成的事情相同,只是数目不同而已,所以对应到函数就是功能相同,参数不同。

// 数组的全排列问题.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;

int sum = 0;

void print(int array[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << array[i];
	}
	cout << endl;
}

void swap(int array[], int a, int b)
{
	int temp = array[a];
	array[a] = array[b];
	array[b] = temp;
}

void permuta(int array[], int len, int index)
{
	if (index==len)
	{
		print(array, len);
		sum++;
	}
	for (int i = index; i < len; i++)
	{
                //交换两个数
		swap(array, i, index);
		permuta(array, len, index + 1);
                //将两个数还原,以便i++后与index交换时符合程序的设计思路
		swap(array, i, index);
	}
}

int main()
{
	int array[4] = { 1,2,3,4};
	permuta(array, 4, 0);
	cout << sum;
    return 0;
}
输出sum为24。
程序的运行思路是先沿着一个问题递归求得下面所有的子问题,然后通过for循环求解与其平行的其他子问题。

例如,对于序列4,2,3,1。它有三个子问题,4,2,3,1   4,3,2,1   4,1,3,2,对于最后一个序列4,1,3,2,有两个子问题,4,1,3,2   4,1,2,3。这两个问题已经不能分解,此时的index==len,打印出序列。

这是一个递归到底的过程,然后接下来程序会求解与4,1,3,2平行的两个序列4,2,3,1   4,3,2,1,求解完成后再返回求解与4,2,3,1平行的三个子问题。

总结:写的有些不知所云,纯粹出于为了增加自己的记忆和理解,每个人的想法可能不一样。个人认为这个问题中最重要的就是理解for循环和递归的运行过程,结合在数学层面上对全排列的理解就会很容易明白。

在C语言中生成一个指定数组全排列,可以使用非递归的迭代方法,通常采用基于置换的方法,即循环交换数组中的元素。以下是一个实现的示例: ```c #include <stdio.h> #include <stdbool.h> // 函数声明 void swap(int *a, int *b); void permute(int arr[], int start, int end); int main() { int arr[] = {1, 2, 3}; // 示例数组 int n = sizeof(arr) / sizeof(arr[0]); permute(arr, 0, n - 1); return 0; } // 交换数组中的两个元素 void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } // 生成数组全排列(非递归实现) void permute(int arr[], int start, int end) { bool flag = true; // 控制循环的标志变量 int i; // 初始化一个数组来记录是否访问过每个位置 int isVisited[10]; // 假设数组元素范围不超过10 for (i = 0; i <= end; i++) { isVisited[i] = 0; // 初始化所有位置为未访问 } for (i = 0; i <= end; i++) { // 当前位置未被访问,进行排列 if (isVisited[i] == 0) { // 找到一个未被访问的位置,从当前位置开始生成排列 isVisited[i] = 1; // 标记为已访问 swap(&arr[start], &arr[i]); // 将当前位置的元素与起始位置的元素交换 // 如果当前不是最后一个元素,递归生成剩余元素的排列 if (start < end) { permute(arr, start + 1, end); } else { // 当前是最后一个元素,打印一个全排列 for (int j = 0; j <= end; j++) { printf("%d ", arr[j]); } printf("\n"); } // 回溯,将元素交换回去,标记为未访问 swap(&arr[start], &arr[i]); isVisited[i] = 0; } // 如果当前位置已访问,直接跳过 flag = false; } // 如果所有元素都被访问过一次,则结束循环 if (flag) { return; } else { // 恢复最后交换的状态,继续循环 if (start < end) { permute(arr, start + 1, end); } else { for (int j = 0; j <= end; j++) { printf("%d ", arr[j]); } printf("\n"); } } } ``` 这段代码首先定义了`swap`函数用于交换数组中的两个元素,然后定义了`permute`函数来生成全排列。`permute`函数使用了一个`isVisited`数组来记录每个元素是否在当前排列中被访问过。函数通过循环遍历数组,找到一个未被访问的元素,并将其与起始位置的元素交换,然后递归地生成剩余元素的排列。通过这种方式,可以非递归地生成所有可能的全排列
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值