首先,什么是二叉树?
二叉树是一个根结点只有左右子树就叫二叉树;如下图就是一个普通的二叉树:
树有许多的表示方法,这里二叉树用孩子表示法。
之前关于链表我们知道,用头指针来表示单链表,这里用相同的思想:用根结点指针来表示一棵树;
这里先用递归的思想来完成二叉树的先序、中序、后序,层序这里需要借助之前的顺序队列来完成;
代码实现:
bin_tree.h
#pragma once
#include <stdio.h>
typedef char TreeNodeType;
//使用孩子表示法来表示一棵树
typedef struct TreeNode {
TreeNodeType data;
struct TreeNode* lchild;
struct TreeNode* rchild;
}TreeNode;
//对于链表来说,使用链表的头节点指针来表示一个链表
//对于二叉树来说,使用跟结点的指针来表示一棵树
void TreeInit(TreeNode** pRoot);
void TreePreOrder(TreeNode* root);
void TreeInOrder(TreeNode* root);
void TreePostOrder(TreeNode* root);
void TreeLevelOrder(TreeNode* root);
//输入一个数组(数组中的每个元素就是树上的结点),根据数组的内容
//构建出一颗树,数组中元素的内容符合树的先序遍历结果(包含所有空结点)
TreeNode* TreeCreate(TreeNodeType arry[],size_t size,char null_node);
//求二叉树中结点的个数
size_t TreeSize(TreeNode* root);
//求二叉树中叶子结点的个数
size_t TreeLeafSize(TreeNode* root);
//求二叉树中第K层结点的个数
size_t TreeKLevelSize(TreeNode* root,int K);
//求二叉树的高度/深度
size_t TreeHeight(TreeNode* root);
void TreeDestroy(TreeNode* root);
//在二叉树中查找结点,给定一个数值,求出对应结点的指针
//假设二叉树中的结点是不重复的
TreeNode* TreeFind(TreeNode* root,TreeNodeType to_find);
//求出child的父节点
TreeNode* FindParent(TreeNode* root,TreeNode* child);
//求出当前节点的左子树和右子树
TreeNode* LChild(TreeNode* node);
TreeNode* RChild(TreeNode* node);
bin_tree.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "bin_tree.h"
#include "seqqueue.h"
#include "seqstack.h"
TreeNode* CreateTreeNode(TreeNodeType value){
TreeNode* new_node = (TreeNode*)malloc(sizeof(TreeNode));
new_node->data = value;
new_node->lchild = NULL;
new_node->rchild = NULL;
return new_node;
}
void DestroyTreeNode(TreeNode* node){
free(node);
}
void TreeInit(TreeNode** pRoot){
if(pRoot == NULL){
//非法输入
return;
}
*pRoot = NULL;
return;
}
void TreePreOrder(TreeNode* root){
if(root == NULL){
//空树
return;
}
//先访问根结点,访问即打印
printf("%c ",root->data);
//然后递归的遍历左子树
TreePreOrder(root->lchild);
//最后在递归的遍历右子树
TreePreOrder(root->rchild);
return;
}
void TreeInOrder(TreeNode* root){
if(root == NULL){
//空树
return;
}
//先递归的遍历左子树
TreeInOrder(root->lchild);
//再访问根结点
printf("%c ",root->data);
//最后递归的遍历右子树
TreeInOrder(root->rchild);
return;
}
void TreePostOrder(TreeNode* root){
if(root == NULL){
//空树
return;
}
//先递归的遍历左子树
TreePostOrder(root->lchild);
//再递归的遍历右子树
TreePostOrder(root->rchild);
//最后访问根结点
printf("%c ",root->data);
return;
}
void TreeLevelOrder(TreeNode* root){
if(root == NULL){
//空树
return;
}
SeqQueue queue;
SeqQueueInit(&queue);
SeqQueuePush(&queue,root);
while(1){
SeqQueueType front;
int ret = SeqQueueFront(&queue,&front);
if(ret == 0){
//如果队列取队首元素失败,说明队列为空
//如果队列为空就说明遍历结束了
break;
}
//访问树中的元素,打印当前值
printf("%c ",front->data);
//把当前队首元素出队列
SeqQueuePop(&queue);
//把当前元素的左右子树入队列
if(front->lchild != NULL){
SeqQueuePush(&queue,front->lchild);
}
if(front->rchild != NULL){
SeqQueuePush(&queue,front->rchild);
}
}
return;
}
TreeNode* _TreeCreate(TreeNodeType arry[],size_t size,size_t* index,TreeNodeType null_node){
if(index == NULL){
//非法输入
return NULL;
}
if(*index >= size){
return NULL;
}
if(arry[*index] == null_node){
return NULL;
}
TreeNode* new_node = CreateTreeNode(arry[*index]);
++(*index);
new_node->lchild = _TreeCreate(arry,size,index,null_node);
++(*index);
new_node->rchild = _TreeCreate(arry,size,index,null_node);
return new_node;
}
TreeNode* TreeCreate(TreeNodeType arry[],size_t size,char null_node){
//表示当前取数组中的那个元素
size_t index = 0;
return _TreeCreate(arry,size,&index,null_node);
}
TreeNode* TreeClone(TreeNode* root){
if(root == NULL){
//空树
return NULL;
}
//按照先序方式来遍历
TreeNode* new_node = CreateTreeNode(root->data);
new_node->lchild = TreeClone(root->lchild);
new_node->rchild = TreeClone(root->rchild);
return new_node;
}
//销毁的过程中一定要保证左右子树能够被正确找到,所有按照后序的方式来销毁
void TreeDestroy(TreeNode* root){
if(root == NULL){
//空树
return;
}
//按照后序遍历的方式来销毁整个树
TreeDestroy(root->lchild);
TreeDestroy(root->rchild);
DestroyTreeNode(root);
return;
}
//方法一
void _TreeSize(TreeNode* root,size_t* size){
if(root == NULL){
//空树
return;
}
//按照前序的方式遍历,这里的访问是++
++(*size);
_TreeSize(root->lchild,size);
_TreeSize(root->rchild,size);
}
size_t TreeSize(TreeNode* root){
size_t size = 0;
_TreeSize(root,&size);
return size;
}
//方法二
size_t TreeSize(TreeNode* root){
if(root == NULL){
//空树
return 0;
}
return 1 + TreeSize(root->lchild) + TreeSize(root->rchild);
}
size_t TreeLeafSize(TreeNode* root){
if(root == NULL){
//空树
return 0;
}
if(root->lchild == NULL && root->rchild == NULL){
//root是叶子结点
return 1;
}
//root不是叶子结点
return TreeLeafSize(root->lchild) + TreeLeafSize(root->rchild);
}
size_t TreeKLevelSize(TreeNode* root,int K){
if(root == NULL || K < 1){
//root等于空是空树,K<1是非法输入
return 0;
}
if(K == 1){
return 1;
}
return TreeKLevelSize(root->lchild ,K - 1) + TreeKLevelSize(root->rchild,K - 1);
}
size_t TreeHeight(TreeNode* root){
if(root == NULL){
//空树
return 0;
}
if(root->lchild == NULL && root->rchild == NULL){
return 1;
}
size_t lheight = TreeHeight(root->lchild);
size_t rheight = TreeHeight(root->rchild);
return 1 + (lheight > rheight ? lheight : rheight);
}
TreeNode* TreeFind(TreeNode* root,TreeNodeType to_find){
if(root == NULL){
//空树
return NULL;
}
if(root->data == to_find){
return root;
}
TreeNode* lresult = TreeFind(root->lchild,to_find);
TreeNode* rresult = TreeFind(root->rchild,to_find);
//不等于空,说明找到了
return lresult != NULL ? lresult : rresult;
}
TreeNode* FindParent(TreeNode* root,TreeNode* child){
if(root == NULL || child == NULL){
return NULL;
}
if(root->lchild == child || root->rchild == child){
return root;
}
TreeNode* lresult = FindParent(root->lchild,child);
TreeNode* rresult = FindParent(root->rchild,child);
return lresult != NULL ? lresult : rresult;
}
TreeNode* LChild(TreeNode* node){
if(node == NULL){
return NULL;
}
return node->lchild;
}
TreeNode* RChild(TreeNode* node){
if(node == NULL){
return NULL;
}
return node->rchild;
}