C语言数据结构系列之树的概念结构和常见表示方法

C语言数据结构系列之树的概念结构和常见表示方法

树是一种非线性数据结构,它由若干个节点构成,节点之间通过边来连接,具有层次关系。

树的基本概念和术语

  • 节点:树中的元素,它可以包含一个数据元素或多个数据元素,一个节点也可以称为一个分支节点。
  • 根节点:树的最上层节点,它没有父节点。
  • 叶子节点:没有子节点的节点称为叶子节点。
  • 父节点和子节点:父节点是某个节点的上一级节点,子节点是某个节点的下一级节点。
  • 兄弟节点:具有同一父节点的节点称为兄弟节点。
  • 子树:一个节点和它的子节点构成的树称为子树。

树的表示方法

双亲表示法

双亲表示法是通过每个节点存储它的父节点来表示树的关系。

#define MAX_TREE_SIZE 100
typedef struct{
    ElemType data; // 数据元素
    int parent; // 父节点位置
}PTNode;
typedef struct{
    PTNode nodes[MAX_TREE_SIZE]; // 双亲节点数组
    int r; // 树根位置
    int n; // 节点数目
}PTree;

使用双亲表示法时,需要遍历一次树找到每个节点的父节点并记录,这个过程会导致时间开销较大。

孩子表示法

孩子表示法是通过每个节点存储它的一个子节点指针,来表示树的关系。

#define MAX_TREE_SIZE 100
typedef struct CTNode{
    int child; // 子节点在数组中的位置
    struct CTNode *next; // 指向下一个子节点的指针
} *ChildPtr;

typedef struct{
    ElemType data; // 数据元素
    ChildPtr firstchild; // 子节点指针
}CTBox;

typedef struct{
    CTBox nodes[MAX_TREE_SIZE]; // 子节点数组
    int r; // 树根的位置
    int n; // 节点个数
}CTree;

使用孩子表示法时,需要为每个节点创造一个子节点指针,这可能会引起大量的空间浪费。另外,孩子表示法也需要对树进行遍历来找到每个节点的子节点。

孩子兄弟表示法

孩子兄弟表示法是通过每个节点存储它的第一个子节点和下一个兄弟节点,来表示树的关系。

typedef struct CSNode{
    ElemType data;
    struct CSNode *firstchild; // 指向第一个子节点的指针
    struct CSNode *nextsibling; // 指向下一个兄弟节点的指针
}CSNode, *CSTree;

使用孩子兄弟表示法时,一个节点可以快速地访问其第一个子节点和下一个兄弟节点,但也需要遍历树以找到某个节点的后代或兄弟节点。

树的遍历

树的遍历就是按照某种规则依次访问树中所有节点的过程。

先序遍历

先序遍历就是先访问根节点,再按照先序遍历的方式遍历左子树和右子树。在先序遍历中,根节点总是在第一个被访问。

void PreOrderTraverse(CSTree T){
    if(T){ // 树不为空
        visit(T); // 访问根节点
        PreOrderTraverse(T -> firstchild); // 对左子树进行遍历
        PreOrderTraverse(T -> nextsibling); // 对右子树进行遍历
    }
}

中序遍历

中序遍历就是先按中序遍历的方式遍历左子树,然后访问根节点,最后按照中序遍历的方式遍历右子树。在中序遍历中,根节点总是在左右子树之间被访问。

void InOrderTraverse(CSTree T){
    if(T){ // 树不为空
        InOrderTraverse(T -> firstchild); // 对左子树进行遍历
        visit(T); // 访问根节点
        InOrderTraverse(T -> nextsibling); // 对右子树进行遍历
    }
}

后序遍历

后序遍历就是先按照后序遍历的方式遍历左子树和右子树,然后访问根节点。在后序遍历中,根节点总是在左右子树被访问之后才被访问。

void PostOrderTraverse(CSTree T){
    if(T){ // 树不为空
        PostOrderTraverse(T -> firstchild); // 对左子树进行遍历
        PostOrderTraverse(T -> nextsibling); // 对右子树进行遍历
        visit(T); // 访问根节点
    }
}

示例一

以下是使用孩子表示法创建一棵具有5个节点的树,并通过先序遍历、中序遍历和后序遍历遍历树的过程:

CTree create_tree(){
    CTree T;
    T.n = 5;
    T.r = 0;
    T.nodes[0].data = 1;
    T.nodes[1].data = 2;
    T.nodes[2].data = 3;
    T.nodes[3].data = 4;
    T.nodes[4].data = 5;
    T.nodes[0].firstchild = &T.nodes[1]; // 节点1的第一个子节点是节点2
    T.nodes[1].firstchild = &T.nodes[2]; // 节点2的第一个子节点是节点3
    T.nodes[2].firstchild = NULL; // 节点3没有子节点
    T.nodes[3].firstchild = &T.nodes[4]; // 节点4的第一个子节点是节点5
    T.nodes[4].firstchild = NULL; // 节点5没有子节点
    return T;
}

void visit(CTree T){
    printf("%d ", T.data);
}

void traverse(){
    CTree T = create_tree();
    printf("先序遍历:");
    PreOrderTraverse(T.nodes[0].firstchild);
    printf("\n中序遍历:");
    InOrderTraverse(T.nodes[0].firstchild);
    printf("\n后序遍历:");
    PostOrderTraverse(T.nodes[0].firstchild);
}

这个示例创建了一棵具有5个节点的树,并分别使用先序遍历、中序遍历和后序遍历遍历树中的所有节点。

示例二

以下是使用孩子兄弟表示法创建一棵具有6个节点的二叉树,并通过先序遍历、中序遍历和后序遍历遍历二叉树的过程:

CSTree create_binary_tree(){
    CSTree T;
    T = (CSTree)malloc(sizeof(CSNode));
    T -> data = 1;
    T -> firstchild = (CSTree)malloc(sizeof(CSNode));
    T -> firstchild -> data = 2;
    T -> firstchild -> firstchild = (CSTree)malloc(sizeof(CSNode));
    T -> firstchild -> firstchild -> data = 4;
    T -> firstchild -> firstchild -> firstchild = NULL;
    T -> firstchild -> firstchild -> nextsibling = (CSTree)malloc(sizeof(CSNode));
    T -> firstchild -> firstchild -> nextsibling -> data = 5;
    T -> firstchild -> firstchild -> nextsibling -> firstchild = NULL;
    T -> firstchild -> firstchild -> nextsibling -> nextsibling = NULL;
    T -> firstchild -> nextsibling = (CSTree)malloc(sizeof(CSNode));
    T -> firstchild -> nextsibling -> data = 3;
    T -> firstchild -> nextsibling -> firstchild = NULL;
    T -> firstchild -> nextsibling -> nextsibling = NULL;
    return T;
}

void visit(CSTree T){
    printf("%d ", T -> data);
}

void traverse(){
    CSTree T = create_binary_tree();
    printf("先序遍历:");
    PreOrderTraverse(T);
    printf("\n中序遍历:");
    InOrderTraverse(T);
    printf("\n后序遍历:");
    PostOrderTraverse(T);
}

这个示例创建了一棵具有6个节点的二叉树,并分别使用先序遍历、中序遍历和后序遍历遍历树中的所有节点。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言数据结构系列之树的概念结构和常见表示方法 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言 数据结构中栈的实现代码

    下面是关于C语言中栈的实现代码的详细攻略: 栈的概念 栈是一种只能在一端进行插入或删除操作的线性数据结构,它具有后进先出(Last In First Out, LIFO)的特点。通俗的说,就像大家在平时搭积木那样,搭积木的时候总是从最下面开始往上搭,拿积木的时候总是从最上面的积木开始拿起,栈就是这么一个先进后出的数据结构。 栈的实现方法 栈的实现方法比较多,…

    数据结构 2023年5月17日
    00
  • Java 数据结构算法Collection接口迭代器示例详解

    Java 数据结构算法 Collection 接口迭代器示例详解 如果你正在学习 Java 编程,那么数据结构和算法一定是一个不可避免的话题。在 Java 中,Collection 框架提供了许多有用的接口和类来管理和操作集合。其中,迭代器 Iterator 是 Collection 中最重要的接口之一,它提供了对集合元素进行迭代的方法。本文将对 Java …

    数据结构 2023年5月17日
    00
  • Java数据结构之线段树的原理与实现

    Java数据结构之线段树的原理与实现 什么是线段树 线段树是一种基于分治思想的数据结构,它可以用来解决各种区间查询问题,例如区间求和、最大值、最小值等等。在算法竞赛和数据结构课程中,线段树被广泛应用,是一种非常实用的数据结构。 线段树的基本原理 线段树是一种二叉树,它的每个节点包含一个区间,叶子节点表示区间中的单个元素,非叶子节点表示区间的合并。 线段树的建…

    数据结构 2023年5月17日
    00
  • C语言实现带头结点的链表的创建、查找、插入、删除操作

    C语言实现带头结点的链表的创建、查找、插入、删除操作攻略 一、链表基本概念 链表是一种动态的数据结构,它可以在运行时动态地分配内存,支持数据的插入、删除等操作。链表(Linked List)由多个节点(Node)组成,每个节点包含两部分,一个是数据部分(Data),另一个是指向下一个节点的指针(Next)。 二、带头结点的链表 带头结点的链表是一种特殊的链表…

    数据结构 2023年5月17日
    00
  • Mysql 数据库结构及索引类型

    好的。首先,我们需要了解 Mysql 数据库的基本结构和索引类型。 Mysql 数据库结构 Mysql 数据库包含多个数据库,每个数据库包含多个数据表,每个数据表包含多个数据记录(或者叫行)。关键的概念包括数据库、数据表、数据记录以及 Mysql 列类型等。 数据库 Mysql 数据库是一个命名的容器,用于存储和管理相关数据表。可以使用以下 SQL 代码来创…

    数据结构 2023年5月17日
    00
  • Java数据结构之常见排序算法(上)

    Java数据结构之常见排序算法(上) 本篇文章将介绍常见的排序算法,包括冒泡排序、选择排序、插入排序、快速排序和归并排序。这些排序算法既是学习算法和数据结构的入门知识,也是在实际工作中常用的基础算法。 冒泡排序 冒泡排序是一种简单的排序算法,它的基本思想是从前往后依次比较相邻的两个元素,如果前面的元素比后面的元素大,则交换它们的位置,重复这个过程,每一轮比较…

    数据结构 2023年5月17日
    00
  • C++数据结构之红黑树的实现

    《C++数据结构之红黑树的实现》是一篇介绍红黑树实现的文章,通过本文,你可以了解到什么是红黑树以及如何实现红黑树。 什么是红黑树 红黑树是一种自平衡的二叉查找树,它具有良好的平衡性和查找性能。红黑树可以在O(log n)的时间内完成查找、插入和删除操作。 红黑树的一个重要性质是它的任何一个节点都有一个颜色(红色或黑色)属性。在插入、删除操作中,需要通过一定的…

    数据结构 2023年5月17日
    00
  • C语言 超详细总结讲解二叉树的概念与使用

    C语言 超详细总结讲解二叉树的概念与使用 1. 什么是二叉树? 二叉树是一种树状数据结构,其中每个节点最多有两个子节点,被称为左子节点和右子节点。具有以下几个特点: 每个节点最多有两个子节点; 左子节点可以为空,右子节点也可以为空; 二叉树的每个节点最多有一个父节点; 二叉树通常定义为递归模式定义,即每个节点都可以看做一棵新的二叉树。 2. 二叉树的遍历方式…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部