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语言 结构体数组详解及示例代码 结构体是C语言中最为基础的数据结构之一,它可以将多个数据类型组合成一个整体,方便地进行访问和管理。而结构体数组则是将多个相同结构体类型的变量按照一定规律排列在一起的一种数据结构。本文将详细讲解C语言中结构体数组的使用方法及示例代码。 定义结构体 首先,我们需要定义一个结构体类型。结构体类型需要指定名称、成员变量及其数据类型:…

    数据结构 2023年5月17日
    00
  • Android随手笔记44之JSON数据解析

    Android随手笔记44之JSON数据解析 1. JSON数据的基本概念 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于 JavaScript 的一个子集。JSON 格式最初是为了解决 JavaScript 程序通过 AJAX 传输数据时的数据交换格式问题而出现的,但是现在已经成为了一种通用的数据格式。…

    数据结构 2023年5月17日
    00
  • go语言数据结构之前缀树Trie

    前缀树Trie 前缀树Trie是一种树形数据结构,被用于快速查找内存中的字符串数据。它非常适合存储大量的字符串,并且能够非常快速的查找以一个指定的字符串前缀开头的全部字符串。 相关术语 在学习前缀树Trie之前,需要掌握一下相关术语: 根节点:Trie树的根节点,代表空字符串。 边:连接两个节点的线,代表一个字符。 节点:表示一个字符串,可能是某个字符串的结…

    数据结构 2023年5月17日
    00
  • JavaScript数据结构之广义表的定义与表示方法详解

    JavaScript数据结构之广义表的定义与表示方法详解 什么是广义表 广义表是一种包含了无数元素的数据结构,可以是元素或者嵌套的子表。广义表可以表示为: $\quad\quad\quad GL = (a_0,a_1,…,a_n)$ 其中$a_i$可以是元素或者一个子表,如果$a_i$为一个子表,那么$a_i$本身也是一个广义表。广义表中,第一个元素$a…

    数据结构 2023年5月17日
    00
  • java 数据结构之堆排序(HeapSort)详解及实例

    Java 数据结构之堆排序(HeapSort)详解及实例 什么是堆排序 堆排序是一种树形选择排序,它的特点是不需要建立临时数组存放已排序的元素,而是直接在原数组上进行排序,因此空间复杂度比较小,时间复杂度为 $O(nlogn)$。 堆排序中需要用到的数据结构是堆,它是一种特殊的二叉树。堆分为大根堆和小根堆,大根堆满足任何一个非叶子节点的值都不小于其子节点的值…

    数据结构 2023年5月17日
    00
  • C语言数据结构之单链表存储详解

    C语言数据结构之单链表存储详解 什么是单链表 链表是一种非顺序存储的数据结构,其每个节点都保存下一个节点的地址。单链表是最简单的链表,每个节点只包含下一个节点的地址。 单链表节点的定义 单链表的节点定义一般包括两个部分:数据域和指针域。数据域存放节点的数据,指针域存放下一个节点的地址。 以下是单链表节点的定义: typedef struct node { i…

    数据结构 2023年5月17日
    00
  • 第14届蓝桥杯C++B组省赛题解(A-J)(更新完毕)

    目录 A. 日期统计 题目内容 思路 代码 答案 B.01 串的熵 题目内容 思路 代码 答案 C.冶炼金属 题目内容 输入格式 输出格式 输入样例 输出样例 思路 代码 D.飞机降落 题目内容 输入格式 输出格式 输入样例 输出样例 思路 代码 E.接龙数列 题目内容 输入格式 输出格式 输入样例 输出样例 思路 代码 F.岛屿数量 题目内容 输入格式 输…

    算法与数据结构 2023年4月25日
    00
  • js处理层级数据结构的方法小结

    “JS处理层级数据结构的方法小结”是一篇讲解JavaScript如何处理嵌套数据结构的文章。在现代的web应用中,嵌套结构是非常常见的,比如JSON数据、树形数据等。以下是对该话题的详细讲解: 1. 嵌套数据结构的概念 指的是包含嵌套关系的数据类型,如数组、对象、树形结构、XML文档等。这些类型之间有着固定层级关系,包含多个层次的数据。嵌套数据结构的处理,往…

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