数据结构:树的存储结构

这篇具有很好参考价值的文章主要介绍了数据结构:树的存储结构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习树之前,我们已经了解了二叉树的顺序存储和链式存储,哪么我们如何来存储普通型的树结构的数据?如下图1:

数据结构:树的存储结构,数据结构,数据结构

如图1所示,这是一颗普通的树,我们要如何来存储呢?通常,存储这种树结构的数据的方法有3中:

  1. 双亲表示法。
  2. 孩子表示法。
  3. 孩子兄弟表示法。

双亲表示法

双亲表示法采用顺序表(也就是数组)存储普通树,核心思想:顺序存储各个节点的同时,给各个节点附加一个记录其父节点位置的变量。

注意:根结点没有父节点,因此根结点记录父节点位置的变量一般为-1。

例如,采用双亲表示法存储图1中的普通树,其存储状态如图2所示:

数据结构:树的存储结构,数据结构,数据结构

图2存储普通树转化为代码为:

#define MAX_SIZE 100//定义树中结点最大数量
typedef struct node{
    char data;//树中结点的数据
    int parent;//结点的父节点再数组中的位置下标
};

typedef struct {
    node arr[MAX_SIZE];//存放树中所有结点
    int n;//节点数
}Tree;

因此,存储图1中普通树的实现代码为:

#include "iostream"

using namespace std;
#define MAX_SIZE 100//定义树中结点最大数量
typedef struct node{
    char data;//树中结点的数据
    int parent;//结点的父节点再数组中的位置下标
};

typedef struct {
    node arr[MAX_SIZE];//存放树中所有结点
    int n;//节点数
}Tree;

Tree Init(Tree tree){
    cout << "请输入结点个数:" << endl;
    cin >> tree.n;
    cout << "请输入结点的值其双亲位于数组中的位置下标:" << endl;
    for(int i = 0; i < tree.n; i++){
        cin >> tree.arr[i].data >> tree.arr[i].parent;
    }
    return tree;
}

void FindParent(Tree tree){
    char a;
    bool IsFind = false;
    cout << "请输入要查询的节点值:" << endl;
    cin >> a;
    for(int i = 0; i < tree.n; i++){
        if(tree.arr[i].data == a){
            IsFind = true;
            cout << a << "的父节点为" << tree.arr[tree.arr[i].parent].data << ",存储位置下标为" << tree.arr[i].parent << endl;
            break;
        }
    }
}
int main(){
    Tree tree;
    for(int i = 0; i < MAX_SIZE; i++){
        tree.arr[i].parent = -1;
        tree.arr[i].data = ' ';
    }
    tree = Init(tree);
    FindParent(tree);
    return 0;
}

程序运行实例:

请输入结点个数:
10
请输入结点的值其双亲位于数组中的位置下标:
R -1
A 0
B 0
C 0
D 1
E 1
F 3
G 6
H 6
K 6
请输入要查询的节点值:
C
C的父节点为R,存储位置下标为0

孩子表示法

孩子表示法是采用“顺序表+链表”的组合结构,其存储过程是:从树的根结点开始,使用顺序表依次存储树中各个节点,需要注意的是,与双亲表示法不同,孩子表示法会给各个节点配备一个链表,用于存储各个节点的孩子节点位于顺序表中的位置。

如果孩子没有叶子节点,则该节点的链表为空链表。

例如,使用孩子表示法存储图3a中的树,则最终存储状况如图3b所示:

数据结构:树的存储结构,数据结构,数据结构

代码实现如下:

#include "iostream"

using namespace std;
#define MAX_SIZE 100//定义树中结点最大数量
typedef struct node{
    int child;//链表中每个结点存储的是数据再数组中存储的位置下标
    struct node *next;
};
typedef struct {
    char data;//结点的数据
    node * FirstChild;//孩子链表的头节点
}box;
typedef struct {
    box arr[MAX_SIZE];//存放树中所有结点
    int n, r;//节点数和树根的位置
}Tree;

Tree Init(Tree tree){
    cout << "请输入结点个数:";
    cin >> tree.n;
    for(int i = 0; i < tree.n; i++){
        cout << "输入第" << i + 1 << "个节点的值:" ;
        cin >> tree.arr[i].data;
        tree.arr[i].FirstChild = new node;
        tree.arr[i].FirstChild->next = NULL;
        cout << "输入结点" << tree.arr[i].data << "的孩子结点的数量:";
        int num = 0;
        cin >> num;
        if(num != 0){
            node *p = tree.arr[i].FirstChild;
            for(int j = 0; j < num; j++){
                node *ptr = new node;
                ptr->next = NULL;
                cout << "输入第" << j + 1 << "个孩子节点在顺序表中的位置: ";
                cin >> ptr->child;
                p->next = ptr;
                p = p->next;
            }
        }
    }
    return tree;
}

void FindKids(Tree tree, char ch){
    bool IsFind = false;
    for(int i = 0; i < tree.n; i++){
        if(tree.arr[i].data == ch){
            node *p = tree.arr[i].FirstChild->next;
            while(p){
                IsFind = true;
                cout << tree.arr[p->child].data;
                p = p->next;
            }
            break;
        }
    }
}
int main(){
    Tree tree;
    tree.r = 0;//默认根结点的下标为0
    for(int i = 0; i < MAX_SIZE; i++){
        tree.arr[i].FirstChild = NULL;
    }
    tree = Init(tree);
    FindKids(tree, 'F');//找出结点F的所有孩子结点
    return 0;
}

程序运行结果如下:

请输入结点个数:10
输入第1个节点的值:R
输入结点R的孩子结点的数量:3
输入第1个孩子节点在顺序表中的位置: 1
输入第2个孩子节点在顺序表中的位置: 2
输入第3个孩子节点在顺序表中的位置: 3
输入第2个节点的值:A
输入结点A的孩子结点的数量:2
输入第1个孩子节点在顺序表中的位置: 4
输入第2个孩子节点在顺序表中的位置: 5
输入第3个节点的值:B
输入结点B的孩子结点的数量:0
输入第4个节点的值:C
输入结点C的孩子结点的数量:1
输入第1个孩子节点在顺序表中的位置: 6
输入第5个节点的值:D
输入结点D的孩子结点的数量:0
输入第6个节点的值:E
输入结点E的孩子结点的数量:0
输入第7个节点的值:F
输入结点F的孩子结点的数量:3
输入第1个孩子节点在顺序表中的位置: 7
输入第2个孩子节点在顺序表中的位置: 8
输入第3个孩子节点在顺序表中的位置: 9
输入第8个节点的值:G
输入结点G的孩子结点的数量:0
输入第9个节点的值:H
输入结点H的孩子结点的数量:0
输入第10个节点的值:K
输入结点K的孩子结点的数量:0
找出节点 F 的所有孩子节点:GHK

使用孩子表示法存储的树结构,正好和双亲表示法相反,适用于 查找某个节点的孩子结点,不适用于查找父节点。

其实,我们也可以将双亲表示法和孩子表示法相互结合,就可以得到如图4所示:

数据结构:树的存储结构,数据结构,数据结构

使用图4结果存储普通树,技能快速找到指定节点的父节点,也能快速找到指定结点的孩子结点。

孩子兄弟表示法

孩子兄弟表示法:采用的是链式存储结构,其思想是,从树的根结点开始,依次用链表存储各个节点的孩子结点和兄弟节点。

所以,该链表中的结点包括3个部分,如图5所示:

  1. 结点的值。
  2. 指向孩子结点的指针。
  3. 指向兄弟结点的指针。

数据结构:树的存储结构,数据结构,数据结构

代码表示如下:

typedef struct node{
    char data;
    struct node *ForstChild, *NextSibling;
};

还是以图1为例,使用孩子兄弟表示法进行存储的结果如图所示:

数据结构:树的存储结构,数据结构,数据结构

由图我们可以发现,孩子兄弟表示法是用二叉树的左子树存储树的孩子结点,用右子树来存储兄弟结点

孩子兄弟表示法可以作为将普通树转化为二叉树的最有效的方法,同时这个方法也被称之为“二叉树表示法”或者”二叉链表表示法文章来源地址https://www.toymoban.com/news/detail-617966.html

到了这里,关于数据结构:树的存储结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构——二叉树的创建与遍历(链式存储结构)

    二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。以下是对链式存

    2024年02月05日
    浏览(47)
  • 数据结构之二叉树的性质与存储结构

      数据结构是程序设计的重要基础,它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从问题出发,分析和研究计算机加工的数据的特性,以便为应用所涉及的数据选择适当的逻辑结构、存储结构及其相应的操作方法,为提高利用

    2024年01月21日
    浏览(46)
  • 【数据结构】树的基础知识及三种存储结构

    💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃 个人主页 :阿然成长日记 👈点击可跳转 📆 个人专栏: 🔹数据结构与算法🔹C语言进阶 🚩 不能则学,不知则问,耻于问人,决无长进 🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍 把它叫做树是因为它

    2024年02月09日
    浏览(47)
  • 数据结构——二叉树的链式存储的实现

                             InitBiTree(BiTree T)——初始化二叉树。                         CreateBiTree(BiTree T)——先序遍历的顺序建立二叉链表。                         PreOrderTraverse(BiTree T)——先序遍历。                         

    2024年02月04日
    浏览(51)
  • 【数据结构】树与森林(树的存储结构、森林与二叉树的转化、树与森林的遍历)

    树与二叉树知识点文章: 【数据结构】树与二叉树(递归法先序、中序、后序、层次遍历二叉树、二叉树的建立以及求树高的方法) 二叉树遍历算法的应用: 【数据结构】树与二叉树遍历算法的应用(求叶子节点个数、求树高、复制二叉树、创建二叉树、二叉树存放表达式、

    2024年04月13日
    浏览(36)
  • 数据结构——二叉树的基本概念及顺序存储(堆)

    目录 一.前言 二.树概念及结构 2.1 树的概念 2.2 树的相关概念 2.3 树的表现 2.4 树在实际中的应用(表示文件系统的目录树结构) 三.二叉树的概念及结构 3.1 概念 3.2 特殊的二叉树 3.3 二叉树的性质 3.4 二叉树的存储结构 3.4.1 顺序存储 3.4.2 链式存储 四.二叉树顺序结构及实现

    2024年02月08日
    浏览(43)
  • 【数据结构】二叉树的存储与基本操作的实现

    二叉树的存储结构分为: 顺序存储 和类似于 链表的链式存储 这里博主讲一下链式存储 二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有 二叉和三叉 表示方式 二叉表示: 三叉表示: 这里博主主要讲解一下孩子表示法 在学习二叉树的基本操作前,需

    2024年02月04日
    浏览(45)
  • 【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)

    一个二叉树是一个有穷的结点集合。 它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。 二叉树可具有以下5种形态。 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2 i − 1 , i ≥ 1 i geq 1 i ≥ 1 每层最大结点可以对应完美二叉树(满二叉树),其所有分支结

    2024年02月20日
    浏览(43)
  • 数据结构:图文详解 树与二叉树(树与二叉树的概念和性质,存储,遍历)

    目录 一.树的概念 二.树中重要的概念 三.二叉树的概念 满二叉树 完全二叉树 四.二叉树的性质 五.二叉树的存储 六.二叉树的遍历 前序遍历 中序遍历  后序遍历  树是一种 非线性数据结构 ,它由节点和边组成。树的每个节点可以有零个或多个子节点,其中一个节点被指定为

    2024年02月04日
    浏览(49)
  • 【数据结构-二叉树 九】【树的子结构】:树的子结构

    废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【子结构】,使用【二叉树】这个基本的数据结构来实现,这个高频题的站点是: CodeTop ,筛选条件为: 目标公司+最近一年+出现频率排序 ,由高到低的去 牛客TOP101 去找,只有两个地方

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包