【作业】 数据结构作业(1)

该博客探讨了一种通过二叉树结构递归生成布尔值所有可能组合的方法,首先介绍了初始的自顶向下递归思路及其问题,然后改用自底向上递归并优化了输出。虽然这种方法简洁,但存在较高的时间复杂度O(n*2^n)和空间复杂度O(2^n)。博主还分享了更简洁的直接递归解决方案,减少了时间和空间开销。实验过程中遇到了输出异常和效率问题,最后通过调整解决了这些问题。
摘要由CSDN通过智能技术生成

题目描述:

给n个bool变量,要求输出这n个bool值所有可能的组合,
并计算所有可能组合的数量。 

我最初的想法

1、构造一个n+1层二叉树,根节点不储存值
2、二叉树的左节点和右节点分别储存的值为true, false
3、二叉树的叶子节点数即为组合的数量
4、从每个叶子节点向上递归,打印值, 直到到达根节点

注:本题利用数组保存一个二叉树结构,
一个序号为i的节点的两个子节点序号为2 * i 和 2 * i + 1, 
值分别为truefalse

代码实现

#include<iostream>
using namespace std;

//递归计算所有组合的情况
int cnt(int n)
{
	if (n == 1) return 2;
	return 2 * cnt(n - 1);
}

//用数组保存一个二叉树结构
//一个序号为i的节点的两个子节点序号为2 * i 和 2 * i + 1,值分别为true和 false
void makeBoolArray(bool* a, int N)
{
	for (int i = 1; i < N; i += 2) a[i] = false;
	for (int j = 2; j < N; j += 2) a[j] = true;
}

//从叶子节点自底而上递归
void print(bool* a, int k)
{
	if (k <= 1)  return;
	if (a[k])  cout << "true   ";
	else       cout << "false  ";
	print(a, k / 2);
}

//测试
int main()
{
	int n;
	cout << "n: ";
	cin >> n;
	int count = cnt(n);
	cout << "组合数: " << count << endl;

	bool* a = new bool[2 * count];
	makeBoolArray(a, 2 * count);

	for (int i = count; i < count * 2; ++i)
	{
		print(a, i);
		cout << endl;
	}

	delete[] a;
}

实验总结

实验遇到问题和解决过程: 
最原始的思路是从根节点自顶而下递归,输入测试数据后显示一些数据未能正常输出并有不合理的换行。将算法改为从叶子节点自底而上递归解决了问题,但也造成了更大的时间开销。

时间复杂度和空间复杂度分析:
对bool变量数n,从2^n个叶子节点向上递归到根节点经过n层,其余时间开销相对可忽略,时间复杂度为O(n* 2^n)
输入n,需要的二叉树为n+1层,开辟了一个长度为2^n的数组,其余空间开销为常数级别,故空间复杂度为O(2^n)

实验心得体会:
递归法思路和代码实现简洁,但会消耗大量的时间和栈空间

这个算法显然非常的冗长, 但使用二叉树、一个节点的两个子节点分别保存True和False的想法仍然非常直观, 同时使用数组维护一个二叉树的结构(利用索引为i的子节点索引为2i 和2i + 1)也简化了代码

上网查了一下这道题, 发现直接用递归做非常的容易, 直接贴代码了

#include<iostream>
using namespace std;

enum boolean {True, False};


int cnt = 0;
void recursion(boolean* a, int k, int n)
{
	if (k == n)
	{
		for (int i = 0; i < n; ++i)
		{
			cout << a[i] << " ";
		}
		cout << endl;
		++cnt;
	}
	else
	{
		a[k] = True;
		recursion(a, k + 1, n);
		a[k] = False;
		recursion(a, k + 1, n);
	}
}

int main()
{
	int n;
	cin >> n;
	boolean* a = new boolean[n];
	recursion(a, 0, n);
	cout << endl;
	delete[] a;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值