码迷,mamicode.com
首页 > 其他好文 > 详细

二叉树的二叉链表表示和实现

时间:2015-08-19 23:46:58      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:c   数据结构   计算机专业   考研   

二叉树的二叉链表存储结构

typedef struct BiTNode
{
    TElemType data;
    BiTNode * lchild, *rchild;//左右孩子指针
}BiTNode, * BiTree;

二叉链表的22个基本操作

#define ClearBiTree DestroyBiTree//清空二叉树和销毁二叉树的操作一样

void InitBiTree(BiTree &T){
    T = NULL;
}

void DestroyBiTree(BiTree &T){
    if (T)//非空树
    {
        DestroyBiTree(T->lchild);//递归销毁左子树,如无左子树,则不执行任何操作
        DestroyBiTree(T->rchild);//递归销毁右子树,如无右子树,则不执行任何操作
        free(T);//释放根结点
        T = NULL;//空指针赋0
    }
}

void PreOrderTraverse(BiTree T, void(*visit)(TElemType)){//先序递归遍历T,对每个结点调用visit一次且仅一次
    if (T)//T不空
    {
        visit(T->data);//先访问根结点
        PreOrderTraverse(T->lchild, visit);//再先序遍历左子树
        PreOrderTraverse(T->rchild, visit);//最后先序遍历右子树
    }
}

void InOrderTraverse(BiTree T, void(*visit)(TElemType)){//中序递归遍历T,对每个结点调用visit一次且仅一次
    if (T)//T不空
    {
        InOrderTraverse(T->lchild, visit);//先中序遍历左子树
        visit(T->data);//再访问根结点
        InOrderTraverse(T->rchild, visit);//最后中序遍历右子树
    }
}

Status BiTreeEmpty(BiTree T){
    if (T)
        return FALSE;
    else
        return TRUE;
}

int BiTreeDepth(BiTree T){//返回T的深度
    int i, j;
    if (!T)
        return 0;//空树深度为0
    i = BiTreeDepth(T->lchild);//i为左子树深度,如左子树为空,i为0
    j = BiTreeDepth(T->rchild);//j为右子树深度,如右子树为空,j为0
    return i > j ? i + 1 : j + 1;//T的深度为其左右子树的深度中的大者+1
}

TElemType Root(BiTree T){
    if (BiTreeEmpty(T))//二叉树T为空
        return Nil;//返回“空”
    else//二叉树T不空
        return T->data;//返回根结点的值
}

TElemType Value(BiTree p){//二叉树T存在,p指向T中某个结点,返回p所指结点的值
    return p->data; 
}

void Assign(BiTree p, TElemType value){
    p->data = value;//给p所指结点赋值为value
}

typedef BiTree QElemType;//定义队列元素为二叉树的指针类型

BiTree Point(BiTree T, TElemType s){//返回二叉树T中指向元素值为s的结点的指针
    LinkQueue q; 
    QElemType a;
    if (T)//非空树
    {
        InitQueue(q);//初始化队列
        EnQueue(q, T);//根指针入队
        while (!QueueEmpty(q))//队不空
        {
            DeQueue(q, a);//出队,队列元素赋给a
            if (a->data == s)//a所指结点的值为s
                return a;//返回a
            if (a->lchild)//有左孩子
                EnQueue(q, a->lchild);//入队左孩子
            if (a->rchild)//有右孩子
                EnQueue(q, a->rchild);//入队右孩子
        }
    }
    return NULL;
}

TElemType LeftChild(BiTree T, TElemType e){//返回e的左孩子,若e无左孩子,则返回“空”
    BiTree a; 
    if (T)//非空树
    {
        a = Point(T, e);//a是指向结点e的指针
        if (a && a->lchild)//T中存在结点e且e存在左孩子
            return a->lchild->data;//返回e的左孩子的值
    }
    return Nil;//其余情况返回空
}

TElemType RightChild(BiTree T, TElemType e){//返回e的右孩子,若e无右孩子,则返回“空”
    BiTree a;
    if (T)//非空树
    {
        a = Point(T, e);//a是指向结点e的指针
        if (a && a->rchild)//T中存在结点e且e存在右孩子
            return a->rchild->data;//返回e的右孩子的值
    }
    return Nil;//其余情况返回空
}

Status DeleteChild(BiTree p, int LR){//二叉树T存在,p指向T中某个结点,LR为0或1,删除T中p所指结点左或右子树
    if (p)//p不空
    {
        if (LR == 0)//删除左子树
            ClearBiTree(p->lchild);//清空p所指结点的左子树
        else//删除右子树
            ClearBiTree(p->rchild);//清空p所指结点的右子树
        return OK;
    }
    return ERROR;//p空,返回ERROR
}

void PostOrderTraverse(BiTree T, void(*visit)(TElemType)){//后序递归遍历T(利用队列),对每个结点调用函数visit一次且仅一次
    if (T)//T不空
    {
        PostOrderTraverse(T->lchild, visit);//先后序遍历左子树
        PostOrderTraverse(T->rchild, visit);//再后序遍历右子树
        visit(T->data);//最后访问根结点
    }
}

void LevelOrderTraverse(BiTree T, void(*visit)(TElemType)){//层序递归遍历T(利用队列),对每个结点调用visit函数一次且仅一次
    LinkQueue q;
    QElemType a;
    if (T)//T非空
    {
        InitQueue(q);//初始化队列
        EnQueue(q, T);//根指针入队
        while (!QueueEmpty(q))//队列不空
        {
            DeQueue(q, a);//出队元素(指针),赋给a
            visit(a->data);//访问a所指根结点
            if (a->lchild != NULL)//a有左孩子
                EnQueue(q, a->lchild);//入队a的左孩子
            if (a->rchild != NULL)//a有右孩子
                EnQueue(q, a->rchild);//入队a的右孩子
        }
        printf("\n");
    }
}

void CreateBiTree(BiTree &T){//构造二叉链表表示的二叉树T,变量Nil表示空(子)树
    TElemType ch;
    scanf("%d", &ch);//输入结点的值
    if (ch == Nil)//结点的值为空
        T = NULL;
    else//结点的值不为空
    {
        T = (BiTree)malloc(sizeof(BiTNode));//生成根结点
        if (!T)
            exit(OVERFLOW);
        T->data = ch;//将值赋给T所指结点
        CreateBiTree(T->lchild);//递归构造左子树
        CreateBiTree(T->rchild);//递归构造右子树
    }
}

TElemType Parent(BiTree T, TElemType e){//若e是T的非根结点,则返回它的双亲,否则返回“空”
    LinkQueue q;
    QElemType a;
    if (T)//非空树
    {
        InitQueue(q);//初始化队列
        EnQueue(q, T);//树根指针入队
        while (!QueueEmpty(q))//队不空
        {
            DeQueue(q, a);//出队,队列元素赋给a
            if (a->lchild && a->lchild->data == e || a->rchild && a->rchild->data == e)//找到e(是其左孩子或右孩子)
                return a->data;//返回e的双亲的值
            else//未找到e,则入队其左右孩子指针(如果非空)
            {
                if (a->lchild)//a有左孩子
                    EnQueue(q, a->lchild);//入队左孩子指针
                if (a->rchild)//a有右孩子
                    EnQueue(q, a->rchild);//入队右孩子指针
            }
        }
    }
    return Nil;//树空或未找到e
}

TElemType LeftSibling(BiTree T, TElemType e){//返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回“空”
    TElemType a;
    BiTree p;
    if (T)//非空树
    {
        a = Parent(T, e);//a为e的双亲
        if (a != Nil)//找到e的双亲
        {
            p = Point(T, a);//p为指向结点a的指针
            if (p->lchild && p->rchild && p->rchild->data == e)//p存在左右孩子且右孩子是e
                return p->lchild->data;//返回p的左孩子(e的左兄弟)
        }
    }
    return Nil;//其余情况返回空
}

TElemType RightSubling(BiTree T, TElemType e)   {//返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回“空”
    TElemType a;
    BiTree p;
    if (T)//非空树
    {
        a = Parent(T, e);//a为e的双亲
        if (a!= Nil)//找到e的双亲
        {
            p = Point(T, a);//p为指向结点a的指针
            if (p->lchild && p->rchild && p->lchild->data == e)//p存在左右孩子且左孩子是e
                return p->rchild->data;//返回p的右孩子(e的右兄弟)
        }
    }
    return Nil;//其余情况返回空
}

Status InsertChild(BiTree p, int LR, BiTree c){//二叉树存在,p指向T中某个结点,LR为0或1,非空二叉树c与T不相交且右子树为空,插入c为T中p所指结点的左右子树,p所指结点的原有左或右子树则成为c的右子树
    if (p)//p不空
    {
        if (LR == 0)//把二叉树c插为p所指结点的左子树
        {
            c->rchild = p->lchild;//p所指结点的原有左子树或成为c的右子树
            p->lchild = c;//二叉树c成为p的左子树
        }
        else//LR==1,把二叉树c插为p所指结点的右子树
        {   
            c->rchild = p->rchild;//p所指结点的原有右子树成为c的右子树
            p->rchild = c;//二叉树c成为p的右子树
        }
        return OK;
    }
    return ERROR;//p空
}

typedef BiTree SElemType;
void InOrderTraverse1(BiTree T, void(*visit)(TElemType)){//中序遍历二叉树T的非递归算法(利用栈),对每个数据调用visit函数
    SqStack S;
    InitStack(S);//初始化栈S
    while (T || StackEmpty(S))//当二叉树T不空或者栈不空
    {
        if (T)//二叉树T不空
        {//根指针入栈,遍历左子树
            Push(T);//入栈根指针
            T = T->lchild;//T指向其左孩子
        }
        else//根指针退栈
        {
            Pop(S, T);//出栈根指针
            visit(T->data);//访问根结点
            T = T->rchild;//T指向其右孩子
        }
    }
    printf("\n");
}

void InOrderTraverse2(BiTree T, void(*visit)(TElemType)){
    SqStack S;
    BiTree p;
    InitStack(S);//初始化栈
    Push(S, T);//根指针入栈(无论空否)
    while (!StackEmpty(S))//栈不空
    {
        while (GetTop(S, p) && p)//栈顶元素不为空指针
            Push(S, p->lchild);//向左走到尽头,入栈左孩子指针
        Pop(S, p);//空指针退栈,退掉最后入栈的空指针
        if (!StackEmpty(S))//访问结点,向右一步
        {
            Pop(S, p);//弹出栈顶元素(非空指针)
            visit(p->data);//访问刚弹出的结点(目前栈顶元素的左孩子)
            Push(S, p->rchild);//入栈其右孩子指针
        }
    }
    printf("\n");
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

二叉树的二叉链表表示和实现

标签:c   数据结构   计算机专业   考研   

原文地址:http://blog.csdn.net/zhou554291911/article/details/47790283

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!