一、树的存储结构
1.普通树的存储结构
普通树有许多种存储结构:下面只了解最常用的孩子兄弟表示法
typedef int DataType;
struct Node
{
struct Node* _firstChild1; // 第一个孩子结点
struct Node* _pNextBrother; // 指向其下一个兄弟结点
DataType _data; // 结点中的数据域
};
2.二叉树的存储结构
二叉树的存储结构分为顺序存储和链式存储
(1)顺序存储
顺序存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有
空间的浪费。而现实中使用中只有堆才会使用数组来存储。二叉树顺序存储在物理上是一个数
组,在逻辑上是一颗二叉树。
(2)链式存储
链式存储又分为两种:二叉存储和三叉存储(看图就可以很好的理解)
typedef int BTDataType;
// 二叉链
struct BinaryTreeNode
{
struct BinTreeNode* _pLeft; // 指向当前节点左孩子
struct BinTreeNode* _pRight; // 指向当前节点右孩子
BTDataType _data; // 当前节点值域
};
// 三叉链
struct BinaryTreeNode
{
struct BinTreeNode* _pParent; // 指向当前节点的双亲
struct BinTreeNode* _pLeft; // 指向当前节点左孩子
struct BinTreeNode* _pRight; // 指向当前节点右孩子
BTDataType _data; // 当前节点值域
};
二、二叉树的常见操作
1.二叉树的遍历
这里只展示递归版本,非递归版本在leetcode中借助题目实现
(1)前序 二叉树的前序遍历
//前序
void PrevOrder(BTNode* root)
{
//空树
if(root == NULL)
{
printf("NULL ");
return;
}
printf("%c ",root->data);//根
PrevOrder(root->left);//左子树
PrevOrder(root->right);//右子树
}
(2)中序 二叉树的中序遍历
//中序
void InOrder(BTNode* root)
{
//空树
if(root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);//左子树
printf("%c ",root->data);//根
InOrder(root->right);//右子树
}
(3)后序 二叉树的后序遍历
//后序
void PostOrder(BTNode* root)
{
//空树
if(root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);//左子树
PostOrder(root->right);//右子树
printf("%c ",root->data);//根
}
(4)层序 -- 需要队列实现
①根先进队列。
②队列不为空,出队头数据,同时把出的节点的左右孩子带进去。
③直到队列为空时结束。
//层序遍历 需要利用队列(先进先出)
//上一层节点带下一层节点进队列。一层一层走,队列先进先出。
void LevelOrder (BTNode* root)
{
//定义队列
Queue q;
QueueInit(&q);
//空树
if(root == NULL)
{
printf("NULL ");
return;
}
//非空树
//1.根先迸队列
QueuePush(&q, root);
//2.迭代 -> 队列不为空,出队头数据,同时把出的节点的左右孩子带进去
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);//取队头数据
QueuePop(&q);//出队头数据
printf("%c ",front->data);//打印队头数据
//出去的节点的左孩子带进去(只带不为空的)
if(front->left != NULL)
{
QueuePush(&q, front->left);
}
//出去的节点的右孩子带进去(只带不为空的)
if(front->right != NULL)
{
QueuePush(&q, front->right);
}
}
//3.队列为空时结束,并且销毁队列
printf("\n");
QueueDestroy(&q);
}
2.递归解决二叉树的有关问题
(1)
(2)
(3)
(4)
(5)