目录
- 二. 二叉树
- 2.1 二叉树的性质
- 2.2 二叉树的存储结构
- 2.2.1 二叉树的顺序存储(只适合存储完全二叉树)
- 2.2.2 二叉树的链式存储
- 2.3 二叉树的遍历
- 2.3.1 先序遍历
- 2.3.2 中序遍历
- 2.3.3 后序遍历
- 2.3.4 二叉树的层序遍历
- 2.3.5 由遍历序列构造二叉树
- 2.3.5.1 前序+中序确定二叉树
- 2.3.5.2 后序+中序确定二叉树
- 2.3.5.3 层序+中序确定二叉树
- 2.4 线索二叉树(难且重要)
- 2.4.1 线索二叉树的概念
- 2.4.2 二叉树的线索化(代码实现)
- 2.4.3 在线索二叉树中找前驱/后继
\quad
二. 二叉树
\quad
2.1 二叉树的性质
\quad
\quad
2.2 二叉树的存储结构
\quad
2.2.1 二叉树的顺序存储(只适合存储完全二叉树)
\quad
\quad
2.2.2 二叉树的链式存储
\quad
\quad
2.3 二叉树的遍历
\quad
2.3.1 先序遍历
\quad
\quad
2.3.2 中序遍历
\quad
\quad
2.3.3 后序遍历
\quad
\quad
2.3.4 二叉树的层序遍历
\quad
B出来后,他的左右孩子就要入队
\quad
2.3.5 由遍历序列构造二叉树
\quad
\quad
2.3.5.1 前序+中序确定二叉树
\quad
\quad
2.3.5.2 后序+中序确定二叉树
\quad
\quad
2.3.5.3 层序+中序确定二叉树
\quad
\quad
2.4 线索二叉树(难且重要)
2.4.1 线索二叉树的概念
\quad
普通二叉树存在的问题
\quad
以中序为例构建线索二叉树
注意这里的名词含义
\quad
2.4.2 二叉树的线索化(代码实现)
\quad
中序线索化
先序线索化出现的问题
假设现在访问的是第三个结点也就是D结点,那么pre就是指向B
按照visit的逻辑,D的做孩子指向B,然后pre在指向D
根据先序规则,访问完根节点接着就是访问左孩子
就会导致q结点指回B,这样就会形成一个闭环了
那么怎么解决这个问题呢
我们对preThread进行改造一下
由于visit中,我们访问完左孩子后会把Ltag置为1,表示已经指向前驱了
那么我们就可以对Ltag动手
改造完成
后序线索化(不会出现先序线索化的那个问题)
//二叉树的遍历
#include<stdio.h>
#include<stdlib.h>
#include<String.h>
#include<assert.h>
typedef char BTDatetype;
typedef struct BinaryTreeNode {
BTDatetype _date;
struct BinaryTreeNode* _right;
struct BinaryTreeNode* _left;
int ltag, rtag; //等于0就是指向孩子, 等于1就是指向前驱或后继
}BTNode;
BTNode* p; //p指向目标节点
BTNode* pre = NULL; //指向目标节点的前驱
BTNode* final = NULL; //用于记录最终结果
void visit(BTNode* goal);
void PrevOrder(BTNode* root);
void InThread(BTNode* root);
void InOrder(BTNode* root);
BTNode* CreateNode(char x);
void PostOrder(BTNode* root);
void CreateInThread(BTNode* T); //中序线索化二叉树
void PreThread(BTNode* root);//先序遍历二叉树, 一边遍历,一边线索化
//前序遍历
void PrevOrder(BTNode* root)
{
if (root == NULL)
{
//printf("NULL");
return;
}
printf("%c ", root->_date);
PrevOrder(root->_left);
PrevOrder(root->_right);
}
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
//printf("NULL ");
return;
}
InOrder(root->_left);
printf("%c ", root->_date);
InOrder(root->_right);
}
//后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
//printf("NULL ");
return;
}
PostOrder(root->_left);
PostOrder(root->_right);
printf("%c ", root->_date);
}
//模拟树
BTNode* CreateNode(char x)
{
BTNode* Node = (BTNode*)malloc(sizeof(BTNode));
Node->_date = x;
Node->_left = NULL;
Node->_right = NULL;
Node->ltag = 0;
Node->rtag = 0;
return Node;
}
//线索化
void visit(BTNode* root) {
if (root->_left == NULL)
{
root->_left = pre;
root->ltag = 1;
}
if (pre != NULL && pre->_right ==NULL)
{
pre->_right = root;
pre->rtag = 1;
}
pre = root;
}
//中序遍历二叉树, 一边遍历,一边线索化
void InThread(BTNode* root)
{
if (root == NULL)
{
//printf("NULL ");
return;
}
InThread(root->_left);
visit(root);
InThread(root->_right);
}
//先序遍历二叉树, 一边遍历,一边线索化
void PreThread(BTNode* root)
{
if (root == NULL)
{
//printf("NULL ");
return;
}
visit(root);
if (root->ltag == 0)
{
PreThread(root->_left);
}
PreThread(root->_right);
}
void CreateInThread(BTNode* T) //中序线索化二叉树
{
pre = NULL;
if (T != NULL) {
InThread(T);
if (pre->_right == NULL) {
pre->rtag = 1;
}
}
}
int main()
{
BTNode* A = CreateNode('A');
BTNode* B = CreateNode('B');
BTNode* C = CreateNode('C');
BTNode* D = CreateNode('D');
BTNode* E = CreateNode('E');
BTNode* F = CreateNode('F');
BTNode* G = CreateNode('G');
A->_left = B;
A->_right = C;
B->_left = D;
B->_right = E;
C->_left = F;
D->_right = G;
return 0;
}
\quad
2.4.3 在线索二叉树中找前驱/后继
\quad
根据中序遍历的规则,如有一直有左孩子,那么就会最先访问最左下的节点