普通链式二叉树(2)
实现代码:
因为其中一部分要使用到队列来实现层序遍历,所以要用到队列的代码
Queue.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef struct BinaryTreeNode* QDateType;
typedef struct QueueNode
{
struct QueueNode* next;
QDateType date;
}QNode;
typedef struct Queue
{
QNode * head;
QNode * tail;
int size;
}Que;
//队列初始化
void QueueInit(Que* pq);
//队列销毁
void QueueDestroy(Que* pq);
//入队(尾部插入数据)
void QueuePush(Que* pq,QDateType x);
//出队(头部删除数据)
void QueuePop(Que* pq);
//获得队头节点的值
QDateType QueueFront(Que* pq);
//获得队尾节点的值
QDateType QueueBack(Que* pq);
//判断队列是否为空
bool QueueEmpty(Que* pq);
//获得队列的长度(有效元素个数)
int QueueSize(Que* pq);
Tree.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <math.h>
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate1(BTDataType* a, int n, int* pi);
BTNode* BinaryTreeCreate2(BTDataType* a, int* pi);
// 二叉树销毁
void BinaryTreeDestroy1(BTNode** root);
void BinaryTreeDestroy2(BTNode* root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root);
Queue.c
#include "Queue.h"
//队列初始化
void QueueInit(Que* pq)
{
assert(pq);
pq->head=pq->tail=NULL;
pq->size=0;
}
//队列销毁
void QueueDestroy(Que* pq)
{
assert(pq);
QNode* cur=pq->head;
while(cur)
{
QNode *next=cur->next;
free(cur);
cur=next;
}
pq->head=pq->tail=NULL;
pq->size=0;
}
//入队(尾部插入数据)
void QueuePush(Que* pq,QDateType x)
{
assert(pq);
QNode *newnode=(QNode*) malloc(sizeof (QNode));
if(newnode==NULL)
{
perror("malloc failed");
exit(-1);
}
newnode->next=NULL;
newnode->date=x;
if(pq->tail==NULL)
{
pq->head=pq->tail=newnode;
}
else
{
pq->tail->next=newnode;
pq->tail=newnode;
}
pq->size++;
}
//出队(头部删除数据)
void QueuePop(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if(pq->head->next==NULL)
{
free(pq->head);
pq->head=pq->tail=NULL;
}
else
{
QNode *next=pq->head->next;
free(pq->head);
pq->head=next;
}
pq->size--;
}
//获得队头节点的值
QDateType QueueFront(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->date;
}
//获得队尾节点的值
QDateType QueueBack(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->date;
}
//判断队列是否为空
bool QueueEmpty(Que* pq)
{
assert(pq);
return pq->head==NULL;
}
//获得队列的长度(有效元素个数)
int QueueSize(Que* pq)
{
assert(pq);
return pq->size;
}
Tree.c
#include "Tree.h"
#include "Queue.h"
//通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate1(BTDataType* a, int n, int* pi)
{
if(a[(*pi)]=='#')
{
(*pi)++;
return NULL;
}
BTNode * root=(BTNode *) malloc(sizeof(BTNode));
root->data=a[(*pi)++];
root->left= BinaryTreeCreate1(a,n,pi);
root->right= BinaryTreeCreate1(a,n,pi);
return root;
}
BTNode* BinaryTreeCreate2(BTDataType* a, int* pi)
{
if(a[(*pi)]=='#')
{
(*pi)++;
return NULL;
}
BTNode * root=(BTNode *) malloc(sizeof(BTNode));
root->data=a[(*pi)++];
root->left= BinaryTreeCreate2(a,pi);
root->right= BinaryTreeCreate2(a,pi);
return root;
}
// 二叉树销毁
void BinaryTreeDestroy1(BTNode** root)
{
if(*root==NULL)
return ;
BinaryTreeDestroy1((*root)->left);
BinaryTreeDestroy1((*root)->right);
free(*root);
*root=NULL;
}
void BinaryTreeDestroy2(BTNode* root)
{
if(root==NULL)
return ;
BinaryTreeDestroy2(root->left);
BinaryTreeDestroy2(root->right);
free(root);
//*root=NULL;
//在main函数调用完这个函数之后手动将root置空
}
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
return root==NULL ? 0
: BinaryTreeSize(root->left)
+ BinaryTreeSize(root->right)+1;
}
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if(root==NULL)
return 0;
if(root->right==NULL && root->left==NULL)
return 1;
return BinaryTreeLeafSize(root->left)+ BinaryTreeLeafSize(root->right);
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
assert(k>0);
if(root==NULL)
return 0;
if(k==1)
return 1;
return BinaryTreeLevelKSize(root->left,k-1)+
BinaryTreeLevelKSize(root->right,k-1);
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if(root==NULL)
return NULL;
if(root->data==x)
return root;
BTNode *ret=NULL;
ret= BinaryTreeFind(root->left,x);
if(ret!=NULL)
return ret;
ret= BinaryTreeFind(root->right,x);
if(ret!=NULL)
return ret;
return NULL;
}
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if(root==NULL)
{
printf("NULL ");
return ;
}
printf("%c",root->data);
BinaryTreePrevOrder(root->left);
BinaryTreePrevOrder(root->right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
if(root==NULL)
{
printf("NULL ");
return ;
}
BinaryTreeInOrder(root->left);
printf("%c",root->data);
BinaryTreeInOrder(root->right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
if(root==NULL)
{
printf("NULL ");
return ;
}
BinaryTreePostOrder(root->left);
BinaryTreePostOrder(root->right);
printf("%c",root->data);
}
// 通过队列进行层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
Que q;
QueueInit(&q);
if(root)
QueuePush(&q,root);
while(!QueueEmpty(&q))
{
BTNode *front= QueueFront(&q);
printf("%c ",front->data);
if(front->left)
QueuePush(&q,front->left);
if(front->right)
QueuePush(&q,front->right);
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
}
//求树的高度
int BinaryTreeHeight(BTNode* root)
{
if(root==NULL)
return 0;
int leftHeight= BinaryTreeHeight(root->left);
int rightHeight= BinaryTreeHeight(root->right);
return leftHeight>rightHeight ? leftHeight+1 : rightHeight+1 ;
//也可以只用下面这句
//return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right))+1;
}
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
Que q;
QueueInit(&q);
if(root)
QueuePush(&q,root);
while(!QueueEmpty(&q))
{
BTNode *front= QueueFront(&q);
if(front==NULL)
break;
QueuePush(&q,front->left);
QueuePush(&q,front->right);
QueuePop(&q);
}
while (!QueueEmpty(&q))
{
BTNode *front= QueueFront(&q);
QueuePop(&q);
if(front!=NULL)
{
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}
补充:
以上代码中包含队列的代码,如对队列疑惑可以看我前面写的队列的博客。此外,以上代码中有部分知识,上一节已经讲过了,讲过的内容有:
(计算一颗树的节点个数)(计算一棵树的叶子节点的个数)(计算一棵树第k层节点个数)(前,中,后序遍历)
这些内容都在上一篇内容里面。
其次就是,这里树的节点存储的数据我设为了char类型,但是有些函数功能需要是int类型的,大家在Tree.h里的typedef char BTDataType;
改成自己想要的类型就好了。
代码解析:
前序遍历数组,构建二叉树
(这个就是比较权威的建树手法了)
//通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate2(BTDataType* a, int* pi)
{
if(a[(*pi)]=='#')
{
(*pi)++;
return NULL;
}
BTNode * root=(BTNode *) malloc(sizeof(BTNode));
root->data=a[(*pi)++];
root->left= BinaryTreeCreate2(a,pi);
root->right= BinaryTreeCreate2(a,pi);
return root;
}
销毁二叉树
// 二叉树销毁
void BinaryTreeDestroy1(BTNode** root)
{
if(*root==NULL)
return ;
BinaryTreeDestroy1((*root)->left);
BinaryTreeDestroy1((*root)->right);
free(*root);
*root=NULL;
}
void BinaryTreeDestroy2(BTNode* root)
{
if(root==NULL)
return ;
BinaryTreeDestroy2(root->left);
BinaryTreeDestroy2(root->right);
free(root);
//*root=NULL;
//在main函数调用完这个函数之后手动将root置空
}
二叉树查找值为x的节点
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if(root==NULL)
return NULL;
if(root->data==x)
return root;
BTNode *ret=NULL;
ret= BinaryTreeFind(root->left,x);
if(ret!=NULL)
return ret;
ret= BinaryTreeFind(root->right,x);
if(ret!=NULL)
return ret;
return NULL;
}
求树的高度
//求树的高度
int BinaryTreeHeight(BTNode* root)
{
if(root==NULL)
return 0;
int leftHeight= BinaryTreeHeight(root->left);
int rightHeight= BinaryTreeHeight(root->right);
return leftHeight>rightHeight ? leftHeight+1 : rightHeight+1 ;
//也可以只用下面这句,换掉前3句,也就是int leftHeight开始的3句就可以去掉。
//return fmax(BinaryTreeHeight(root->left), BinaryTreeHeight(root->right))+1;
}
层序遍历
// 通过队列进行层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
Que q;
QueueInit(&q);
if(root)
QueuePush(&q,root);
while(!QueueEmpty(&q))
{
BTNode *front= QueueFront(&q);
printf("%c ",front->data);
if(front->left)
QueuePush(&q,front->left);
if(front->right)
QueuePush(&q,front->right);
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
}
判断这个树是不是完全二叉树
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
Que q;
QueueInit(&q);
if(root)
QueuePush(&q,root);
while(!QueueEmpty(&q))
{
BTNode *front= QueueFront(&q);
if(front==NULL)
break;
QueuePush(&q,front->left);
QueuePush(&q,front->right);
QueuePop(&q);
}
while (!QueueEmpty(&q))
{
BTNode *front= QueueFront(&q);
QueuePop(&q);
if(front!=NULL)
{
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}