二叉树的基本操作
1:创建
2:前序,中序,后序遍历
3:统计结点数
4:统计叶子结点数
5:打印叶子结点
6:计算二叉树的深度
7:按树状打印二叉树
8:复制二叉树
下面是具体代码和解析
#include <stdio.h>
#include<stdlib.h>
typedef char Elemtype;
int countall=0; //存储结点数
int leafcount=0; //存储叶子结点数
int depth=0; //存储二叉树深度
typedef struct node{
Elemtype data;
struct node *lchild,*rchild;
}BiTNode,*BiTtree;
//1:创建二叉树
void createTree(BiTNode **root)
{
Elemtype data;
scanf("%c",&data);
if(data == '#')
{
(*root)=NULL;
}
else
{
*root = (BiTNode *)malloc(sizeof(BiTNode));
if((*root) == NULL)
{
printf("分配空间失败!\n");
exit(0);
}
(*root)->data = data;
createTree(&((*root)->lchild));
createTree(&((*root)->rchild));
}
}
//或
//void creatBiTree(BiTtree *root){
// Elemtype ch;
// scanf("%c",&ch);
// if(ch == '@'){
// (*root)=NULL;
// } else
// {
// *root = (BiTNode *)malloc(sizeof(BiTNode));
// if((*root) == NULL)
// {
// printf("分配空间失败!\n");
// exit(0);
// }
// (*root)->data = ch;
// creatBiTree(&((*root)->lchild));
// creatBiTree(&((*root)->rchild));
// }
//}
//2:先序遍历
void preOrder(BiTtree root){
if(root!=NULL){
printf("%c",root->data);
preOrder(root->lchild);
preOrder(root->rchild);
}
}
//2:中序遍历
void inOrder(BiTtree root){
if(root!=NULL){
inOrder(root->lchild);
printf("%c",root->data);
inOrder(root->rchild);
}
}
//3:后序遍历
void postOrder(BiTtree root){
if(root!=NULL){
postOrder(root->lchild);
postOrder(root->rchild);
printf("%c",root->data);
}
}
//4:统计结点数
void countAll(BiTtree root){
if(root!=NULL){
countall++;
countAll(root->lchild);
countAll(root->rchild);
}
}
//5:统计叶子结点 方法一
void leafCount1(BiTtree root){
if(root!=NULL){
if(root->lchild==NULL&&root->rchild==NULL)leafcount++;
leafCount1(root->lchild);
leafCount1(root->rchild);
}
}
//6:统计叶子节点 方法二:分治算法,空0,1个节点返回1,否则左右叶子结点相加
int leafCount2(BiTtree root){
int hl,hr;
if(root==NULL)
return 0;
else if((root->lchild==NULL)&&(root->rchild==NULL))return 1;
else{
hl=leafCount2(root->lchild);
hr=leafCount2(root->rchild);
}
return hl+hr;
}
//7:打印叶子结点
void printLeaf(BiTtree root){
if(root!=NULL){
if((root->lchild==NULL)&&(root->rchild==NULL))
printf("%c",root->data);
printLeaf(root->lchild);
printLeaf(root->rchild);
}
}
//8:计算二叉树的深度(方法一):后序遍历求深度,递归
int bitreeDepth1(BiTtree root){
int hl,hr;
if(root==NULL)return 0;
else if (root!=NULL){
hl=bitreeDepth1(root->lchild);
hr=bitreeDepth1(root->rchild);
}
return hl>hr?hl+1:hr+1;
}
//9:计算二叉树的深度(方法二):
//前序遍历(二叉树的深度为结点层次的最大值)设根结点为第一层的结点,所有h层结点的左右孩子结点在h+1层,故可以遍历每个节点的层次,其中最大值是二叉树的高度。
void bitreeDepth2(BiTtree root,int h){
if(root!=NULL){
if(h>depth) depth=h;
bitreeDepth2(root->lchild,h+1);
bitreeDepth2(root->rchild,h+1);
}
}
//10:按树状打印二叉树
//二叉树的横向显示应是竖向显示的90度旋转
//采用‘逆中序’遍历,所以横向显示算法为先右子树,再根结点,再左子树的RDL结构
//输出格式里,结点的左右位置与结点的层深有关,故算法中设置了一个表示当前根结点层深的参数
//来控制输出结点的左右位置,每当递归进层时深度加1。这些操作应在访问根结点时实现
void printBitree(BiTtree root,int h){
if(root!=NULL){
printBitree(root->rchild, h+1);
for(int i=0;i<h;i++)
printf("--");
printf("%c\n",root->data);
printBitree(root->lchild, h+1);
}
}
BiTtree CopyBTree(BiTtree root){
BiTtree p,lchild,rchild;
if(root==NULL)
return NULL;
lchild=CopyBTree(root->lchild);
rchild=CopyBTree(root->rchild);
p=(BiTtree)malloc(sizeof(BiTNode));
p->data=root->data;
p->lchild=root->lchild;
p->rchild=root->rchild;
return p;
}
int main(){
BiTNode *root;
printf("请输入二叉树数据:(#代表NULL)\n");
createTree(&root);
printf("先序遍历结果:\n");
preOrder(root);
printf("\n中序遍历结果:\n");
inOrder(root);
printf("\n后序遍历结果:\n");
postOrder(root);
countAll(root);
printf("\n结点总数为:%d\n",countall);
leafCount1(root);
printf("\n叶子结点数为(法一):%d\n",leafcount);
int a=leafCount2(root);
printf("\n叶子结点数为(法二):%d\n",a);
bitreeDepth2(root, 1);
printf("\n树的高度(法一):%d\n",bitreeDepth1(root));
printf("\n树的高度(法二):%d\n",depth);
if(CopyBTree(root))
printf("\n复制二叉树成功!\n");
else
printf("\n复制失败!\n");
printf("\n叶子结点是:\n");
printLeaf(root);
printf("\n树状打印二叉树\n");
printBitree(root, 1);
}
运行结果:
当听完讲解你或许懂了,但其实不自己亲手写一遍,是不会发现其中的问题的。
比如创建二叉树时为什么要用指针的指针?
递归的过程你是否能写得出来?
具体的问题我会在下篇《二叉树操作出现的问题》提到。