我们都知道用“左儿子右兄弟”的方法可以将一棵一般的树转换为二叉树,如:
0 0 / | \ / 1 2 3 ===> 1 / \ \ 4 5 2 / \ 4 3 \ 5
现在请你将一些一般的树用这种方法转换为二叉树,并输出转换前和转换后树的高度。
你可以认为每棵树的结点数至少为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()的值就会不确定,程序会发生异常。