0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

文件系统-多叉树与二叉树的转化

冬至子 来源:编程外星人 作者:怪蛙 2023-10-11 10:06 次阅读

在这一节中,我们来学习如何使用程序来实现一棵文件树。在上一节中,我们了解到使用文件树的方式来整合计算机中所有的资源,而这一棵文件树则是一棵多叉树。也就是说,树上的每一个节点都可能有多个子节点。

而这样的一棵多叉树在计算机中来实现是较为复杂的,使用起来也不方便。例如我们想要为节点1增加一个子节点2,之后再为节点1增加一个子节点3,之后再为节点1增加一个子节点4。整个过程如下图:

图片

由于这是一棵多叉树,因此节点1可能具有多个子节点。这样一来,在为节点1分配内存时,我们就无法确定的为其分配指定大小,由于树型结构的特点,我们需要使用一个指针变量用于指向其一个子节点,而如果其具有2个子节点,则需要2个指针变量,如果其具有3个子节点,则需要3个指针变量。

于是对于多叉树来说,当一个节点增加一个子节点时,当前节点也需要发生变化,也就是需要重新申请一个较大的内存空间用于存放更多的指针变量。同样的,当一个节点的子节点被删除时,也需要重新申请内存,释放多余的指针变量。这对于编程实现多叉树来说,是很复杂的,也是低效的。因此我们有必要寻找一种简洁的办法来处理多叉树的实现问题。

我们知道,使用计算机编程来实现一个二叉树是非常简单的,每一个节点除了实际数据区域外只需要额外两个指针用于存放其左孩子节点和右孩子节点即可,而且其内存申请和释放都很简洁。二叉树就是每一个节点的子节点最多不能超过2个节点,如下图则是一个二叉树:

图片

为了解决多叉树的问题,我们自然想到是否能将一个多叉树转化为一个二叉树,并使用计算机程序来实现呢?答案是肯定的!其实,每一棵多叉树都可以转化为一个等价的二叉树。进而可以将一个具有多个多叉树的森林转化为一个与之等价的二叉树。

具体转化的过程是这样的:我们可以定义一个二叉树的节点,并定义两个指针变量,这两个指针变量分别为指向其“子节点”(child)和其“兄弟节点”(sibling),也就是说,一个二叉树的两个叉,左侧表示其孩子,而右侧表示其兄弟。于是我们就可以将一个多叉树转化一个二叉树,具体转化过程如下:

图片

上图中的多叉树和二叉树是等价的,这两棵树所表示的内容完全一致,只是在结构上不同而已。也就是说这棵多叉树可以转化为二叉树,二叉树也可以转化为多叉树,本质上讲它们二者是可以相互转化的,而没有任何的不同。

对于这棵二叉树来讲,其“左叉”表示其孩子节点,而“右叉”表示其兄弟节点。而二叉树在计算机程序中是比较容易实现的。接下来我们就定义这样一棵二叉树,用于表示其原有的多叉树:

typedef struct vfs_node_s
{
  struct vfs_node_s *child;
  struct vfs_node_s *sibling;
  char name[200];
} vfs_node_s;

我们简单的定义name属性为表示这个节点的数据内容,而左叉child为其子节点,而右叉sibling为其兄弟节点。然后实现两函数用于初始化和销毁这个虚拟文件树:

int vfs_init(void)
{
  vfs = malloc(sizeof(vfs_s));
  vfs- >root = malloc(sizeof(vfs_node_s));
  strncpy(vfs- >root- >name, "/", NODE_NAME_SIZE);
  vfs- >root- >child = NULL;
  vfs- >root- >sibling = NULL;


  return 0;
}


int vfs_destory(void)
{
  vfs_destory_r(&vfs- >root);
  free(vfs);
  return 0;
}

完成初始化和销毁虚拟文件树之后我们再来实现对任意节点进行的插入和删除操作,也就是说针对虚拟文件树,我们在指定位置插入一个新的节点:

int vfs_insert_node(char *path, file_operations_s ops)
{
  if (path[0] != '/')
  {
    return -1;
  }
  //插入子节点,调用递归函数
  int ret = vfs_insert_node_r(&vfs- >root- >child, &path[1], ops);
  return ret;
}


int vfs_insert_node_r(vfs_node_s **node, char *abs_path, file_operations_s ops)
{
  if (node == NULL)
  {
    return -1;
  }
  if (abs_path == NULL)
  {
    return -1;
  }
  if (abs_path[0] == 0)
  {
    return -1;
  }
  char node_name[NODE_NAME_SIZE] = {0};
  //找到虚拟文件树上的指定路径
  char *p = abs_path;
  for (int i = 0; *p != '/' && *p != 0 && i < NODE_NAME_SIZE; i++)
  {
    node_name[i] = *p++;
  }
  if (*p == '/' && *p != 0)
  {
    p++;
  }
  //查找其所有兄弟节点
  while (*node != NULL)
  {
    //找到兄弟节点
    if (strcmp((*node)- >name, node_name) == 0)
    {
      //递归执行其子节点插入操作
      return vfs_insert_node_r(&(*node)- >child, p, ops);
    }
    node = &(*node)- >sibling;
  }


  //最后生成一个新节点
  vfs_node_s *node_new = malloc(sizeof(vfs_node_s));
  strncpy(node_new- >name, node_name, NODE_NAME_SIZE);
  node_new- >child = NULL;
  node_new- >sibling = NULL;
  *node = node_new;
  //将新节点插入
  if (*p != 0)
  {
    return vfs_insert_node_r(&node_new- >child, p, ops);
  }
  return 0;
}

这样,我们就完成了二叉树的创建、销毁与插入功能,当然还应该实现针对指定节点的删除功能,这里我们不再给出具体实现代码,请读者自行完成。这样的二叉树就可以完整的表示我们计算机中的虚拟文件系统(根节点是虚拟节点,并非是实际存在的,Linux系统中的根节点是实际的硬盘分区,因此Linux的文件系统不是虚拟文件系统)。

此后我们就可以用这一棵二叉树来表示计算机中的所有资源了,具体方式则是将资源抽象成一个文件,挂载到文件系统中,成为文件系统中的一个节点,这样就可以方便用户管理和使用这些资源了。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 计算机
    +关注

    关注

    19

    文章

    7488

    浏览量

    87848
  • Linux系统
    +关注

    关注

    4

    文章

    593

    浏览量

    27392
  • 二叉树
    +关注

    关注

    0

    文章

    74

    浏览量

    12324
收藏 人收藏

    评论

    相关推荐

    基于二叉树的时序电路测试序列设计

    为了实现时序电路状态验证和故障检测,需要事先设计一个输入测试序列。基于二叉树节点和树枝的特性,建立时序电路状态二叉树,按照电路二叉树节点(状态)与树枝(输入)的层次逻辑
    发表于 07-12 13:57 0次下载
    基于<b class='flag-5'>二叉树</b>的时序电路测试序列设计

    二叉树层次遍历算法的验证

    实现二叉树的层次遍历算法,并对用”A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))”创建的二叉树进行测试。
    发表于 11-28 01:05 2096次阅读
    <b class='flag-5'>二叉树</b>层次遍历算法的验证

    二叉树,一种基础的数据结构类型

    然后我们再定义一棵深度也为 3 的二叉树,该二叉树的 n 个结点(n≤7),当从 1 到 n 的每个结点都与上图中的编号结点一一对应时,这二叉树就称为完全二叉树
    的头像 发表于 04-13 10:48 4347次阅读
    <b class='flag-5'>二叉树</b>,一种基础的数据结构类型

    详解电源二叉树到底是什么

    作为数据结构的基础,分很多种,像 AVL 、红黑二叉搜索....今天我想分享的是关于二叉树
    的头像 发表于 06-06 15:05 1w次阅读
    详解电源<b class='flag-5'>二叉树</b>到底是什么

    C语言二叉树代码免费下载

    本文档的主要内容详细介绍的是C语言二叉树代码免费下载。
    发表于 08-27 08:00 1次下载

    红黑(Red Black Tree)是一种自平衡的二叉搜索

    平衡(Balance):就是当结点数量固定时,左右子树的高度越接近,这棵二叉树越平衡(高度越低)。而最理想的平衡就是完全二叉树/满二叉树,高度最小的二叉树
    的头像 发表于 07-01 15:05 5699次阅读
    红黑<b class='flag-5'>树</b>(Red Black Tree)是一种自平衡的<b class='flag-5'>二叉</b>搜索<b class='flag-5'>树</b>

    二叉树操作的相关知识和代码详解

    是数据结构中的重中之重,尤其以各类二叉树为学习的难点。在面试环节中,二叉树也是必考的模块。本文主要讲二叉树操作的相关知识,梳理面试常考的内容。请大家跟随小编一起来复习吧。 本篇针对面
    的头像 发表于 12-12 11:04 2038次阅读
    <b class='flag-5'>二叉树</b>操作的相关知识和代码详解

    二叉树的前序遍历非递归实现

    我们之前说了二叉树基础及二叉的几种遍历方式及练习题,今天我们来看一下二叉树的前序遍历非递归实现。 前序遍历的顺序是, 对于中的某节点,先遍历该节点,然后再遍历其左子树,最后遍历其右子
    的头像 发表于 05-28 13:59 1952次阅读

    二叉排序树AVL如何实现动态平衡

      什么是AVL 大家好,我是bigsai,好久不见,甚是想念,今天给大家讲讲AVL。 对于这种数据结构,想必大家也已经不再陌生,我们简单回顾一下。 在的种类中,通常分成
    的头像 发表于 10-28 17:02 1810次阅读
    <b class='flag-5'>二叉排序树</b>AVL如何实现动态平衡

    C语言数据结构:什么是二叉树

    完全二叉树:完全二叉树是效率很高的数据结构。对于深度为K,有n个节点的二叉树,当且仅当每一个节点都与深度为K的满二叉树中编号从1至n的节点一一对应时,称为完全
    的头像 发表于 04-21 16:20 2507次阅读

    怎么就能构造成二叉树呢?

    一直跟着公众号学算法的录友 应该知道,我在二叉树:构造二叉树登场!,已经讲过,只有 中序与后序 和 中序和前序 可以确定一颗唯一的二叉树。前序和后序是不能确定唯一的二叉树的。
    的头像 发表于 07-14 11:20 1577次阅读

    使用C语言代码实现平衡二叉树

    这篇博客主要总结平衡二叉树,所以,二叉排序树知识不会提及,但是会用到。
    的头像 发表于 09-21 11:00 1092次阅读

    二叉树的代码实现

    二叉树的主要操作有遍历,例如有先序遍历、中序遍历、后序遍历。在遍历之前,就是创建一棵二叉树,当然,还需要有删除二叉树的算法。
    的头像 发表于 01-18 10:41 1225次阅读
    <b class='flag-5'>二叉树</b>的代码实现

    C++构建并复制二叉树

    使用C++构建一个二叉树并复制、输出。
    的头像 发表于 01-10 15:17 1013次阅读
    C++构建并复制<b class='flag-5'>二叉树</b>

    C++自定义二叉树并输出二叉树图形

    使用C++构建一个二叉树并输出。
    的头像 发表于 01-10 16:29 1741次阅读
    C++自定义<b class='flag-5'>二叉树</b>并输出<b class='flag-5'>二叉树</b>图形