二叉树的二叉链表结点结构定义
typedef struct BiTNode/*结点结构*/
{
char data;//结点数据
struct BiTNode* lchild, * rchild;//左孩子,右孩子。
}BiTNode,*BiTree;
1.前序遍历
前序遍历的规则时若二叉树为空,则空操作返回,否则 先访问根节点,然后前序遍历左子树,在前序遍历右子树,如图:
这个二叉树的前序遍历就为 ABDGHCEIF。
void PreTraverse(BiTree T)//前序遍历
{
if (T == NULL)
return;
else
{
//先打印头结点,然后在先序遍历左孩子,最后在先序遍历右孩子
printf("%c ", T->data);
PreTraverse(T->lchild);
PreTraverse(T->rchild);
}
}
2.中序遍历
规则是若树为空则返回,否者从根节点开始(这里不是先访问根节点),中序遍历根节点的左子树,然后在访问根节点,最后中序遍历右子树,就还是上面那个图,他的中序遍历为: GDHBAEICF
void InTraverse(BiTree T)//中序遍历
{
if (T == NULL)
return;
else
{
//先中序遍历左孩子,然后在打印结点,最后在中序遍历右孩子。
InTraverse(T->lchild);
printf("%c ", T->data);
InTraverse(T->rchild);
}
}
3.后序遍历
规则是若树为空,则空返回,否则从左到右,先叶子后结点的方式遍历访问左右子树,最后访问根节点 上图的后序遍历为:GHDBIEFCA
void PostTraverse(BiTree T)//后序遍历
{
if (T == NULL)
return;
else
{
//先后序遍历左孩子,然后后序遍历右孩子,最后在打印结点。
PostTraverse(T->lchild);
PostTraverse(T->rchild);
printf("%c ", T->data);
}
}
4.建立二叉树
普通的树是没有将那些空指针表示出来,这时我们可以对普通的二叉树进行扩展,变成扩展二叉树的样子,我们可以将空指针引出一个虚结点,其值为一特定值,例如 ‘#’。这时我们的前序遍历就会变成:AB#D##C##.
这样我们就可以将先序遍历序列AB#D##C##用键盘输入:
- 前序输入
/*按前序输入二叉树中结点的值*/
/* ‘#’表示空树,构造二叉树链表表示二叉树T */
void PreCreateBiTree(BiTree& T)
{
char ch;
scanf_s("%c", &ch);
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
if (!T)
exit(0);
T->data = ch;
PreCreateBiTree(T->lchild);
PreCreateBiTree(T->rchild);
}
}
2.后序输入
还是这个扩展二叉树,他的后序遍历为:###DB##CA。
如果我们还是向上一个程序那样,只将他的访问顺序改变,而且还是先判断 ch 是否等于 “#” 的话,我们会在开头就结束程序,根本无法建立二叉树。
这时我们观察 后序遍历的结果:###DB##CA,我们从后往前看,首先为根节点,然后再是右节点,然后在左节点。这样的话第一个就不会为 “#” 就可以用后序输入来建立二叉树
/*后序输入,创建二叉树*/
void PostCreateBiTree(BiTree& T,char a[])
{
static int count = strlen(a);//用静态变量来建立count;
char ch = a[count - 1];//从后往前
count--;
if (ch == '#')
{
T = NULL;
}
else
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = ch;
PostCreateBiTree(T->rchild, a);
PostCreateBiTree(T->lchild, a);
}
}
5.复制树
void copy(BiTree T, BiTree& newT)//复制树
{
if (T = NULL)
return;
else
{
newT = (BiTree)malloc(sizeof(BiTNode));
if (!newT)
exit(0);
newT->data = T->data;
copy(T->lchild, newT->lchild);
copy(T->rchild, newT->rchild);
}
}
6.求深度
求深度,我们可以用深搜来解决
void dfs(BiTree T,int m)//深搜来求深度,m用来记录当前深度
{
if (T == NULL)
{
if (max < m)//用max来记录最大的深度
max = m;
return;
}
else
{
/* 向下遍历,m就加一*/
dfs(T->lchild,m+1);
dfs(T->rchild,m+1);
}
}
7.求结点个数
求结点个数同样可以使用深搜来解决,代码如下:
void dfsnode(BiTree T,int ans)//ans为当前的节点数
{
if (T == NULL)
return;
else
{
/*向下遍历,ans++*/
ans++;
dfsnode(T->lchild);
dfsnode(T->rchild);
}
}
节点计算题
根据完全二叉树的定义,我们可以知道 当结点个数为偶数的时候,度为1的节点个数为 1,即n1=1,但结点个数为奇数的时候,度为1的节点个数为0,即n1=0;然后结点个数为 n=n1+n2+n0;其中n2为度为2的结点,n0叶子结点 ,所以n0=n2+1;
所以这题中 n=768,为偶数,所以 n1=1 ,所以 n=1+2*n0-1=768;
所以 n0=384;
根据完全二叉树,所以我们可以计算出深度为6的最多结点个数,
n=2^6-1=63,根据题意完全二叉树的第六层有 8个叶子结点,所以我们可以判断,第六层可能为最后一层,或者为倒数第二层,即最后一层可能为第7层,然后我们再看题中为求最多节点个数,所以我们可以默认为有7层,
因为完全二叉树的第六层有 m=2^(6-1)=32 个结点,其中有8个叶子结点,其余都有儿子结点,因为要最多所以 k=(32-8)*2+63=111个结点。