二叉树的相关节点计算
1、二叉树的创建、遍历、删除
代码如下:
#include "stdafx.h"
#include<iostream>
using namespace std;
struct BitNode
{
int data;
BitNode *lchild;
BitNode *rchild;
};
void CreateTree(BitNode* &T)//这里传递的只能是指针,在这里如果不加上&的话,会出问题的,递归到最后回来的
{ //会是T=NULL这个地方还需要不断理解
int a;
cin>>a;
if(a==8)//为空子树,这里定义
{
T=NULL;
return;
}
T=new BitNode;//这个就是必须用到指针的地方,而且只能是前序遍历,没有树根,哪里来的子树
T->data=a; //记得将左右孩子初始化+()
CreateTree(T->lchild);
CreateTree(T->rchild);
}
void PreOrderTraverse(BitNode *T)
{
if(T)
{
cout<<T->data;
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BitNode *T)
{
if(T)
{
InOrderTraverse(T->lchild);
cout<<T->data;
InOrderTraverse(T->rchild);
}
}
void PostOrderTraverse(BitNode *T)
{
if(T)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout<<T->data;
}
}
void DeleteTree(BitNode *T)//只能用后序遍历
{
if(T)
{
if(T->lchild)DeleteTree(T->lchild);
if(T->rchild)DeleteTree(T->rchild);
cout<<T->data;
delete T;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
BitNode *T=NULL;
CreateTree(T);
PreOrderTraverse(T);
cout<<'\n';
InOrderTraverse(T);
cout<<'\n';
PostOrderTraverse(T);
cout<<'\n';
DeleteTree(T);
return 0;
}
输出:
0 1 8 8 2 3 8 8 8
0123
1032
1320
1320请按任意键继续. . .
总结:
(1)当形参需要new来返回的时候,用指针,而且用引用指针,如 int* &a; 否则会出问题,,也就是说指针指向的内容也需要绑定??值得研究??
理解为:传递指针,形参执行构造函数,然而只有用引用时,才能改变原来指针的内容,故为指针 引用。
(2)树的建立只能用前序建立法,因为只有当根创建了,子树才能建立
(3)树的删除必须用后序遍历,只有子树删除了,根才能够删除
(4)示例化对象时,最好调用默认构造函数进行初始化,当使用new的时候会调用系统默认构造函数帮你进行初始化,这就是使用new的一个好处。
(5)也就是说,new能够动态分配内存,还能够调用系统默认构造函数进行初始化,只需要加上()即可。
(6)传递指针的时候,要初始化指针,因为执行复制构造函数。
1.1、前序、中序、后序遍历的非递归实现
(1)前序的非递归实现,利用一个堆栈,每一次处理,打印本节点,将右孩子压入堆栈,指针指向左节点,循环while
(2)中序遍历的非递归实现,每一次处理,先压入右节点,再压入本节点(标记处理过),指向左孩子,while循环,直到左边遍历完毕
循环出来之后,while循环不断出堆栈,若出来的点已经被访问过,则打印该点,否则,就是原来的右节点,出栈,调用上面的函数。感觉需要跳转的样子。
解决办法:同样只要存储自己,出栈的时候只需要将右节点做处理即可。也就是判断若有右孩子,则跳出,进入do while
(3)后序遍历需要压入的同样有两个,先压入自己(处理过),再压入右节点,指向左节点
解决办法:书上的方法是,利用在两个循环外面做一个do while 实现跳转,中间用 flag标志来控制。 另外 不需要压入两个点,只需要压入自己就可以了。判断若上一个处理的点(用p缓存)是自己的右孩子,或者是空的,那么就可以出栈了。
2、统计树节点的个数
int CountNum(BitNode* T)
{
if(T)
{
return( CountNum(T->lchild)+CountNum(T->rchild)+1);
}
else
return 0;
}
思想:
(1)cvte笔试的时候没有做出来,其实是非常简单的,所以还是要多练习
(2)要想求子节点的个数,对于一个小堆,就是返回本生以及做孩子下面的节点树,以及右孩子下面的节点树。
(3)递归主体 返回左孩子+右孩子的+本身(1)
(4)递归出口 若本身为空,返回(0)