文章目录
一、链式结构二叉树
⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。 通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址 ,其结构如下:
typedef int BTDataType;
// ⼆叉链
typedef struct BinaryTreeNode
{
struct BinTreeNode* left; // 指向当前结点左孩⼦
struct BinTreeNode* right; // 指向当前结点右孩⼦
BTDataType val; // 当前结点值域
}BTNode;
⼆叉树分为空树和⾮空⼆叉树,⾮空⼆叉树由根结点、根结点的左⼦树、根结点的右⼦树组成的
根结点的左⼦树和右⼦树分别⼜是由⼦树结点、⼦树结点的左⼦树、⼦树结点的右⼦树组成的,因此⼆叉树定义是递归式的,后序链式⼆叉树的操作中基本都是按照该概念实现的。
二、链式二叉树的遍历
1、遍历方式
(1)前序遍历:先打印根节点,然后打印左子树,最后打印右子树
(2)中序遍历:先打印左子树,再打印根结点,最后打印右子树
(3)后序遍历:先打印左子树,再打印右子树,最后打印根结点
2、前序遍历
//前序遍历
void PreOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
printf("%d ", root->val);
PreOrder(root->left);
PreOrder(root->right);
}
3、中序遍历
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
InOrder(root->left);
printf("%d ", root->val);
InOrder(root->right);
}
4、后序遍历
//后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->val);
}
三、链式二叉树结点个数和高度等
1、二叉树结点的个数
//结点个数
int BinarySize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
return 1 + BinarySize(root->left) + BinarySize(root->right);
}
2、二叉树叶子结点的个数
//叶子结点的个数
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);
}
3、第K层结点的个数
//第K层结点的个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}
4、树的深度
//树的深度
int BinaryTreeDepth(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int left = 1 + BinaryTreeDepth(root->left);
int right = 1 + BinaryTreeDepth(root->right);
return left > right ? left : right;
}
5、找值所在的结点
//二叉树找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDateType x)
{
if (root == NULL)
{
return NULL;
}
if (root->date == x)
{
return root;
}
BTNode* leftFind = BinaryTreeFind(root->left, x);
return (leftFind != NULL ? leftFind : BinaryTreeFind(root->right,x));
}
6、二叉树销毁
//销毁
void BinaryTreeDesTroy(BTNode** root)
{
if (*root == NULL)
{
return;
}
BinaryTreeDesTroy(&((*root)->left));
BinaryTreeDesTroy(&((*root)->right));
free(*root);
*root = NULL;
}
四、借助队列完成二叉树的操作
1、队列创建和队列的相关操作
typedef BTNode* QNDateType;
//队列结点
typedef struct QueueNode
{
QNDateType* date;
struct QueueNode* next;
}QN;
//队列
typedef struct Queue
{
QN* phead;
QN* ptail;
int size;
}Queue;
//队列的初始化
void QueueInit(Queue* pq)
{
assert(pq != NULL);
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
//入队列从队尾入
void QueuePush(Queue* pq,QNDateType x)
{
assert(pq != NULL);
QN* newnode = (QN*)malloc(sizeof(QN));
if (newnode == NULL)
{
perror("malloc fail");
exit(1);
}
newnode->date = x;
newnode->next = NULL;
if (pq->phead == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
//队列是否为空
bool QueueEmpty(Queue* pq)
{
return pq->size == 0;
}
//出队列从队头出
void QueuePop(Queue* pq)
{
assert(pq != NULL);
assert(!QueueEmpty(pq));
if (pq->size > 1)
{
QN* del = pq->phead;
pq->phead = pq->phead->next;
free(del);
del = NULL;
}
else
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
pq->size--;
}
//取队头元素
QNDateType QueueFront(Queue* pq)
{
assert(pq != NULL);
assert(!QueueEmpty(pq));
return pq->phead->date;
}
//销毁队列
void QueueDesTroy(Queue* pq)
{
assert(pq);
QN* pcur = pq->phead;
while (pcur)
{
QN* next = pcur->next;
free(pcur);
pcur = next;
}
pcur = NULL;
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
2、借助队列完成二叉树的层序打印
//层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
if (root == NULL)
{
return;
}
Queue q;
QueueInit(&q);
QNDateType n = root;
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
n = QueueFront(&q);
printf("%d ", n->date);
QueuePop(&q);
if(n->left)
QueuePush(&q, n->left);
if(n->right)
QueuePush(&q, n->right);
}
QueueDesTroy(&q);
}
3、借助队列判断是否为完全二叉树
//是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
if (root == NULL)
{
return false;
}
Queue q;
QNDateType n = root;
QueueInit(&q);
QueuePush(&q, root);
while (n)
{
n = QueueFront(&q);
QueuePop(&q);
if(n)
QueuePush(&q, n->left);
if(n)
QueuePush(&q, n->right);
}
while (!QueueEmpty(&q))
{
n = QueueFront(&q);
QueuePop(&q);
if (n != NULL)
{
QueueDesTroy(&q);
return false;
}
}
QueueDesTroy(&q);
return true;
}