树与二叉树【中】

\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

在这里插入图片描述
根据中序遍历的规则,如有一直有左孩子,那么就会最先访问最左下的节点

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值