数据结构——二叉树

二叉树

二叉树的顺序存储

结点结构体
struct treeNode {//二叉树结点
    int value;
    bool IsEmpty;
};
定义一个二叉树
    treeNode t[MAXSIZE];//定义一个二叉树
完全二叉树存储方案

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

普通二叉树(非完全)存储方案

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

二叉树的链式存储

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

结点结构体
struct BitNode {//二叉树链式存储结点
    int value;
    BitNode* lchild, * rchild;
}BitNode,*Bitree;
带有父节点指针的链式存储结点(三叉链表)

方便逆序遍历

typedef struct BitNode {//二叉树链式存储结点
    int value;
    BitNode* lchild, * rchild;
    BitNode* father;
}BitNode, *Bitree;
定义一个根节点
    Bitree root = NULL;
    root = new(BitNode);
    root->value = 1;
    root->lchild = NULL;
    root->rchild = NULL;

二叉树的遍历

先序遍历
//先序遍历 
void preOrder(Bitree root)
{
    if (root != NULL)
    {
        visit(root);
        preOrder(root->lchild);
        preOrder(root->rchild);
    }
}
中序遍历
//中序遍历
void InOrder(Bitree root)
{
    if (root != NULL)
    {
        preOrder(root->lchild);
        visit(root);
        preOrder(root->rchild);
    }
}
后序遍历
//后序遍历
void InOrder(Bitree root)
{
    if (root != NULL)
    {
        preOrder(root->lchild);
        preOrder(root->rchild);
        visit(root);
    }
}
层次遍历

队列辅助

//二叉树层次遍历
void levelOrder(Bitree root)
{
    InitQueue(Q);//初始化辅助队列
    Bitree p;
    EnQueue(Q, root);//根节点入队
    while (!IsEmpty(Q))//队列不空则循环
    {
        DeQueue(Q, p);//对头结点出队
        visit(p);//访问出队结点
        if (p->lchild != NULL)
            EnQueue(Q, p->lchild);//左子树不空则左子树结点入队
        if (p->rchild != NULL)
            EnQueue(Q, p->rchild);//右子树不空则右子树结点入队
    }
}

线索二叉树

在这里插入图片描述

tag0表示指针指向孩子
tag
1表示指针指向线索

typedef struct ThreadNode{
    int data;
    ThreadNode* lchild, * rchild;
    int ltag, rtag;//左右线索标志
}ThreadNode,*Threadtree;

在这里插入图片描述

中序线索化

ThreadNode* pre = NULL;
//中序线索化二叉树
void creatInThread(Threadtree T)
{
    pre == NULL;
    if (T != NULL)
    {
        InThread(T);
        if (pre->rchild == NULL)//最后将pre结点的rtag置1
            pre->rtag = 1;
    }
}
//一边遍历一遍线索化
void InThread(Threadtree root)
{
    if (root != NULL)
    {
        InThread(root->lchild);
        Thread_visit(root);
        InThread(root->rchild);
    }
}
void Thread_visit(ThreadNode* q)
{
    if (q->lchild == NULL)//左子树为空建立前驱结点
    {
        q->lchild = pre;
        q->ltag = 1;
    }
    if (pre!=NULL&&pre->rchild == NULL)//前驱结点不为空且右子树为空建立后继结点
    {
        pre->rchild = q;
        pre->rtag = 1;
    }
    pre = q;
}
先序线索化

在遍历过程中注意防止程序指针循环指的问题加上条件
if (root != NULL)
{
Thread_visit(root);
if(root->ltag==0)
PreThread(root->lchild);==
PreThread(root->rchild);
}

//先序线索化
void creatPreThread(Threadtree T)
{
    pre == NULL;
    if (T != NULL)
    {
        InThread(T);
        if (pre->rchild == NULL)//最后将pre结点的rtag置1
            pre->rtag = 1;
    }
}
//一边遍历一边线索化
void PreThread(Threadtree root)
{
    if (root != NULL)
    {
        Thread_visit(root);
        if(root->ltag==0)
            PreThread(root->lchild);
        PreThread(root->rchild);
    }
}
void Thread_visit(ThreadNode* q)
{
    if (q->lchild == NULL)//左子树为空建立前驱结点
    {
        q->lchild = pre;
        q->ltag = 1;
    }
    if (pre!=NULL&&pre->rchild == NULL)//前驱结点不为空且右子树为空建立后继结点
    {
        pre->rchild = q;
        pre->rtag = 1;
    }
    pre = q;
}
中序线索二叉树找后继结点
//中序线索二叉树中找到中序后继

//在线索二叉树中找到p的后继结点
ThreadNode* NextNode(ThreadNode* p)
{
    if (p->rtag == 0)return Firstnode(p->rchild);
    else return p->rchild;
}
//找到以p为根子树中第一个杯中序遍历的结点
ThreadNode* Firstnode(ThreadNode* p)
{
    while (p->ltag == 0)
        p = p->lchild;
    return p;
}

///

线索后继方法中序遍历线索二叉树

void InOrder(ThreadNode* T)//利用线索后继方法实现中序线索二叉树遍历
{
    for (ThreadNode* p = Firstnode(T); p!NULL; p = NextNode(p))
        visit(p);
}
中序线索二叉树找前驱结点
//线索二叉树结点找前驱
///
//找到以p为根的子树中最后一个被遍历的结点
ThreadNode* LastNode(ThreadNode* p)
{
    while (p->rtag == 0)p = p->rchild;
    return p;
}
//在中序线索二叉树中找到结点p的前驱结点
ThreadNode* preNode(ThreadNode* T)
{
    //左子树中最右下的结点
    if (T->ltag == 0)return LastNode(T->lchild);
    else return T->lchild;
}
///
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值