BT.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef char BTDataType;
typedef struct BinaryTreeNode//二叉树节点
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
typedef BTNode* QueueDataType;//队列节点存储二叉树节点地址,方便层序遍历
typedef struct queue//队列节点
{
QueueDataType _data;
struct queue* next;
}QNode;
typedef struct queueinfo//队列信息记录头尾,大小,传队列信息直接传这个结构体变量(信息找头尾)
{
QNode* phead;
QNode* ptail;
int size;
}QInfo;
//初始化队列
void QueueInit(QInfo* queue);
// 销毁队列
void QueueDestory(QInfo* queue);
//搞个节点
QNode* QueueGetNode(QueueDataType data);
//队列插入数据
void QueueInsert(QInfo* queue, QueueDataType data);
// 队列头部删除数据,并获取它
QueueDataType QueuePop(QInfo* queue);
// 队列判空
int QueueIsEmpty(QInfo* queue);
// 队列大小
int QueueSize(QInfo* queue);
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, /*int n, */int* pi);
// 二叉树销毁
void BinaryTreeDestory(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);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
BT.c
#include"BT.h"
//初始化队列
void QueueInit(QInfo* queue)
{
//因为这个源码是实现二叉树的,用到队列只在一个函数内,所以采用非动态开辟内存方法,而是传入函数内创建好的,进行初始化,而非创建
queue->phead = NULL;
queue->ptail = NULL;
queue->size = 0;
}
//销毁队列
void QueueDestory(QInfo* queue)
{
while (queue->size)//同链表删除
{
QNode* next = queue->phead->next;
free(queue->phead);
queue->phead = next;
queue->size--;
}
}
//搞个节点
QNode* QueueGetNode(QueueDataType data)//因为队列底层是链表(此是不带头),返回搞的节点就行,顺序表得扩容
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
assert(newnode);//扩容失败
newnode->_data = data;
newnode->next = NULL;
return newnode;
}
//队列尾部插入数据
void QueueInsert(QInfo* queue, QueueDataType data)
{
if (queue->size == NULL)
{
queue->ptail = queue->phead = QueueGetNode(data);
}
else
{
queue->ptail->next= QueueGetNode(data);
queue->ptail = queue->ptail->next;
}
queue->size++;
}
//队列头部获取并删除数据
BTNode* QueuePop(QInfo* queue)
{
assert(queue);
BTNode* mid = queue->phead->_data;
QNode* next = queue->phead->next;
free(queue->phead);
queue->phead = next;
queue->size--;
return mid;
}
//队列判空
int QueueIsEmpty(QInfo* queue)
{
assert(queue);
return queue->size == NULL;
}
//返回队列长度
int QueueSize(QInfo* queue)
{
assert(queue);
return queue->size;
}
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, /*int n, */int* pi)//a是数组,pi是数组第几个,需要用指针实时记录
{//n是检查当前建历的节点加上空,与a最后结果pi相等,可不检查
if (a[*pi] == '#')
{
(*pi)++;
return NULL;
}
BTNode* pcur = (BTNode*)malloc(sizeof(BTNode));
pcur->_data = a[(*pi)++];
pcur->_left = BinaryTreeCreate(a, pi);
pcur->_right= BinaryTreeCreate(a, pi);
return pcur;//遍历完字符串树就构建完成了
}
// 二叉树销毁
void BinaryTreeDestory(BTNode** root)
{
if (*root == NULL)
return;
BinaryTreeDestory(&((*root)->_left));
BinaryTreeDestory(&((*root)->_right));
//二叉树销毁用后续遍历,到了叶子节点才开始(操作)销毁
free(*root);
*root = NULL;
//可以不销毁二级指针,只是外部BTNode*root1的地址的拷贝
}
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
return 0;
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;//分治思想,递归,总个数等于左子树加上右子树加上自己//后序,左右树遍历完了才操作(返回自己的值
}
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)//单孩子节点遍历到空
return 0;
if (root->_left == NULL && root->_right == NULL)//叶子节点
return 1;
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);//等于左边子树的叶子节点数加上右边节点的叶子数
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
return 0;//找空结束
if (k == 1)
return 1;//找到第K层了且非空
return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
//子树中第k-1层节点个数
}
// 二叉树查找值为x的节点//仅找出一节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
return 0;//返回0表示此子树未找到
if (root->_data == x)
return root;//返回找到的地址
BTNode* leftback = BinaryTreeFind(root->_left, x);
BTNode* rightback = BinaryTreeFind(root->_right, x);
return leftback == NULL ? rightback : leftback;//反正都是空就返回右空
}
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if (root == NULL)
return;
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left);
BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
if (root == NULL)
return;
BinaryTreeInOrder(root->_left);
printf("%c ", root->_data);
BinaryTreeInOrder(root->_right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
if (root == NULL)
return;
BinaryTreeInOrder(root->_left);
BinaryTreeInOrder(root->_right);
printf("%c ", root->_data);
}
// 层序遍历//用队列层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
assert(root);
QInfo queue;
QueueInit(&queue);//传地址
QueueInsert(&queue, root);
while (!QueueIsEmpty(&queue))
{
BTNode* pcur = QueuePop(&queue);
#if 1
printf("%c ", pcur->_data);
if(pcur->_left)//不插入空节点,不然找左右值时要检查节点不为空
QueueInsert(&queue, pcur->_left);
if (pcur->_right)
QueueInsert(&queue, pcur->_right);
#elif 2
if (pcur)//插入空节点要检查
{
printf("%c ", pcur->_data);
QueueInsert(&queue, pcur->_left);
QueueInsert(&queue, pcur->_right);
}
#endif
}
printf("\n");
}
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)//层序遍历,出到空节点停止并判断队列中是否只剩下空
{
if (root == NULL)
return 1;
QInfo queue;
QueueInit(&queue);
QueueInsert(&queue, root);
while (!QueueIsEmpty(&queue))
{
BTNode* mid = QueuePop(&queue);
if (mid != NULL)
{
QueueInsert(&queue, mid->_left);
QueueInsert(&queue, mid->_right);
}
else
{
break;//跳出检查队列是否只剩下空元素
}
}
while (!QueueIsEmpty(&queue))
{
BTNode* mid = QueuePop(&queue);
if (mid != NULL)
return 0;
}
}
main.c
#include"BT.h"
int main()
{
char BTarry[] = "124##5##36##7##";//"ABD##E#H##CF##G##";
int i = 0;
char findchar = '3';
BTNode* mid=0;
BTNode* root = BinaryTreeCreate(BTarry, /*int n, */&i);
printf("前,中,后序遍历:\n");
BinaryTreePrevOrder(root);
putchar('\n');
BinaryTreeInOrder(root);
putchar('\n');
BinaryTreePostOrder(root);
putchar('\n');
putchar('\n');
printf("叶子节点数 = %d\n", BinaryTreeLeafSize(root));
putchar('\n');
printf("找 %c 节点,%s\n", findchar, (mid = BinaryTreeFind(root, findchar)) == 0 ?"失败":"成功");
printf("层序遍历: ");
BinaryTreeLevelOrder(root);
putchar('\n');
printf("此二叉树 %s 完全二叉树\n", BinaryTreeComplete(root) == 1 ? "是" : "不是");
BinaryTreeDestory(&root);
return 0;
}