C# · 12月 19, 2021

二叉树的基本操作(C语言)

要介绍二叉树的基本操作,首先介绍一下二叉树的结点:

typedef struct node

{

char data;

struct node *lchild;

struct node *rchild;

}BiTNode;

 包括该结点的值、指向左孩子的指针和指向右孩子的指针。

1.先序构造二叉树

BiTNode *creatBiTree()

{

char k;

scanf(“%c”,&k);

if(k==’#’)

return NULL;

BiTNode *T=(BiTNode *)malloc(sizeof(BiTNode));

T->data=k;

T->lchild=creatBiTree();

T->rchild=creatBiTree();

return T;

}

先序构造采用递归的算法,构造完父结点再去构造父结点的左孩子,构造完父结点的左孩子再去构造父结点的右孩子,最后返回根节点的地址。这样无论哪个节点,构造的顺序都是父结点->左孩子->右孩子,保证按照先序的顺序构造二叉树。

2.二叉树的遍历

1)先序遍历

void xianxu(BiTNode *T)

{

if(T)

{

printf(“%2c”,T->data);

xianxu(T->lchild);

xianxu(T->rchild);

}

}

2)中序遍历

void zhongxu(BiTNode *T)

{

if(T)

{

zhongxu(T->lchild);

printf(“%2c”,T->data);

zhongxu(T->rchild);

}

}

3)后序遍历

void houxu(BiTNode *T)

{

if(T)

{

houxu(T->lchild);

houxu(T->rchild);

printf(“%2c”,T->data);

}

}

三种遍历算法都使用了递归,仅仅是访问结点内容这部分代码的位置不同。先序遍历肯定要先访问这个结点的内容,中序遍历肯定是在访问了该结点的左子树后再访问这个结点的内容,后序遍历肯定是左右子树都访问完再访问这个结点的内容。

3.统计叶子结点的个数

int countLeaf(BiTNode *T)

{

if(T==NULL)

return 0;

else if(T->lchild==NULL&&T->rchild==NULL)

return 1;

else

return countLeaf(T->lchild)+countLeaf(T->rchild);

}

 如果一棵树为空树,肯定一个叶子结点也没有,返回0;如果一个结点的左孩子为空右孩子也为空,那么这个结点一定是叶子结点,返回1;如果是其他的情况,叶子结点的个数无非是左子树叶子结点的个数+右孩子叶子结点的个数。层层递归,最后返回的就是二叉树叶子结点的个数。

4.计算二叉树的深度

int countDepth(BiTNode *T)

{

if(T==NULL)

return 0;

else if(T->lchild==NULL&&T->rchild==NULL)

return 1;

else

{

int depth1=countDepth(T->lchild)+1;

int depth2=countDepth(T->rchild)+1;

return depth1>depth2?depth1:depth2;

}

}

如果一棵树为空树,则没有深度可言,返回0;如果一个结点的左孩子为空右孩子也为空,则该结点肯定是叶子结点,该结点的下面不再有结点,对该结点而言深度就是1; 如果是其他情况,则要先求左子树的深度和右子树的深度,左子树的深度+1就是该结点去掉右子树时的深度,右子树的深度+1就是该结点去掉左子树时的深度,深度肯定取大的,所以返回的是左子树深度+1和右子树深度+1中大的那一个。

5.销毁一棵二叉树

void destroy(BiTNode *T)

{

if(T)

{

destroy(T->lchild);

destroy(T->rchild);

free(T);

}

}

对于一个结点,先销毁左子树,再销毁右子树,最后释放该结点的内存。注意一定要最后释放该结点的内存,因为左子树和右子树都是需要该结点中指向左孩子的指针和指向右孩子的指针索引的,释放了该结点的内存就找不到左子树和右子树了,就造成了内存泄漏。 

写好上述操作函数之后,下面在主函数中进行测试:

int main()

{

printf(“先序构造一棵二叉树(左/右孩子为空用’#’表示):”);

BiTNode *T=creatBiTree();

printf(“先序遍历这棵二叉树:”);

xianxu(T);

printf(“n”);

printf(“中序遍历这棵二叉树:”);

zhongxu(T);

printf(“n”);

printf(“后序遍历这棵二叉树:”);

houxu(T);

printf(“n”);

printf(“这棵树叶子结点的个数:%dn”,countLeaf(T));

printf(“这棵树的深度:%dn”,countDepth(T));

destroy(T);

return 0;

}

测试结果: