二叉树的先序建立是一种二叉树的构建方式,其优缺点如下:
优点:
-
构建简单:二叉树的先序建立方法比较容易理解,只需要按照先序遍历的顺序依次创建每个节点即可。
-
时间复杂度低:使用递归的方式进行先序建立二叉树,其时间复杂度为O(n),n为二叉树节点数。
缺点:
-
不具有唯一性:由于没有规定左子树和右子树的分界点,不同的节点顺序可能会形成不同的二叉树结构。因此,相同的节点集合,可能有多种不同的二叉树先序遍历序列。
-
对于某些特定的二叉树,先序建立可能容易导致树高过高,从而影响操作效率和空间利用率。
综上所述,二叉树的先序建立方法适用于一些简单的二叉树构建,但是由于不具有唯一性以及可能存在树高过高等问题,一般情况下在实际应用中会采用其他更加合适的构建方式。
本代码输入建立二叉树的先序建立棵二叉树,然后执行二叉树复制、求深度、先序、中序和后序遍历操作并输出结果
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct BiTNode
{
char data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
void PreCreateBiTree(BiTree *T);
bool isBiTreeEmpty(BiTree T);
void PreOrderTraverse(BiTree T);
void InOrderTraverse(BiTree T);
void PostOrderTraverse(BiTree T);
void Copy(BiTree T, BiTree *NewT);
int Depth(BiTree T);
int NodeCount(BiTree T);
void DestroyBiTree(BiTree T);
int main(int argc, char *argv[])
{
BiTree T = NULL;
printf("请输入二叉树先序节点序列,空位置用'#'代替.\n");
PreCreateBiTree(&T);
getchar();
printf("先序遍历: ");
PreOrderTraverse(T);
printf("\n");
printf("中序遍历: ");
InOrderTraverse(T);
printf("\n");
printf("后序遍历: ");
PostOrderTraverse(T);
printf("\n");
printf("树T节点个数为: %d\n", NodeCount(T));
printf("树T深度为: %d\n", Depth(T));
//复制新树并遍历
BiTree NewT = (BiTree)malloc(sizeof(BiTNode));
Copy(T, &NewT);
printf("\n");
printf("NewTree:\n");
printf("先序遍历: ");
PreOrderTraverse(NewT);
printf("\n");
printf("中序遍历: ");
InOrderTraverse(NewT);
printf("\n");
printf("后序遍历: ");
PostOrderTraverse(NewT);
printf("\n");
printf("树NewT节点个数为: %d\n", NodeCount(NewT));
printf("树NewT深度为: %d\n", Depth(NewT));
//销毁二叉树T和NewT
DestroyBiTree(T);
DestroyBiTree(NewT);
return 0;
}
//按先序输入建立二叉树(注意双重指针)
void PreCreateBiTree(BiTree *T)
{
char ch;
scanf("%c", &ch);
if(ch == '#') //递归结束,建空树
{
*T = NULL;
} //of if
else //递归建立二叉树
{
*T = (BiTree)malloc(sizeof(BiTNode)); //生成根节点
(*T)->data = ch; //根节点赋值为ch
PreCreateBiTree(&((*T)->lchild)); //递归建立左子树
PreCreateBiTree(&((*T)->rchild)); //递归建立右子树
} //of else
} //of PreCreateBiTree()
//二叉树判空
bool isBiTreeEmpty(BiTree T)
{
if(T == NULL)
{
return true;
}//of if
return false;
}// of isBiTreeEmpty()
//先序遍历二叉树
void PreOrderTraverse(BiTree T)
{
if(isBiTreeEmpty(T))
{
return;
}//of if
printf("%c ", T->data);
PreOrderTraverse(T->lchild); //递归遍历左子树
PreOrderTraverse(T->rchild); //递归遍历右子树
} //of PreOrderTraverse()
//中序遍历二叉树
void InOrderTraverse(BiTree T)
{
if(isBiTreeEmpty(T))
{
return;
}//of if
InOrderTraverse(T->lchild); //递归遍历左子树
printf("%c ", T->data);
InOrderTraverse(T->rchild); //递归遍历右子树
} //of InOrderTraverse()
//后序遍历二叉树
void PostOrderTraverse(BiTree T)
{
if(isBiTreeEmpty(T))
{
return;
}//of if
PostOrderTraverse(T->lchild); //递归遍历左子树
PostOrderTraverse(T->rchild); //递归遍历右子树
printf("%c ", T->data);
} //of PostOrderTraverse()
//复制二叉树(注意双重指针)
void Copy(BiTree T, BiTree *NewT)
{
if(isBiTreeEmpty(T))
{
*NewT = NULL; //如果为空树递归结束
return;
}//of if
else
{
*NewT = (BiTree)malloc(sizeof(BiTNode));
(*NewT)->data = T->data; //复制根节点
Copy(T->lchild, &((*NewT)->lchild)); //递归复制左子树
Copy(T->rchild, &((*NewT)->rchild)); //递归复制右子树
}//of else
} //of Copy()
//计算二叉树的深度
int Depth(BiTree T)
{
if(isBiTreeEmpty(T)) //如果为空树,返回深度为0,递归结束
{
return 0;
} //of if
else
{
int m = Depth(T->lchild); //递归计算左子树的深度记为m
int n = Depth(T->rchild); //递归计算右子树的深度记为n
return (m > n) ? (m + 1) : (n + 1); //二叉树的深度为m与n较大者再加1
} //of else
} //of Depth()
int NodeCount(BiTree T)
{
if(isBiTreeEmpty(T)) //如果为空树,则节点个数为0,递归结束
{
return 0;
} //of if
else //否则节点个数为左子树节点数 加 右子树节点数再加 根节点1
{
return NodeCount(T->lchild) + NodeCount(T->rchild) + 1;
} //of else
} //of NodeCount()
//销毁二叉树
void DestroyBiTree(BiTree T)
{
if(!isBiTreeEmpty(T))
{
DestroyBiTree(T->lchild);
DestroyBiTree(T->rchild);
free(T);
} //of if
} //of DestroyBiTree()
输入先序:ABC##DE#G##F###
运行结果:
与前一篇文章插入节点操作一样,Copy()函数也需要用到双重指针