二叉树知识点

二叉树的存储结构

顺序存储

定义

#define MaxSize 100
struct TreeNode{
    ElemType value;		//节点中的数据元素
    bool isEmpty;		//节点是否为空
};

初始化

bool InitTreeNode(TreeNode &T[]){
    int i;
    for(i=0;i<MaxSize;i++){
        T[i].isEmpty=true;
    }
    if(i==MaxSize+1)
    	return true;
    else
        return false;			//初始化失败
}

链式存储

struct ElemType{
    int value;
};
typedef struct BiTNode{
    ElemType data;			//值域
    struct BitNode *lchild,*rchild;		//指针域
}BiTNode,*BiTree;

void test(){
    BiTree root=NULL;		//定义一棵空树
    
    //插入空节点
    root=(BiTNode *)malloc(sizeof(BiTNode));
    root.data={1};
    root->lchild=NULL;
    root->rchild=NULL;
}

n个节点的二叉链表共有n+1个空链域

分析:n个节点有2n个指针,使用了n-1个(根节点没有,其他都有一个),还剩n+1个。

二叉树的遍历

先序遍历

过程:

1.若二叉树为空,则什么也不做

2.若二叉树非空:先访问根节点–>先序遍历左子树—>先序遍历右子树(利用递归特性)

typedef struct BiTNode{
    ElemType data;
    struct BiTNode *lchild,*rchild;
}BiTNode,* BiTree;

//先序遍历
void PreOrder(BiTree T){
    if(T!=NULL){
        visit(T);					//访问当前根节点
        PreOrder(T->lchild);		 //递归访问左子树
        PreOrder(T->rchild);		 //递归 访问右子树
    }
}

中序遍历

过程:

1.若二叉树为空,则什么也不做

2.若二叉树非空:先序遍历左子树—>先访问根节点–>先序遍历右子树(利用递归特性)

//中序遍历
void InOrder(BiTree T){
    if(T!=NULL){
        InOrder(T->lchild);
        visit(T);
        Inorder(T->rchild);
    }
}

后序遍历

过程:

1.若二叉树为空,则什么也不做

2.若二叉树非空:先序遍历左子树–>先序遍历右子树—>先访问根节点(利用递归特性)

//后序遍历
void PostOrder(BiTree T){
    if(T!=NULL){
        PostOrder(T->lchild);
        PostOrder(T->rchild);
        visit(T);
    }
}

先序遍历–>前缀表达式

中序遍历–>中缀表达式(需要加界限符)

后序遍历–>后缀表达式

求树的深度

int treeDepth(BiTree T){
    if(T==NULL){
        return 0;
    }else{
        int l=treeDepth(T->lchild);
        int r=treeDepth(T->rchild);
        return l>r?l+1:r+1;
    }
}

二叉树的层序遍历

思想:

1.初始化一个辅助队列

2.根节点入队

3.若队列非空,则队头节点出队,访问该节点,并将其左右孩子插入队尾(如果有)

//二叉树
typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;

//链式队列节点
typedef struct LinkNode{
    BitNode *data;			//存指针而不是节点
    struct LinkNode *next;
}LinkNode;

typedef struct{
    LinkNode *front,*rear;
}LinkQueue;


//顺序遍历
void levelOrder(BiTree T){
    LinkQueue Q;		//创建一个队列
    InitQueue(Q);		//初始化
    BiTree p;
    EnQueue(Q,T);			//根节点入队
    while(!EmptyQueue(Q)){		//队列不空
        //队头节点出队
        DeQueue(Q,p);
        //访问队头节点
        visit(p);
        if(p->lchild!=NULL){
            EnQueue(Q,p->lchild);
        }
        if(p->rchild!=NULL){
            EnQueue(Q,p->rchild);
        }
        
    }
}

由遍历序列得到二叉树

条件:确定唯一的二叉树

1.前序加中序遍历序列

2.后序加中序遍历序列

3.层序加中序遍历序列

线索二叉树

作用:方便从一个指定节点出发,找到其前驱,后继,方便遍历

存储结构:

1.在普通二叉树的基础上,增加两个标志位ltag,rtag;

2.ltag=1时,表示lchild指向前驱;ltag=0时,表示lchild指向左孩子

1.中序线索二叉树的构造

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wFGrg27A-1627293541628)(C:\Users\25720\Desktop\1.png)]

//用土方法找到中序前驱
//思路:进行一次中序遍历,从第一个中序遍历的结点开始(D),若当前访问节点是所需要找到节点,则pre是中序前驱,否则将pre=当前节点

void InOrder(BiTree T){
    if(T!=NULL){
        InOrder(T->lchild);
        visit(T);
        InOrder(T->rchild);
    }
}

//找p的前驱节点
void visit(BiTNode *q){
    if(q==p){				//若当前节点是所需要的节点,则pre是前驱节点
        final=pre;
    }
    else						//若不是,则将pre=p,继续遍历
    {
        pre=p;
    }
} 

//辅助全局变量
BitNode *p;				//需要查找前驱节点的节点
BiTNode *final=NULL;		//结果
BiTNode * pre=NULL;			//当前节点的前驱节点,初始为NULL;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fpj8YzmW-1627293541636)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722153456317.png)]

//中序线索二叉树的构造



//定义线索二叉树
typedef struct ThreadNode{
    ElemType data;
    struct ThreadNode *lchild,*rchild;
    int ltag,rtag;				//左右线索标志,0表示指向左右孩子,1表示指向线索		
}ThreadNode,*ThreadTree;

Thread *pre=NULL;			//全局变量,指向当前访问节点的前驱

//中序遍历二叉树,一边遍历一边线索化
void InThread(ThreadTree T){
    if(T!=NULL){
        InThread(T->lchild);
        visit(T);				//进行线索化
        InThread(T->rchild);
    }
}

void visit(ThreadNode *p){
    //思路:当前节点若没有左孩子,则左指针指向pre,若当前pre不为空且pre的右指针为空,则pre的右指针指向p,pre是q的前驱
    if(p->lchild==NULL){
        p->lchild=pre;
        p->ltag=1;
    }
    
    if(pre!=NULL && pre->rchild==NULL){
        pre->rchild=p;
        pre->rtag=1;
    }
    
    pre=p;			//pre后移
}


void CreateThread(ThreadTree T){
    //判断是否为空
    if(T!=NULL){
        //线索化
        InThread(T);
        if(pre->rchild==NULL){
            pre->rtag=1;//最后一个节点访问之后,pre=p,且pre指向NULL,需要进行线索化(pre->rtag=1)
        }
    }
}


2.前序线索二叉树的构造

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m240PaeF-1627293541639)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722155619407.png)]

//需要注意的问题是进行左子树遍历时,要进行判断是否指向线索前驱
//改正后的代码为:
void PreThread(ThreadTree T){
    if(T!=NULL){
        visit(T);			//先处理根节点
        if(T->ltag==0)
            PreThread(T->lchild);
        PreThread(T->rchild);
    }
}    

中序线索二叉树找前驱后继

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rsHFAkGo-1627293541642)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722162359603.png)]

/*
分析:
要找节点p的后继,首先判断节点p的rtag是否为1,若为1,则p->rchild就是线索后继
若不为1,则以p为根节点的右子树的最左下的节点为后继

*/

//找到以p节点为根节点的子树中,最先被中序遍历访问的节点--->最左下的节点
ThreadNode *FirstNode(ThreadNode *p){
    while(p->ltag==0) p=p->lchild;
}

//找p节点的后继节点
ThreadNode *NextNode(ThreadNode *p){
    if(p->rtag==0) return FirstNode(p->rchild);
    else return p->rchild;
}

//进行中序线索二叉树的遍历
void InoOrder(ThreadNode *T){
    //从根节点开始,首先找到中序遍历最先被访问的节点,然后找后继一直访问
    for(ThreadNode *q=FirstNode(T);q!=NULL;q=NextNode(q)){
        visit(p);
    }
}

找前驱

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6RLTqq2u-1627293541645)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722163617755.png)]

先序线索二叉树找前驱后继

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-diuTInuy-1627293541647)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722163953370.png)]

找先序后继

ThreadNode *NextPreNode(ThreadNode *p){
    
    if(p->rtag==0){			//有右孩子
        if(p->ltag==0)	return p->lchild;		//有左孩子
        else return p->rchild;
    }else
    {
        return p->rchild;
    }
}

找先序前驱

p->ltag==1时,就是p->lchild;

p->ltag==0时,找不到,因为p的所有孩子只能是后继

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PnkcPIA4-1627293541649)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722165440562.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BMWztcwZ-1627293541651)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722165408248.png)]

后序线索二叉树找前驱后继

找前驱

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0XPQnlmC-1627293541654)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722165645491.png)]

void PrePostNode(ThreadNode *p){
    if(p->ltag==0){
        //如果有右孩子
        if(p->rtag==0) return p->rchild;
        else return p->lchild;
    }
    else{
        return p-lchild;
    }
}

找后继

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-USNz0H45-1627293541656)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722170336333.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-No0Iuxb4-1627293541657)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722170435813.png)]

总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tFqVeqSn-1627293541659)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722170521408.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TQl5Cwps-1627293541662)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722170534756.png)]

前序后序二叉树可能的棵树问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YQt4D4jj-1627293541664)(C:\Users\25720\AppData\Roaming\Typora\typora-user-images\image-20210722204611644.png)]

做题

1,前序序列和中序序列的关系相当于以前序序列进栈,中序序列出栈

2.某二叉树的先序序列和后序序列正好相反,则该二叉树一定是高度等于其节点数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值