这里写目录标题
过往的时光早已不再,好好珍惜现在
二叉树的基础知识
知识点一
(二叉树性质 )
树与二叉树的相互转换
二叉树的遍历
层次优先遍历
树的深度和广度优先遍历
中序线索二叉树
二叉树相关遍历代码
顺序存储和链式存储
typedef struct Branch//顺序存储结构
{
int cldx;
Branch* next;
}Branch;
typedef struct
{
int data;
Branch* first;
}Tnode;
链式存储结构
二叉树的链式存储结构
typedef struct BTnode
{
char data;
struct BTnode* lchild;
struct BTnode* rchild;
}BTnode;
二叉树的遍历
void xianxubianli(BTnode* p)
{
if (p != NULL)
{
visit(p);
xianxubianli(p->lchild);
xianxubianli(p->lchild);
}
}
递归进行中序遍历
void zhongxubainli(BTnode* p)
{
if (p != NULL)
{
zhongxubainli(p->lchild);
visit(p);
zhongxubianli(p->rchild);
}
}BTnode*p
后序遍历进行递归操作
void houxubianli(BTnode* bt)
{
if (p != NULL)
{
houxubianli(p->lchild);
houxubianli(p->rchild);
visit(p);
}
}
二叉树的相关例题
左右两边表达式求值
int comp(BTnode* p)
{
int A, B;
if (p != NULL)
{
if (p->lchikd != NULL && p->rchild != NULL)
{
A = comp(p->lchild);//这个是不断的求左边的树,一直到不行的时候,然后返回,
//到上一个根的右边的树,然后看看求右边的树的值,并且也是递归,求右边树的数据的问题,
//然后分别不断的求出左右两边的值,然后一起进行ji算
B = comp(p->rchild);
return op(A, B, p->data);//这个是求的是树左右两边的数据的求值
}
else
return p->data - '0';//这个是这个根的数据的返回
}
else
return 0;//这是没有数据,直接就是返回0
}//有一些问题,比如说返回的值为什么是int,A表示的是什么意思,不是指针,难道是
深度的表达,因为是整型嘛
int comp(BTnode* p)
{
int A, B;
if (p != NULL)
{
if (p->lchild != NULL && p->rchild != NULL)
{
A = comp(p->lchild);
B = comp(p->rchild);
return op(A, B, p->data);
}
else
return p->data - '0';
}
else
retunrn 0;
}
求树的深度
求树的深度,先分别进行求出树的左子树的最长的深度以及右子树最长的深度,然后进行比较得出最大的深度数
然后进行求出的数字加一
int getdeth(BTnode* p)
{
int LD, RD;
if (p == NULL)
return 0;
else
{
LD = getdeth(p->lchild);
RD = getdeth(p->rchild);
return (LD > RD ? LD : RD) + 1;
}
}
找数
例题,对于二叉树的数据域进行分别进行查找,找一个数据域是否等于一个KEY的数,
如果等于KEY的数字则讲这个指针赋值到q里面,其实就是对于数的分一个分支进行分别的访问和
查找
void search(BTnode* p, BTnode*& q, int key)//类型还是树的指针类型
{
if (p != NULL)//这是前提条件
{
if (p->data == key)//这是直接测试p的数据域的直接的访问
q = p;//然后就是指针的赋值
else
{
search(p->lchild, q, key);//否者,如果不成立条件的话,那么进行左边的访问数据的问题
search(p->rchild, q, key);//如果左边的不行,那么就访问右边的树
}
}
}
void search(BTnode* q, int key, BTnode* q)
{
if (p != NULL)
{
if (p->data == key)
q = p;
else
{
saerch(p->lchild, q, key);
search(p->rchild, q, key);
}
}
}
找第k个数
题目进行输出二叉树中第k个指针的值
#include<stdio.h>
int main()
{
int n = 0;
void trave(BTnode * bt, int k);
return 0;
}//上面的代码就是父母,直接就是一个框架而已
void trave(BTnode* bt, int k)//下面就是函数的问题
{
int n = 0;
if (p != NULL)//这是关于p不是空的前提条件
{
++n;//这是动的加,递进就是数据的
if (n == k)//这是输出的条件问题,就是递归访问的条件
{
//输出这一点的指针的数据域
printf("%d\n", p->data);
return 0;
}
trvae(p->lchild);
trave(p->rchild);
}
}
上面这一种形式是先序的输出方式
下面还有中序和后序的输出方式
void trave(BTnode* p, int k)
{
if (p != NULL)
{
trave(p->lchild, k);
++n;
if (k == n)
{
《输出所在点的数据域》;
return;
}
trave(p->rchild, k);
}
}
递归后序的表达方式
void trave(BTnode* p, int k)
{
if (p != NULL)
{
trave(p->lchild, k);
trave(p->rchild, k);
++n;
if (k == n)
{
《输出所在点的数据域》
return;
}
}
}
二叉树非递归遍历代码
二叉树的层次优先遍历
void level(BTnode* bt)
{
if (bt != NULL)
{
int front, near;
BTnode* que[maxsize];//对于队列进行初始化que
front = rear = 0;//循环队列进行开始的赋值
BTnode* p;
rear = (rear + 1) % maxsize;//先进行尾节点加一,然后进行赋值操作
que[rear] = bt;//这就是进队列了
while (front != rear)//这是队列只要是不为空时候都是可以进行的
{
front = (front + 1) % maxsize;//出队前进行赋值操作
p = que[front];//先出队才可以访问里面的数据
visit(p);
//先要判断他里面的左右孩子是否存在,如果存在则
//进行入队的操作
if (p->lchild != NULL)
{
rear = (rear + 1) % maxsize;//进行入队的操作
que[rear] = p->lchild;
}
if (p->rchild != NULL)
{
rear = (rear + 1) % maxsize;
que[rear] = p->rchild;
}
}
}
}
二叉树非递归前序中序后续遍历
//二叉树非递归进行代码处理
// 其实就是引用了栈的应用,先
void shuchushu(BTnode* bt)//先序的存储进行取得
{
if (bt != NULL)
{
BTnode* stack[maxsaize];//进行定义栈的大小(类型就是本身就是树的类型处理)
int top = -1;//底部进行开始空的时候数组的赋值
BTnode* p = NULL;//开始的指针的大小为空
stack[++top] = bt;//对于栈进行赋值操作
while (top != -1)//进行循环的操作,取,也是存的道理都是一样的
{
p = satck[top--];//开始进行取
visit(p);
if (p->rchild != NULL)
stack[++top] = p->lchild;
if (p->lchild != NULL)
stack[++top] = p->rchild;
}
}
}shu
中序输出的非递归的方式进行
void zhongxushuchu(BTnode* bt)
{
if (bt != NULL)
{
BTnode* stack[maxsize];
int top = -1;
BTnode* p = NULL;
p = bt;
while (top != -1 || p != NULL)
{
while (p != NULL)
{
stack[++top] = p;
p = p->lchild;
}
if (top != -1)
{
p = stack[--top];
visit(p);
p = p->rchild;
}
}
}
}
后序遍历的非递归形式的表达方式
void houxubianli(BTnode* bt)
{
if (bt != NULL)
{
BTnode* stack1[maxsize]; int top1 = -1;
BTnode* stack2[maxsize]; int top2 = -1;
BTnode* p = NULL;
stack[++top1] = bt;
while (top != -1)
{
p = stack1[top1--];
stack2[++top2] = p;
if (p->lchild != NULL)
stack1[++top1] = p->lchild;
if (p->rcchild != NULL)
stack1[++top!] = p->rchild;
}
while (top2 != -1)
{
p = stack2[--top];
visit(p);
}
}
}
##二叉树遍历扩展
typedef struct Branch
{
int cldx;//这个其实就是子孩子的节点下标
Branch* next;//这个是指向的是字孩子节点的后一个孩子节点
}Branch;
typedef struct
{
int data;
Branch* first;//这个是指向的节点的指针,其实是孩子节点,第一个开始的时候就需要用到这个,就是因为开始的根节点也是孩子节点
}Tnode;
Tnode tree[6];//定义树节点的多少,这个其实就是指针数组,里面的全是指针节点
Branch* q = tree[0]->first;//开始的时候就是需要指向的first,指向的就是数组里面的指针,所以需要用到first,并且用指针的形式表示出来
tree[q->cldx];//这个就是这个节点的下标
void shuchuxingshi(Tnode* p, Tnode tree[])
{
if (p != NULL)
{
visit(p);
//下面就是访问他的子节点的情况了
Branch* q;
q = p->first;//这个就是子节点的指针情况了
while (q != NULL)
{
shuchuxingshi(tree[q->cldx], tree);//这个就是调用的子节点的情况里面进行调用了
//这个子节点的情况调用完之后就是下一个子节点的情况,然后重新依次的进行调用
//里面子节点的情况
}
}
}
树的广度层次优先遍历的代码演示
void level(Tnode* tn, Tnode tree[])
{
int front, rear;
Tnode* que[maxsize];
front = rear = 0;
Tnode* p;
if (tn != NULL)
{
rear = (rear + 1) % maxszie;
que[rear] = tn;
while (front != rear)
{
front = (front + 1) % maxszie;
p = que[front];
visit(p);
Branch* q = p->first;//这个就是分析子节点的问题了,和之前的情况是一样的
while (q != NULL)
{
rear = (rear + 1) % maxszie;
que[rear] = tree[q->cldx];
q = q->next;
}
}
}
}
中序线索遍历二叉树的代码演示
typedef struct BTnode
{
int data;
int lTag;
int rTag;
TBnode* lchild;
TBnode* rchild;
}TBnode;
void inthread(BTnode* p, TBnode* pre)//pre表示的是p的前驱节点// 前驱节点本来就是NULL的,只不过是需要不断的变化的
{
if (p != NULL)
{
inthread(p->lchild, pre);//一直表示到底部的空节点了
if (p->lchild == NULL)
{
p->lchild = pre;
p->lTag = 1;
}
if (pre != NULL && pre->rchild == NULL)
{
pre->rchild = p;
pre->rTag = 1;
}
pre = p;//如果上述条件都没有成立,那么前驱节点就需要改变了
inthread(p->rchild, pre);
}
}