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

二叉树的顺序表示和实现

时间:2015-08-07 20:10:50      阅读:144      评论:0      收藏:0      [点我收藏+]

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

二叉树的顺序存储结构

#define MAX_TREE_SIZE 100//二叉树的最大结点数
typedef char TElemType;
typedef TElemType SqBiTree[MAX_TREE_SIZE];//0号单元存储根结点

struct position//新增
{
    int level, order;//结点所在的层,在该层的序号(按满二叉树计算)
};

// function
    typedef int TElemType;
    TElemType Nil = 0;

二叉树的顺序存储的基本操作

void visit(TElemType e){
    printf("%d ", e);
}

#define ClearBiTree InitBiTree
#define DestroyBiTree InitBiTree

void InitBiTree(SqBiTree T){//构造空二叉树T。因为T是数组名,不需要&
    int i;
    for (i = 0; i < MAX_TREE_SIZE; i++)
        T[i] = Nil;//初值为空
}

void CreateBiTree(SqBiTree T){//按层序次序输入二叉树中结点的值,构造顺序存储的二叉树T
    int i = 0;
    InitBiTree(T);//构造空二叉树

    printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数<=%d:\n", MAX_TREE_SIZE);
    while (1)//永真循环
    {
        scanf("%d", &T[i]);//按层序依次输入
        if (T[i] == 999)//输入结束
        {
            T[i] = Nil;//恢复为空结点
            break;//跳出循环
        }
        i++;//计数+1
    }

    for (i = 1; i < MAX_TREE_SIZE; i++)//从第2个(非根)结点开始检查
    if (T[i] != Nil && T[(i + 1) / 2 - 1] == Nil){//此结点不空但无双亲
        printf("出现无双亲的非根结点%d\n", T[i]);
        exit(OVERFLOW);
    }
}

Status BiTreeEmpty(SqBiTree T){
    if (T[0] == Nil)//根结点为空,则树空
        return TRUE;
    else
        return FALSE;
}

int BiTreeDepth(SqBiTree T){
    int i;
    if (T[0] == Nil)//根结点为空,则树空
        return 0;//空数的深度为0
    for (i = MAX_TREE_SIZE - 1; i >= 0; i--)//从数组的后面开始找起
        if (T[i] != Nil)//找到最后一个结点,其序号为i
            break;
    return (int)(log(i + 1.0) / log(2.0) + 1.1);//序号为i的结点的深度就是树的深度
}

Status Root(SqBiTree T, TElemType &e){
    if (BiTreeEmpty(T))//T空
        return ERROR;
    else
    {
        e = T[0];
        return OK;
    }
}

TElemType Value(SqBiTree T, position e){
    return T[int(pow(2.0, e.level - 1) + e.order - 2)];//返回处于位置e(层,本层序号)的结点的值
}

Status Assign(SqBiTree T, position e, TElemType value){//给处于位置e(层,本层序号)的结点赋新值value
    int i = int(pow(2.0, e.level - 1) + e.order - 2);//将层、本层序号转为数组的序号
    if (i != 0 && value != Nil && T[(i + 1) / 2 - 1] == Nil)//不是根结点,值非空,但双亲为空
        return ERROR;
    else if (value == Nil && T[i * 2 + 1] != Nil || T[i * 2 + 2] != Nil)//给双亲赋空值但有孩子结点
        return ERROR;
    T[i] = value;//以上两种情况之外,给结点赋新值
    return OK;
}

TElemType Parent(SqBiTree T, TElemType e){//若e是T的非根结点,则返回它的双亲,否则返回“空”
    int i;
    if (T[0] == Nil)//空树
        return Nil;//返回“空”
    for (i = 1; i <=MAX_TREE_SIZE - 1; i++)//从二叉树的第2个结点开始查找
        if (T[i] == e)//找到e
            return T[(i + 1) / 2 - 1];//返回其双亲结点的值
    return Nil;//未找到e
}

TElemType LeftChild(SqBiTree T, TElemType e){
    int i;
    for (i = 0; i < (MAX_TREE_SIZE - 2)/2; i++)//从T的第1个结点到最后一个可能有左孩子的结点
        if (T[i] == e)//找到e
            return T[i * 2 + 2];//返回e的左孩子的值
        return Nil;//未找到e
}

TElemType RightChild(SqBiTree T, TElemType e){
    int i;
    for (i = 0; i < (MAX_TREE_SIZE - 3)/2; i++)//从T的第1个结点到最后一个可能有右孩子的结点
        if (T[i] == e)//找到e
            return T[i * 2 + 2];//返回e的右孩子的值
    return Nil;//未找到e
}

TElemType  LeftSibling(SqBiTree T, TElemType e){//返回e的左兄弟,若e是T的左孩子或无左兄弟,返回“空”
    int i;
    if (T[0] == Nil)//空树
        return Nil;//返回“空”
    for (i = 1; i <= MAX_TREE_SIZE - 1; i++)//从二叉树T的第2个结点开始查找
        if (T[i] == e && i % 2 == 0)//找到e且其序号为偶数(是右孩子)
            return T[i - 1];//返回e的左兄弟的值
        return Nil;//未找到e
}

TElemType  RightSibling(SqBiTree T, TElemType e){//返回e的右兄弟,若e是T的右孩子或无右兄弟,返回“空”
    int i;
    if (T[0] == Nil)//空树
        return Nil;//返回“空”
    for (i = 1; i <= MAX_TREE_SIZE - 2; i++)//从二叉树T的第2个结点开始查找
    if (T[i] == e && i % 2)//找到e且其序号为偶数(是右孩子)
        return T[i + 1];//返回e的左兄弟的值
    return Nil;//未找到e
}

void Move(SqBiTree q, int j, SqBiTree T, int i){//把从q的j结点开始的子树移为从T的i结点开始的子树
    if (i >= MAX_TREE_SIZE)//i结点超出了存储范围
        exit(OVERFLOW);
    if (q[2 * j + 1] != Nil)//q的左子树不空
        Move(q, (2 * j + 1), T, (2 * i + 1));//把q的j结点的左子树移为T的i结点的左子树
    if (q[2 * j + 2] != Nil)//q的右子树不空
        Move(q, (2 * j + 2), T, (2 * i + 2));//把q的j结点的右子树移为T的i结点的右子树
    T[i] = q[j];//把q的j结点移为T的i结点
    q[j] = Nil;//把q的j结点置空
}

void InsertChild(SqBiTree T, TElemType p, int LR, SqBiTree c){
    //初始条件:二叉树T存在,p是T中某个结点的值,LR为0或1,非空二叉树c与T不相交且右子树为空
    //操作结果:根据LR为0或1,插入c为T中p结点的左或右子树。p结点的原有左或右子树则成为c的右子树
    int j, k;
    for (j = 0; j < int(pow(2.0, BiTreeDepth(T)) - 1); j++)//查找p的序号
        if (T[j] == p)//j为p的序号
            break;
    k = 2 * j + 1 + LR;//k为p的左或右孩子的序号
    if (T[k] != Nil)//p原来的左或右孩子不空
        Move(T, k, c, 2);//把从T的k结点开始的子树移为c的右子树
    Move(c, 0, T, k);//把树c移为从T的k结点开始的子树
}

Status DeleteChild(SqBiTree T, position p, int LR){
    int i;
    Status k = OK;//队列不空的标志
    LinkQueue q;
    InitQueue(q);//初始化队列,用以存放待删除的结点
    i = (int)pow(2.0, p.level - 1) + p.order - 2;//将层、本层序号转为数组的序号
    if (T[i] == Nil)//此结点空
        return ERROR;
    i = i * 2 + 1 + LR;//将待删除子树的根结点在数组中的序号
    while (k)
    {
        if (T[2 * i + 1] != Nil)//左结点不空
            EnQueue(q, 2 * i + 1);//入队左结点序号
        if (T[2 * i + 2] != Nil)//右结点不空
            EnQueue(q, 2 * i + 2);//入队右结点序号
        T[i] = Nil;//删除此结点
        k = DeQueue(q, i);//出队结点的序号,其值赋给i,成功(队列不空)返回OK,否则返回ERROR
    }
    return OK;
}

void(*VisitFunc)(TElemType);//函数变量
void PreTraverse(SqBiTree T, int e){  //递归先序遍历二叉树中T序号为e的子树,PreOrderTraverse()调用
    VisitFunc(T[e]);//访问树T中序号为e的结点
    if (T[2 * e + 1] != Nil)//序号为e的结点的左子树不空
        PreTraverse(T, 2 * e + 1);//递归先序遍历树T中序号为e的结点的左子树
    if (T[2 * e + 2] != Nil)//序号为e的结点的右子树不空
        PreTraverse(T, 2 * e + 2);//递归先序遍历树T中序号为e的结点的右子树
}

void PreOrderTraverse(SqBiTree T, void(*visit)(TElemType)){//先序遍历T,对每个结点调用函数visit一次且仅一次
    VisitFunc = visit;
    if (!BiTreeEmpty(T))//树不空
        PreTraverse(T, 0);//递归先序遍历树T中序号为0的树(树T自身)
    printf("\n");
}

void InTraverse(SqBiTree T, int e){//递归中序遍历二叉树T中序号为e的子树,InOrderTraverse()调用
    if (T[2 * e + 1] != Nil)//序号为e的结点的左子树不空
        InTraverse(T, 2 * e + 1);//递归中序遍历树T中序号为e的结点的左子树
    VisitFunc(T[e]);//访问树T中序号为e的结点
    if (T[2 * e + 2] != Nil)//序号为e的结点的右子树不空
        InTraverse(T, 2 * e + 2);//递归中序遍历树T中序号为e的结点的右子树
}

void InOrderTraverse(SqBiTree T, void(*visit)(TElemType)){//中序遍历T,对每个结点调用函数visit一次且仅一次
    VisitFunc = visit;
    if (!BiTreeEmpty(T))//树不空
        InTraverse(T, 0);//递归中序遍历树T中序号为0的树(树T自身)
    printf("\n");
}

void PostTraverse(SqBiTree T, int e){//递归后序遍历二叉树T中序号为e的子树,PostOrderTraverse()调用
    if (T[2 * e + 1] != Nil)//序号为e的结点的左子树不空
        PostTraverse(T, 2 * e + 1);//递归后序遍历树T中序号为e的结点的左子树
    if (T[2 * e + 2] != Nil)//序号为e的结点的右子树不空
        PostTraverse(T, 2 * e + 2);//递归后序遍历树T中序号为e的结点的右子树
    VisitFunc(T[e]);//访问树T中序号为e的结点
}

void PostOrderTraverse(SqBiTree T, void(*visit)(TElemType)){//后序遍历T,对每个结点调用函数visit一次且仅一次
    VisitFunc = visit;
    if (!BiTreeEmpty(T))//树不空
        PostTraverse(T, 0);//递归后序遍历树T中序号为0的树(树T本身)
    printf("\n");
}

void LevelOrderTraverse(SqBiTree T, void(*visit)(TElemType)){//层序遍历二叉树T
    int i = MAX_TREE_SIZE - 1, j;
    while (T[i] == Nil)
        i--;//找到最后一个非空结点的序号
    for (j = 0; j <= i; j++)//从根结点起,按层序遍历二叉树
        if (T[j] != Nil)
            visit(T[j]);//只遍历非空的结点
        printf("\n");
}

void Print(SqBiTree T){//逐层、按本层序号输出二叉树T
    int j, k;
    position p;
    TElemType e;
    for (j = 1; j <= BiTreeDepth(T); j++)//j为当前层
    {
        printf("第%d层:", j);
        p.level = j;//当前结点所在层
        for (k = 1; k <= pow(2.0, j - 1); k ++)
        {
            p.order = k;//当前结点在本层的顺序
            e = Value(T, p);//该结点的值赋给e
            if (e != Nil)//e非空
                printf("%d:%d", k, e);//输出在本层的顺序及值
        }
        printf("\n");
    }
}   

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

二叉树的顺序表示和实现

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

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

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