这篇文章中我们主要讲的是二叉树的创建,我们先把二叉树(二)中提到的二叉树的设计结构提过来:
#define END '#'
typedef char ElemType;
typedef struct BtNode//BinaryTreeNode
{
struct BtNode* leftchild;//左孩子节点
struct BtNode* parent;//双亲指针
struct BtNode* rightchild;//右孩子节点
ElemType data;//数据域
}BtNode,*BinaryTree;
struct BtNode* Buynode()
{
struct BtNode* s = (struct BtNode*)malloc(sizeof(*s));
//struct BtNode* s=(struct BtNode*)malloc(sizeof(struct BtNode));
if (NULL == s)
{
exit(0);
}
memset(s, 0, sizeof(*s));//对二叉树单个节点的空间进行初始化
return s;
}
有了二叉树的结构和空间之后我们来进行二叉树的创建,创建代码如下:
BtNode* CreateTree()
{
ElemType ch;
BtNode* s = NULL;
cin >> ch;
if (ch != END)
{
s = Buynode();//初始化s的空间
s->data = ch;//ch给s所指向的数据域
s->leftchild = CreateTree();//左孩子是一颗二叉树
s->rightchild = CreateTree();//右孩子是一颗二叉树
}
return s;
}
接下来我们来给出需要进行测试的主函数:
int main()
{
BinaryTree root = NULL;
root = CreateTree();
InOrder(root);
cout << endl;
return 0;
}
当执行输入ABC##DE##F##G#H##时,运行结果如下:
整个分析的过程如下,由于递归调用的过程相对复杂,这个过程还是比较复杂的,如下图所示:
当执行输入ABC##DE##F##G#H##时,最终代码执行出来的二叉树如下图所示:
因此它的中序遍历为:CBEDFAGH如上面的运行结果所示。
其前序遍历和后序遍历分别为下面两种运行结果截图所示:
接下来我们来研究通过字符串来创建二叉树,首先看下面的代码:
BtNode* strCreateTree(const char* str)
{
BtNode* s = NULL;
if (str != NULL && *str != END)
{
s = Buynode();
s->data = *str;
s->leftchild = strCreateTree(++str);
//s->leftchild = strCreateTree(++str);
s->rightchild = strCreateTree(str+1);
//s->rightchild = strCreateTree(str+1);
}
return s;
}
主函数给出其测试用例如下:
int main()
{
char* str = "ABC##DE##F##G#H##";
BinaryTree root = NULL;
root = strCreateTree(str);
//前序、中序、后序遍历代码见二叉树(二)
InOrder(root);
cout << endl;
PreOrder(root);
cout << endl;
EndOrder(root);
cout << endl;
return 0;
}
运行结果是下面这样的:
很明显我们可以看到同样都是“ABC##DE##F##G#H##”,使用键盘输入创建的二叉树和通过字符串创建的二叉树完全不相同,这就是我们在《数据结构 &分治策略与递归》中讲到的在递归调用中一般不要使用前置“++”进行操作有关。
由于递归调用的时候是每个被调用的函数都有自己对应的栈帧,当str++或者str+1的时候,他们都在自己相应的栈帧上进行++操作,遍历的Str字符串也相互之间没有关系,根本不能将同一个字符串完整遍历一遍,所以才能得到上面这样的结果。
所以我们将参数str设为“&”(相当于别名)的时候,虽然每个递归函数在不同的栈帧上进行,但他们操作的确是同一个字符串,所以上面不能将字符串完整遍历的问题得到了解决。代码修改如下:
BtNode* strCreateTree(char* &str)
{
BtNode* s = NULL;
if (str != NULL && *str != END)
{
s = Buynode();
s->data = *str;
s->leftchild = strCreateTree(++str);
s->rightchild = strCreateTree(++str);
}
return s;
}
这样一来,我们通过字符串创建的二叉树就和第一种从键盘上读取字符创建的二叉树完全相同了。