二叉树是树中比较重要的一个部分,对于二叉树的建立,还有遍历方式,主要分后序,中序,前序的遍历,而这个的前中后主要是根节点的访问顺序的不同,左子树和右子树的访问顺序是一样的,这其实是一个递归的顺序,因为访问到一个根节点的时候,又可以把下面的节点看成是一颗树,也可以用非递归,也就是队列或栈的方式来访问树,还有ACM的一道题目是已知前序,中序遍历,来叫你写出后序遍历的题目,只有知道两种访问顺序,才能构造出一颗完整的树!
采用先序遍历的方式来创建树 先是输入根节点,随后输入左子树再输入右子树,若为空格,则表示左子树不存在或右子树不存在 因此 本次实验报告的输入为
ABD11G111CE11FH111 1代表空格
//先序创建二叉树 输入时候只读入一个字符,所以用getchar,
treePointer CreateTree() {
treePointer ptree = NULL;
char ch;
ch = getchar();
if (ch==' ')
ptree = NULL;
else {
ptree = (treePointer)malloc(sizeof(node));
ptree->data = ch;
ptree->leftChild = CreateTree();
ptree->rightChild = CreateTree();
}
return ptree;
}
之后是递归的前序后序中序来遍历这棵树 代码比较简单
//先序遍历的递归,先访问根节点,再访左子树,随后访问右子树
void Recursive_Preorder(treePointer ptr)
{
if (ptr) {
cout << ptr->data << " ";
Recursive_Preorder(ptr->leftChild);
Recursive_Preorder(ptr->rightChild);
}
}
//中序遍历的递归,先访问左子树,再访问根节点,随后访问右子树
void Recursive_Inorder(treePointer ptr) {
if (ptr) {
Recursive_Inorder(ptr->leftChild);
cout << ptr->data << " ";
Recursive_Inorder(ptr->rightChild);
}
}
//后序遍历的递归,先访问左子树,再访右子树,随后访问根节点
void Recursive_Postorder(treePointer ptr) {
if (ptr) {
Recursive_Preorder(ptr->leftChild);
Recursive_Preorder(ptr->rightChild);
cout << ptr->data << " ";
}
}
之后是层次的遍历,类似于广搜,用到了队列,如果左孩子存在,左孩子入队列,右孩子存在,右孩子入队列
//层次遍历的递归调用,要用到队列的操作
<pre name="code" class="cpp">void Level_Order(treePointer ptr) {
rear = -1;
front = -1;
queue q[10000];
if (!ptr)
return;
q[++rear].key = ptr;
while (front < rear) {
ptr = q[++front].key;
if (ptr) {
cout << ptr->data << " ";
if (ptr->leftChild)
q[++rear].key = ptr->leftChild;
if (ptr->rightChild)
q[++rear].key = ptr->rightChild;
}
else
break;
}
}
非递归的代码明天再补上
非递归前序 主要是当栈不为空的前提下,先把根的结果输出,随后压入栈时注意,先把右子树压入,再左子树压入,因为是后进先出
//先序非递归的遍历
void iter_Preorder(treePointer ptr) {
top = -1;
stack s[1000];
if (!ptr)
return;
s[++top].key = ptr;
while (top != -1) {
treePointer cur = s[top].key;
cout << cur->data << " ";
top--;
if (cur->rightChild)
s[++top].key = cur->rightChild;
if (cur->leftChild)
s[++top].key = cur->leftChild;
}
}
非递归的中序,也是在栈不为空的前提下,先让左子树的节点全部入栈,随后弹出栈,输出结果,再变成他的右子树
//中序非递归遍历 先让左子树都入栈,当左子树为空的时候,则弹出栈顶的元素,进行输出,随后他自己变成自己的右孩子
void iter_Inorder(treePointer ptr) {
top = -1;
stack s[100];
if (!ptr)
return;
treePointer cur = ptr->leftChild;
s[++top].key = ptr;
while (cur || top != -1)
{
while (cur) {
s[++top].key = cur;
cur = cur->leftChild;
}
cur = s[top--].key;
cout << cur->data << " ";
cur = cur->rightChild;
}
}
非递归的后序 ,要定义一个指针表示他的右子树是否被访问过,首先也是左子树全部入栈,之后再判断右孩子是否为空或已经被访问过,如果是空的或已经访问过了,则输出当前元素的值,否则他变成他的右子树
//后序非递归遍历
void iter_Postorder(treePointer ptr) {
stack s[1000];
top = -1;
treePointer cur = ptr;//指向当前要检查的节点
treePointer preVisited = NULL;//指向前一个被访问的节点
while (cur || top != -1) {
//一直向左走直到为空的时候
while (cur) {
s[++top].key = cur;
cur = cur->leftChild;
}
cur = s[top].key;
//当前右孩子如果为空或者已经被访问,则访问当前的节点
if (cur->rightChild == preVisited||cur->rightChild==NULL) {
cout << cur->data << " ";
preVisited = cur;
top--;
cur = NULL;
}
else
cur = cur->rightChild;
}
}
之后是统计节点的个数,也是用到递归的操作,左孩子和右孩子碰到,节点个数就加1
//统计节点的个数
//统计节点的个数
int countTree(treePointer ptr) {
if (ptr) {
return (countTree(ptr->leftChild) + countTree(ptr->rightChild)+1);
}
return 0;
}
统计叶节点的个数 也用到了递归 当左子树和右子树都不存在的时候,则它就为叶节点
//统计叶节点的个数
int count = 0;
void countLeaf(treePointer ptr) {
if(!ptr->leftChild&&!ptr->rightChild) {
count++;
return;
}
else {
if(ptr->leftChild)
countLeaf(ptr->leftChild);
if(ptr->rightChild)
countLeaf(ptr->rightChild);
}
}
统计树的高度
//统计树的高度
int height = 0;
int treeHeight(treePointer ptr) {
if (ptr->leftChild) {
return treeHeight(ptr->leftChild) + 1;
}
if (ptr->rightChild) {
return treeHeight(ptr->rightChild) + 1;
}
if (ptr)
return 1;
}
主函数的测试代码:
int main() {
treePointer ptr = NULL;
cout << "先序遍历创建树,空号代表该节点无左子树或右子树:";
ptr = CreateTree();
cout << "递归前序遍历:";
Recursive_Preorder(ptr);
cout << endl;
cout << "递归中序遍历:";
Recursive_Inorder(ptr);
cout << endl;
cout << "递归后序遍历:";
Recursive_Postorder(ptr);
cout << endl;
cout << "层次遍历:";
Level_Order(ptr);
cout << endl;
cout << "非递归前序:";
iter_Preorder(ptr);
cout << endl;
cout << "非递归中序:";
iter_Inorder(ptr);
cout << endl;
cout << "非递归后序:";
iter_Postorder(ptr);
cout << endl;
cout << "节点个数:";
cout << countTree(ptr)<<endl;
cout << "树的高度";
cout << treeHeight(ptr);
return 0;
}
结果:
参考的几个博客
http://blog.youkuaiyun.com/fansongy/article/details/6798278
http://blog.youkuaiyun.com/zhaoxianyong/article/details/7165386
http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html
http://blog.youkuaiyun.com/cxllyg/article/details/7520037
http://blog.youkuaiyun.com/lalor/article/details/7626854
已知前序和中序 求后序的算法
http://www.cr173.com/html/18891_1.html