POJ4081树的转换以及deque iterator not dereferencable 问题

本文介绍了一种将一般树转换为二叉树的方法,并通过深度优先搜索信息构建树结构,实现了树高度的计算。

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

描述

我们都知道用“左儿子右兄弟”的方法可以将一棵一般的树转换为二叉树,如:

    0                             0
  / | \                          /
 1  2  3       ===>             1
   / \                           \
  4   5                           2
                                 / \
                                4   3
                                 \
                                  5

现在请你将一些一般的树用这种方法转换为二叉树,并输出转换前和转换后树的高度。

输入
输入是一个由“u”和“d”组成的字符串,表示一棵树的深度优先搜索信息。比如,dudduduudu可以用来表示上文中的左树,因为搜索过程为:0 Down to 1 Up to 0 Down to 2 Down to 4 Up to 2 Down to 5 Up to 2 Up to 0 Down to 3 Up to 0。
你可以认为每棵树的结点数至少为2,并且不超过10000。
输出
按如下格式输出转换前和转换后树的高度:
h1 => h2
其中,h1是转换前树的高度,h2是转换后树的高度。
样例输入
dudduduudu

样例输出

  2 =>4

解题思路:

      用先根遍历创建一棵树,首先构建一个节点类型的指针栈,首先将根(root)压入栈底,当输入字符为'd'时,创建一个新的节点temp,将栈顶元素赋值给father,作为新节点的父亲节点。如果father的lchild == NULL,说明temp是father的第一个孩子节点。如果father的lchild !=NULL,则通过循环找到father->lachild的最右端,将temp赋值给它。当输入字符为'u'时,回溯到父亲节点,栈执行pop操作。

      栈中所有曾经存在的元素都有可能是新节点的父亲节点,栈中元素个数最多的时候也是这棵树最深的时候。如果字符串中du顺序正确的话,最后栈中只剩下root节点。

#include<iostream>
#include<stack>
using namespace std;
typedef struct _Node
{
	int value;
	struct _Node *lchild, *rchild;
}Node;
stack<Node *> s;
const int Max = 20010;//最多一万个节点,也就是说10000个d和10000个u
unsigned int max_stack_size = 0;//这个值代表数的深度
Node* main_solution(char *c1, Node *root,unsigned int &max_stack_size)
{
	//Node *father;
	//Node *child;
	char *c = c1;
	int value = 1;
	while (*c != '\0')
	{
		if (*c == 'd')
		{	
			Node *temp = (Node *)malloc(sizeof(Node));
			temp->lchild = NULL;
			temp->rchild = NULL;
			temp->value = value++;

			Node *father = s.top();//栈顶元素是父亲节点
			if (father->lchild == NULL)//temp节点是father节点的第一个子节点
			{
				father->lchild = temp;//
			}
			else//temp节点不是其父节点的第一个子节点
			{
				Node *child = father->lchild;
				while (child->rchild) { child = child->rchild; }
				child->rchild = temp;
			}
			s.push(temp);
			if (s.size() > max_stack_size) { max_stack_size = s.size(); }//统计栈曾经达到的最多元素个数
			
		}

		else//回溯到父节点
		{
			s.pop();
		}
		c++;//移动到下一个字符
	}
	return root;//这棵数已经建好
}
//统计左子右兄树的深度(递归计算)
int Cal_Tree(Node *root)
{
	int num_l, num_r;

	if (root == NULL){ return 0; }
	else
	{
		num_l = 1 + Cal_Tree(root->lchild);
		num_r = 1 + Cal_Tree(root->rchild);
		if (num_l > num_r) { return num_l; }
		else { return num_r; }
	}
}
//内存释放函数(先根遍历释放内存)
void DELETE(Node *root)
{
	if (root)//root不为NULL时
	{
		DELETE(root->lchild);//左分支子树已经释放完毕
		DELETE(root->rchild);//右分支子树已经释放完毕
		delete root;//释放指针变量对应的内存空间
		root = NULL;//防止指针乱跑
	}
	//root等于NULL时,啥都不做
}
int main()
{
	Node *root = (Node *)malloc(sizeof(Node));
	char dic[Max];
	cin.getline(dic, Max, '\n');//可以接受空格,当输入流遇到换行时,停止输入
	//cin >> dic;
	/*   初始化根节点   */
	root->lchild = NULL;
	root->rchild = NULL;
	root->value = 0;//根节点的标号是0

	s.push(root);
	root = main_solution(dic, root, max_stack_size);
	int last_transform = Cal_Tree(root) - 1;
	int pre_tansform = max_stack_size - 1;
	cout << pre_tansform << " => " << last_transform << endl;
	//DELETE(root);
	system("pause");
	return 0;
}
关于deque iterator not dereferencable 问题,以下是本人的感悟:

如果将第39行if (s.size() > max_stack_size) { max_stack_size = s.size(); }移动到else和if语句之间的第42行,就会出现

deque iterator not dereferencable的程序崩溃,结合线程并行的说明以及c++多线程并行,本人进行以下的分析:s.size()是一

个不断变化的量,栈<stack>容器对象s是一个临界区,属于不同线程的共享资源,将第39行程序放入else-if之间,说明if语句无论是否满足,都会被执行。第39行程序如果放在if(条件为真)的控制内,会与s.push(temp)组成原语,不可分割。多线程程序有很多语句是并发的,如果if控制段程序与else控制段程序并发,s.size()的值就会不确定,程序会发生异常。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值