二叉树(顺序结构实现)

二叉树:是n(n > 0)个节点的有限集合,该集合可为空,也可由一个根节点和两棵互不相交的节点(左子树、右子树)的二叉树构成。

二叉树的性质

性质1:在二叉树的第i层上至多有2^(i - 1)个节点(i>=1)。
性质2:深度为k的二叉树至多有2^k - 1个节点(k>=1)。
性质3:对任何一棵二叉树T,如果其叶子节点数为n0,度为2的节点数为n2,那么n0 = n2 + 1。
性质4:具有n个节点的完全二叉树的深度为⌊Log2n⌋ + 1(⌊x⌋表示不大于x的最大整数,向下取整)。
性质5:对于完全二叉树来说,有如下结论:

  1. 如果i = 1,则节点是树的根,无双亲;如果i >= 1,则该节点的双亲为⌊i / 2⌋。
  2. 如果2i > n,则节点i无左孩子;否则其左孩子为节点2i。
  3. 如果2i + 1 > n,则节点i无右孩子;否则其右孩子为节点2i + 1。
二叉树示意图
二叉树顺序存储结构示意图

实现代码如下:

// 二叉树(顺序结构实现)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define TRUE 1   // 结果为真
#define FALSE 0   // 结果为假
#define OK 1      // 执行成功
#define ERROR 0   // 执行失败

#define MAX_TREE_SIZE 100 // 二叉树最大节点数

typedef int Status; // 函数返回结果类型
typedef int ElemType; // 树节点类型
typedef ElemType SqBiTree[MAX_TREE_SIZE]; // 二叉树结构(下标为0的元素为根节点)

// 位置结构
typedef struct {
    int level, order; // 节点的层数,本层序号(按满二叉树计算)
} Position;

ElemType Nil = 0; // 表示该节点为空

/**
 * 初始化二叉树
 * @param T 二叉树
 * @return 执行状态
 */
Status InitBiTree(SqBiTree T) {
    int i; // 用于遍历元素

    // 将数的所有节点置空
    for (i = 0; i < MAX_TREE_SIZE; i++) {
        T[i] = Nil;
    }
    return OK;
}

/**
 * 按层次构建二叉树
 * @param T 二叉树
 * @return 执行状态
 */
Status CreateBiTree(SqBiTree T) {
    int i = 0; // 用于遍历元素

    printf("请按层序输入节点的值(整形),0表示空节点,输入999结束。节点数<= %d\n", MAX_TREE_SIZE);
    // 往树中存储1到10这十个数字
    while (i < 10) {
        T[i] = i + 1; // 为节点赋值

        // 进行防出错判断
        if (i != 0 && T[(i + 1) / 2 - 1] == Nil && T[i] != Nil) {
            printf("出现无双亲的非根节点%d\n", T[i]);
            exit(ERROR); // 错误结束程序
        }
        i++; // i加1
    }
    // 下标i为到达树的最后节点
    while (i < MAX_TREE_SIZE) {
        T[i] = Nil; // 将剩下的节点赋值为空
        i++;
    }
    return OK;
}

/***
 * 清空二叉树(与初始化二叉树一样)
 */
#define ClearBiTree InitBiTree

/**
 * 判断二叉树是否为空
 * @param T 二叉树
 * @return 树是否为空
 */
Status BiTreeEmpty(SqBiTree T) {
    // 树的根节点为空
    if (T[0] == Nil) {
        return TRUE;
    } else {
        return FALSE;
    }
}

/**
 * 获取树的深度
 * @param T 二叉树
 * @return 执行状态
 */
int BiTreeDepth(SqBiTree T) {
    int i, j = -1; // i是计算树的最后一个元素的下标,j是计算树的层数
    // 找到树的最后一个元素
    for (i = MAX_TREE_SIZE - 1; i >= 0; i--) {
        if (T[i] != Nil) {
            break;
        }
    }
    i++; // 树的节点数加1
    /*
     * 层数 该层节点数
     *   1      1
     *   2      2
     *   3      4
     *   4      8
     *   若i = 7,因为4 < 7 < 8,所以该节点在第4层
     */
    do {
        j++; // 计算层数
    } while (i >= powl(2, j)); // 2的j次方
    return j; // 返回节点的层数
}

/**
 * 获取根节点的值
 * @param T 二叉树
 * @param e 用来获取根节点的值
 * @return 执行状态
 */
Status Root(SqBiTree T, ElemType *e) {
    // 二叉树为空,获取失败
    if (BiTreeEmpty(T)) {
        return ERROR;
    } else {
        *e = T[0]; // 将根节点的值赋值给e
        return OK;
    }
}

/**
 * 返回二叉树中该位置对应的值
 * @param T 二叉树
 * @param e 位置
 * @return 该位置的值
 */
ElemType Value(SqBiTree T, Position e) {
    return T[(int) powl(2, e.level - 1) + e.order - 2];
}

/**
 * 给二叉树对应位置的节点重新赋值
 * @param T 二叉树
 * @param e 重新赋值的节点
 * @param value 新值
 * @return 执行状态
 */
Status Assign(SqBiTree T, Position e, ElemType value) {
    // 获取将赋值节点在数组中的下标
    int i = (int)powl(2, e.level - 1) + e.order - 2;

    // 给叶子赋非空值,但双亲节点为空,赋值失败
    if (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; // 给对应节点赋值为value
    return OK;
}

/**
 * 获取值为e的元素的双亲节点(无该节点则返回Nil)
 * @param T 二叉树
 * @param e 元素值
 * @return 值为e的元素的双亲节点
 */
ElemType Parent(SqBiTree T, ElemType e) {
    int i; // 用来遍历元素

    // 根节点为空,无双亲节点
    if (T[0] == Nil) {
        return Nil;
    }

    // 从树的第二层起遍历元素
    for (i = 1; i <= MAX_TREE_SIZE - 1; i++) {
        // 找到值为e的节点
        if (T[i] == e) {
            // 返回值为e节点的双亲节点
            return T[(i + 1) / 2 - 1];
        }
    }
    return Nil; // 未找到值为e元素的双亲节点
}

/**
 * 获取值为e的元素的左孩子
 * @param T 二叉树
 * @param e 元素e
 * @return 值为e的元素的左孩子
 */
ElemType LeftChild(SqBiTree T, ElemType e) {
    int i; // 用来遍历元素

    // 根节点为空,无双亲节点
    if (T[0] == Nil) {
        return Nil;
    }

    // 从根节点开始遍历树的节点
    for (i = 0; i <= MAX_TREE_SIZE - 1; i++) {
        // 找到值为e的节点
        if (T[i] == e) {
            // 返回值为e节点的左孩子
            return T[i * 2 + 1];
        }
    }
    return Nil; // 未找到值为e元素的左孩子
}

/**
 * 获取值为e的元素的右孩子
 * @param T 二叉树
 * @param e 元素e
 * @return 值为e的元素的右孩子
 */
ElemType RightChild(SqBiTree T, ElemType e) {
    int i; // 用来遍历元素

    // 根节点为空,无双亲节点
    if (T[0] == Nil) {
        return Nil;
    }

    // 从根节点开始遍历树的节点
    for (i = 0; i <= MAX_TREE_SIZE - 1; i++) {
        // 找到值为e的节点
        if (T[i] == e) {
            // 返回值为e节点的右孩子
            return T[i * 2 + 2];
        }
    }
    return Nil; // 未找到值为e元素的右孩子
}

/**
 * 获取值为e的元素的左兄弟
 * @param T 二叉树
 * @param e 元素e
 * @return 值为e的元素的左兄弟
 */
ElemType LeftSibling(SqBiTree T, ElemType e) {
    int i; // 用来遍历元素

    // 根节点为空,无双亲节点
    if (T[0] == Nil) {
        return Nil;
    }

    // 从第二层开始遍历树的节点
    for (i = 1; i <= MAX_TREE_SIZE - 1; i++) {
        // 找到值为e的节点,并且序号为偶数(是右孩子)
        if (T[i] == e && i % 2 == 0) {
            // 返回值为e节点的左兄弟
            return T[i - 1];
        }
    }
    return Nil; // 未找到值为e元素的左兄弟
}

/**
 * 获取值为e的元素的右兄弟
 * @param T 二叉树
 * @param e 元素e
 * @return 值为e的元素的右兄弟
 */
ElemType RightSibling(SqBiTree T, ElemType e) {
    int i; // 用来遍历元素

    // 根节点为空,无双亲节点
    if (T[0] == Nil) {
        return Nil;
    }

    // 从第二层开始遍历树的节点
    for (i = 1; i <= MAX_TREE_SIZE - 1; i++) {
        // 找到值为e的节点,并且序号为偶数(是右孩子)
        if (T[i] == e && i % 2 == 1) {
            // 返回值为e节点的右兄弟
            return T[i + 1];
        }
    }
    return Nil; // 未找到值为e元素的右兄弟
}

/**
 * 打印单个元素
 * @param e 元素值
 * @return 执行状态
 */
Status visit(ElemType e) {
    printf("%d ", e);
    return OK;
}

/**
 * 先序遍历二叉树
 * @param T 二叉树
 * @param i 元素下标
 */
void PreTraverse(SqBiTree T, int i) {
    visit(T[i]); // 打印该元素的值

    // 左子树不空
    if (T[2 * i + 1] != Nil) {
        PreTraverse(T, 2 * i + 1); // 遍历左子树
    }

    // 右子树不空
    if (T[2 * i + 2] != Nil) {
        PreTraverse(T, 2 * i + 2); // 遍历右子树
    }
}

/**
 * 先序遍历辅助函数
 * @param T 二叉树
 * @return 执行状态
 */
Status PreOrderTraverse(SqBiTree T) {
    // 二叉树非空
    if (!BiTreeEmpty(T)) {
        PreTraverse(T, 0); // 先序遍历二叉树
    }
    printf("\n");
    return OK;
}

/**
 * 中序遍历二叉树
 * @param T 二叉树
 * @param i 元素下标
 */
void InTraverse(SqBiTree T, int i) {

    // 左子树不空
    if (T[2 * i + 1] != Nil) {
        InTraverse(T, 2 * i + 1); // 遍历左子树
    }

    visit(T[i]); // 打印该元素的值

    // 右子树不空
    if (T[2 * i + 2] != Nil) {
        InTraverse(T, 2 * i + 2); // 遍历右子树
    }
}

/**
 * 中序遍历辅助函数
 * @param T 二叉树
 * @return 执行状态
 */
Status InOrderTraverse(SqBiTree T) {
    // 二叉树非空
    if (!BiTreeEmpty(T)) {
        InTraverse(T, 0); // 先序遍历二叉树
    }
    printf("\n");
    return OK;
}

/**
 * 后序遍历二叉树
 * @param T 二叉树
 * @param i 元素下标
 */
void PostTraverse(SqBiTree T, int i) {

    // 左子树不空
    if (T[2 * i + 1] != Nil) {
        PostTraverse(T, 2 * i + 1); // 遍历左子树
    }

    // 右子树不空
    if (T[2 * i + 2] != Nil) {
        PostTraverse(T, 2 * i + 2); // 遍历右子树
    }

    visit(T[i]); // 打印该元素的值
}

/**
 * 后序遍历辅助函数
 * @param T 二叉树
 * @return 执行状态
 */
Status PostOrderTraverse(SqBiTree T) {
    // 二叉树非空
    if (!BiTreeEmpty(T)) {
        PostTraverse(T, 0); // 先序遍历二叉树
    }
    printf("\n");
    return OK;
}

/**
 * 层序遍历二叉树
 * @param T 二叉树
 */
void LevelOrderTraverse(SqBiTree T) {
    int i = MAX_TREE_SIZE - 1, j; // i用来计算二叉树最后一个节点的位置,j用来遍历元素

    // 找到二叉树最后一个元素的下标
    while (T[i] == Nil) {
        i--;
    }

    // 从根节点遍历二叉树的值
    for (j = 0; j <= i; j++) {
        if (T[j] != Nil) {
            visit(T[j]);
        }
    }
    printf("\n");
}

/**
 * 遍历二叉树的所有节点
 * @param T 二叉树
 */
void Print(SqBiTree T) {
    int j, k; // j用来表示层数,k用来表示元素是该层的第几个元素

    Position p; // 位置结构
    ElemType e; // 节点元素值

    // 从第一层开始遍历到最后二叉树的一层
    for (j = 1; j <= BiTreeDepth(T); j++) {
        printf("第%d层:\n", j);
        // powl(2, j-1)可计算该层有多少个节点
        for (k = 1; k <= powl(2, j - 1); k++) {
            p.level = j; // 设置本层层数
            p.order = k; // 设置本层序号
            e = Value(T, p); // 获取树中该位置的值
            if (e != Nil) { // 元素不为空节点
                printf("%d:%d ", k, e);
            }
            printf("\n");
        }
    }
}

int main() {
    Status status; // 执行状态
    ElemType e; // 用来获取二叉树节点的值
    Position p; // 设置节点的位置
    SqBiTree T; // 二叉树

    /*** 二叉树的初始化 ***/
    InitBiTree(T); // 初始化二叉树
    CreateBiTree(T); // 按层次构建二叉树
    printf("建立二叉树后,树是否为空:%s;树的深度为:%d\n", BiTreeEmpty(T) == TRUE ? "是" : "否", BiTreeDepth(T));

    /*** 获取二叉树根的值 ***/
    status = Root(T, &e); // 获取树根的值e

    printf("status=%d\n", status);
    if (status == OK) { // 根节点有值
        printf("二叉树根的值为:%d\n", e);
    } else {
        printf("二叉树为空\n");
    }

    /*** 前序遍历二叉树 ***/
    printf("前序遍历二叉树:\n");
    PreOrderTraverse(T);

    /*** 中序遍历二叉树 ***/
    printf("中序遍历二叉树:\n");
    InOrderTraverse(T);

    /*** 后序遍历二叉树 ***/
    printf("后序遍历二叉树:\n");
    PostOrderTraverse(T);

    /*** 层序遍历二叉树 ***/
    printf("层序遍历二叉树:\n");
    LevelOrderTraverse(T);

    /*** 获取指定节点的值 ***/
    // 设置节点p为第三层第二个元素
    p.level = 3;
    p.order = 2;

    e = Value(T, p); // 获取树中p节点的值
    printf("树中第三层第二个元素的值为:%d\n", e);

    /*** 修改指定节点的值 ***/
    e = 50;
    Assign(T, p, e); // 修改第三层第二个元素的值为50
    printf("修改节点后,层序遍历二叉树:\n");
    LevelOrderTraverse(T); // 层序遍历

    /*** 获取指定节点的双亲,左孩子,右孩子,左兄弟,右兄弟 ***/
    printf("节点50的双亲为:%d,左孩子为:%d,右孩子为:%d\n", Parent(T, e), LeftChild(T, e), RightChild(T, e));
    printf("节点50的左兄弟为:%d,右兄弟为:%d\n", LeftSibling(T, e), RightSibling(T, e));

    /*** 清空二叉树 ***/
    ClearBiTree(T); // 清空二叉树
    printf("清空二叉树后,二叉树是否为空:%s;树的深度为:%d\n", BiTreeEmpty(T) == TRUE ? "是" : "否", BiTreeDepth(T));

//    Print(T); // 遍历二叉树
}
运行结果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容