数据结构——树(二)

210 阅读2分钟

这是我参与更文挑战的第16天,活动详情查看:更文挑战

二叉树的遍历与线索二叉树

二叉树的遍历

  • 先序遍历: 若二叉树不为空,
    • 访问根结点
    • 先序遍历左子树
    • 先序遍历右子树
  • 中序遍历: 若二叉树不为空,
    • 中序遍历左子树
    • 访问根节点
    • 中序遍历右子树
  • 后序遍历: 若二叉树不为空,
    • 后序遍历左子树
    • 后序遍历右子树
    • 访问根节点

ps.其实就是左子树在前右子树在后,然后根节点在前面就是先序,在中间就是中序

  • 递归算法与非递归算法的转换

以中序为例

void InOrder2(BiTree T)}{
    //二叉树中序遍历的非递归算法,算法需要借助一个栈
    InitStack(S);BiTree *p = T;// 初始化栈,p是遍历指针
    while(p|| !isEmpty(S)){ //如果p非空或者S非空
        if(p){
            push(S,p);
            p = p->lchild;
        }else{
            Pop(S,p);
            visit(p);
            p=p->prchild;
        }
    }
}
  • 层次遍历

  • 由遍历序列构造二叉树

无法通过先序序列和后序序列确定唯一二叉树

线索二叉树

传统的链式存储仅能体现一种父子关系,不能直接得到结点在遍历中的前驱和后继。二叉链表表示的二叉树存在大量的空指针,可以利用其构建结点的前驱和后继。

前文提到,在n个结点的二叉树有n个空指针

ltaglchilddatarchildrtag
0:左孩子,1:前驱0:右孩子,1:后继
typedef struct ThreadNode{
    ElemType data;
    struct ThreadNode *lchild,*rchild;
    int ltag,rtag;
}ThreadNode,*ThreadTree;

线索二叉树的构造

// 中序遍历对二叉树线索化
void InThread(ThreadTree &p.ThreadTree &pre){
    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);
    }
}
void CreateInThread(ThreadTree T){
    ThreadTree pre = NULL;
    if(T!=NULL){
        InThread(T,pre);
        pre->rchild = NULL;
        pre->rtag = 1;
    }
}

可以设置一个头结点,令其lchild域的指针指向二叉树的根节点,令其rchild域的指针指向中序遍历时访问的最后一个结点。同时,将二叉树中序序列的第一个结点lchild域的指针和最后一个结点的rchild域的指针均指向头结点。使二叉树可以两个方向的遍历

二叉树的遍历

//求中序线索二叉树中中序序列下的第一个结点
ThreadNode *Firstnode(ThreadNode *p){
    while(p->ltag == 0)p=p->lchild; //不一定是叶子结点
    return p;
}
// 求中序线索二叉树中结点p在中序序列下的后继结点
ThreadNode *Nextnode(ThreadNode *p){
    if(p->tag == 0) return Firstnode(p->rchild);
    else return p->rchild;
}
// 中序遍历
void Inorder(ThreadNode *T){
    for(ThreadNode *p = Firstnode(T);p!=NULL;p=Nextnode(p))
        visit(p);
}