【无标题】

基于C++中的list实现的N叉树

  1. 问题的引入:某家公司要做一个决策类软件,针对每一种方案都有n种需要执行的任务,每一种任务下面都有m种可以完成该方案的技术,且每一项任务都必须要完成,现在要根据每一项技术的特点求出完成该方案最优的技术组合。
  2. 思考:假设要完成第一项任务,假设可以完成该项任务的技术总共有n1种,那么可供我们选择的技术组合就有(2^n1-1)种(至少要有一种技术)对于m个任务,我们完成该方案的技术组合可以用数据结构中的树来表示:(如下图)
    图一 不同技术组合的树状图
    这里以两个任务为例,任务一下面有技术1,2,任务二下面有技术3,4,5,6,那么完成这个目标的方案组合就有(1,3)(1,4)(1,5)(1,6)(2,3)(2,4)(2,5)(2,6),那么,我们得到这些技术组合的方式就很简单了,只需要对树做一次从左到右的遍历就可以了。在每次遍历结束后,我们根据特定的算法计算每种方案对目标的贡献度的大小,就可以得到最优的方案组合。
    下面是怎么生成一个N叉树(在实际情况中,每种任务下方的技术个数是不定的)的代码
    先来错误的代码:
#include<iostream>
#include<list>
using namespace std;

struct TreeNode {
	int data;
	list<TreeNode*> childList;
	TreeNode(int data)
	{
		this->data = data;
	}

};
list<TreeNode*> lis;
void CreatTree(list<TreeNode*>&lis, list<TreeNode*>&nodes)
{
	if (lis.empty())
	{
		for (const auto&item : nodes)
		{
			lis.push_back(item->data);
		}
		return;
	}
	else
	{
		for (const auto&item : lis)
		{
			 CreatTree(item->childList, nodes);
		}
	}
	return;
}
void Print_Tree(list<TreeNode*>&lis)
{
	if (lis.empty())
	{

	}
}
int main()
{
	list<TreeNode*> node1;
	node1.push_back(new TreeNode(12));
	node1.push_back(new TreeNode(13));
	list<TreeNode*> node2;
	node2.push_back(new TreeNode(114));
	node2.push_back(new TreeNode(132));
	node2.push_back(new TreeNode(1321));
	list<TreeNode*> node3;
	node3.push_back(new TreeNode(15));
	node3.push_back(new TreeNode(16));
	CreatTree(lis, node1);
	CreatTree(lis, node2);
	CreatTree(lis, node3);
	system("pause");
	return 0;
}

接下来放正确的代码

#include<iostream>
#include<list>
using namespace std;

struct TreeNode {
	int data;
	list<TreeNode*> childList;
	TreeNode(int data)
	{
		this->data = data;
	}

};
list<TreeNode*> lis;
void CreatTree(list<TreeNode*>&lis, list<TreeNode*>&nodes)
{
	if (lis.empty())
	{
		for (const auto&item : nodes)
		{
			lis.push_back(new TreeNode(item->data));
		}
		return;
	}
	else
	{
		for (const auto&item : lis)
		{
			 CreatTree(item->childList, nodes);
		}
	}
	return;
}
void Print_Tree(list<TreeNode*>&lis)
{
	if (lis.empty())
	{

	}
}
int main()
{
	list<TreeNode*> node1;
	node1.push_back(new TreeNode(12));
	node1.push_back(new TreeNode(13));
	list<TreeNode*> node2;
	node2.push_back(new TreeNode(114));
	node2.push_back(new TreeNode(132));
	node2.push_back(new TreeNode(1321));
	list<TreeNode*> node3;
	node3.push_back(new TreeNode(15));
	node3.push_back(new TreeNode(16));
	CreatTree(lis, node1);
	CreatTree(lis, node2);
	CreatTree(lis, node3);
	system("pause");
	return 0;
}

相比较于上方正确的代码,做出更改的只有这一部分
更改部分
在原来的代码中

if (lis.empty())
	{
		for (const auto&item : nodes)
		{
			lis.push_back(item->data);
		}
		return;
	}

lis.push_back(itm->data)会将一个地址存放在父亲的ChildList中,那么当左边的树添加完子节点的时候,此时再给右边的树添加子节点,会让上一层中对称位置的指针指向同一个地址,此时,如果我们要在下一层添加子节点,当我们遍历左边的树的时候可以添加子节点,但是当我们遍历右边的树的时候,因为左边的树的对称位置下方已经添加了数据,那么此时判定右边的树不为空,就会进入递归调用中,给这一层下方添加子节点,添加完成之后,返回初始调用的位置,执行for循环,此时下一个节点和上一个节点同样的问题。此时看似是在遍历右边的树,其实是在遍历左边的树,因此,程序就会卡死,不停的给15的下面添加15,16,导致栈溢出。
当我们把代码修改为

lis.push_back(new TreeNode(item->data));

后,此时指针指向的地址不是同一个地址,程序顺利运行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值