0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

文件系統(tǒng)-多叉樹(shù)與二叉樹(shù)的轉(zhuǎn)化

冬至子 ? 來(lái)源:編程外星人 ? 作者:怪蛙 ? 2023-10-11 10:06 ? 次閱讀

在這一節(jié)中,我們來(lái)學(xué)習(xí)如何使用程序來(lái)實(shí)現(xiàn)一棵文件樹(shù)。在上一節(jié)中,我們了解到使用文件樹(shù)的方式來(lái)整合計(jì)算機(jī)中所有的資源,而這一棵文件樹(shù)則是一棵多叉樹(shù)。也就是說(shuō),樹(shù)上的每一個(gè)節(jié)點(diǎn)都可能有多個(gè)子節(jié)點(diǎn)。

而這樣的一棵多叉樹(shù)在計(jì)算機(jī)中來(lái)實(shí)現(xiàn)是較為復(fù)雜的,使用起來(lái)也不方便。例如我們想要為節(jié)點(diǎn)1增加一個(gè)子節(jié)點(diǎn)2,之后再為節(jié)點(diǎn)1增加一個(gè)子節(jié)點(diǎn)3,之后再為節(jié)點(diǎn)1增加一個(gè)子節(jié)點(diǎn)4。整個(gè)過(guò)程如下圖:

圖片

由于這是一棵多叉樹(shù),因此節(jié)點(diǎn)1可能具有多個(gè)子節(jié)點(diǎn)。這樣一來(lái),在為節(jié)點(diǎn)1分配內(nèi)存時(shí),我們就無(wú)法確定的為其分配指定大小,由于樹(shù)型結(jié)構(gòu)的特點(diǎn),我們需要使用一個(gè)指針變量用于指向其一個(gè)子節(jié)點(diǎn),而如果其具有2個(gè)子節(jié)點(diǎn),則需要2個(gè)指針變量,如果其具有3個(gè)子節(jié)點(diǎn),則需要3個(gè)指針變量。

于是對(duì)于多叉樹(shù)來(lái)說(shuō),當(dāng)一個(gè)節(jié)點(diǎn)增加一個(gè)子節(jié)點(diǎn)時(shí),當(dāng)前節(jié)點(diǎn)也需要發(fā)生變化,也就是需要重新申請(qǐng)一個(gè)較大的內(nèi)存空間用于存放更多的指針變量。同樣的,當(dāng)一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)被刪除時(shí),也需要重新申請(qǐng)內(nèi)存,釋放多余的指針變量。這對(duì)于編程實(shí)現(xiàn)多叉樹(shù)來(lái)說(shuō),是很復(fù)雜的,也是低效的。因此我們有必要尋找一種簡(jiǎn)潔的辦法來(lái)處理多叉樹(shù)的實(shí)現(xiàn)問(wèn)題。

我們知道,使用計(jì)算機(jī)編程來(lái)實(shí)現(xiàn)一個(gè)二叉樹(shù)是非常簡(jiǎn)單的,每一個(gè)節(jié)點(diǎn)除了實(shí)際數(shù)據(jù)區(qū)域外只需要額外兩個(gè)指針用于存放其左孩子節(jié)點(diǎn)和右孩子節(jié)點(diǎn)即可,而且其內(nèi)存申請(qǐng)和釋放都很簡(jiǎn)潔。二叉樹(shù)就是每一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)最多不能超過(guò)2個(gè)節(jié)點(diǎn),如下圖則是一個(gè)二叉樹(shù):

圖片

為了解決多叉樹(shù)的問(wèn)題,我們自然想到是否能將一個(gè)多叉樹(shù)轉(zhuǎn)化為一個(gè)二叉樹(shù),并使用計(jì)算機(jī)程序來(lái)實(shí)現(xiàn)呢?答案是肯定的!其實(shí),每一棵多叉樹(shù)都可以轉(zhuǎn)化為一個(gè)等價(jià)的二叉樹(shù)。進(jìn)而可以將一個(gè)具有多個(gè)多叉樹(shù)的森林轉(zhuǎn)化為一個(gè)與之等價(jià)的二叉樹(shù)。

具體轉(zhuǎn)化的過(guò)程是這樣的:我們可以定義一個(gè)二叉樹(shù)的節(jié)點(diǎn),并定義兩個(gè)指針變量,這兩個(gè)指針變量分別為指向其“子節(jié)點(diǎn)”(child)和其“兄弟節(jié)點(diǎn)”(sibling),也就是說(shuō),一個(gè)二叉樹(shù)的兩個(gè)叉,左側(cè)表示其孩子,而右側(cè)表示其兄弟。于是我們就可以將一個(gè)多叉樹(shù)轉(zhuǎn)化一個(gè)二叉樹(shù),具體轉(zhuǎn)化過(guò)程如下:

圖片

上圖中的多叉樹(shù)和二叉樹(shù)是等價(jià)的,這兩棵樹(shù)所表示的內(nèi)容完全一致,只是在結(jié)構(gòu)上不同而已。也就是說(shuō)這棵多叉樹(shù)可以轉(zhuǎn)化為二叉樹(shù),二叉樹(shù)也可以轉(zhuǎn)化為多叉樹(shù),本質(zhì)上講它們二者是可以相互轉(zhuǎn)化的,而沒(méi)有任何的不同。

對(duì)于這棵二叉樹(shù)來(lái)講,其“左叉”表示其孩子節(jié)點(diǎn),而“右叉”表示其兄弟節(jié)點(diǎn)。而二叉樹(shù)在計(jì)算機(jī)程序中是比較容易實(shí)現(xiàn)的。接下來(lái)我們就定義這樣一棵二叉樹(shù),用于表示其原有的多叉樹(shù):

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

我們簡(jiǎn)單的定義name屬性為表示這個(gè)節(jié)點(diǎn)的數(shù)據(jù)內(nèi)容,而左叉child為其子節(jié)點(diǎn),而右叉sibling為其兄弟節(jié)點(diǎn)。然后實(shí)現(xiàn)兩函數(shù)用于初始化和銷毀這個(gè)虛擬文件樹(shù):

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;
}

完成初始化和銷毀虛擬文件樹(shù)之后我們?cè)賮?lái)實(shí)現(xiàn)對(duì)任意節(jié)點(diǎn)進(jìn)行的插入和刪除操作,也就是說(shuō)針對(duì)虛擬文件樹(shù),我們?cè)谥付ㄎ恢貌迦胍粋€(gè)新的節(jié)點(diǎn):

int vfs_insert_node(char *path, file_operations_s ops)
{
  if (path[0] != '/')
  {
    return -1;
  }
  //插入子節(jié)點(diǎn),調(diào)用遞歸函數(shù)
  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};
  //找到虛擬文件樹(shù)上的指定路徑
  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++;
  }
  //查找其所有兄弟節(jié)點(diǎn)
  while (*node != NULL)
  {
    //找到兄弟節(jié)點(diǎn)
    if (strcmp((*node)- >name, node_name) == 0)
    {
      //遞歸執(zhí)行其子節(jié)點(diǎn)插入操作
      return vfs_insert_node_r(&(*node)- >child, p, ops);
    }
    node = &(*node)- >sibling;
  }


  //最后生成一個(gè)新節(jié)點(diǎn)
  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;
  //將新節(jié)點(diǎn)插入
  if (*p != 0)
  {
    return vfs_insert_node_r(&node_new- >child, p, ops);
  }
  return 0;
}

這樣,我們就完成了二叉樹(shù)的創(chuàng)建、銷毀與插入功能,當(dāng)然還應(yīng)該實(shí)現(xiàn)針對(duì)指定節(jié)點(diǎn)的刪除功能,這里我們不再給出具體實(shí)現(xiàn)代碼,請(qǐng)讀者自行完成。這樣的二叉樹(shù)就可以完整的表示我們計(jì)算機(jī)中的虛擬文件系統(tǒng)(根節(jié)點(diǎn)是虛擬節(jié)點(diǎn),并非是實(shí)際存在的,Linux系統(tǒng)中的根節(jié)點(diǎn)是實(shí)際的硬盤分區(qū),因此Linux的文件系統(tǒng)不是虛擬文件系統(tǒng))。

此后我們就可以用這一棵二叉樹(shù)來(lái)表示計(jì)算機(jī)中的所有資源了,具體方式則是將資源抽象成一個(gè)文件,掛載到文件系統(tǒng)中,成為文件系統(tǒng)中的一個(gè)節(jié)點(diǎn),這樣就可以方便用戶管理和使用這些資源了。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 計(jì)算機(jī)
    +關(guān)注

    關(guān)注

    19

    文章

    7360

    瀏覽量

    87632
  • Linux系統(tǒng)
    +關(guān)注

    關(guān)注

    4

    文章

    590

    瀏覽量

    27316
  • 二叉樹(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    74

    瀏覽量

    12302
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    基于二叉樹(shù)的時(shí)序電路測(cè)試序列設(shè)計(jì)

    為了實(shí)現(xiàn)時(shí)序電路狀態(tài)驗(yàn)證和故障檢測(cè),需要事先設(shè)計(jì)一個(gè)輸入測(cè)試序列?;?b class='flag-5'>二叉樹(shù)節(jié)點(diǎn)和樹(shù)枝的特性,建立時(shí)序電路狀態(tài)二叉樹(shù),按照電路二叉樹(shù)節(jié)點(diǎn)(狀態(tài))與樹(shù)枝(輸入)的層次邏輯
    發(fā)表于 07-12 13:57 ?0次下載
    基于<b class='flag-5'>二叉樹(shù)</b>的時(shí)序電路測(cè)試序列設(shè)計(jì)

    二叉樹(shù)層次遍歷算法的驗(yàn)證

    實(shí)現(xiàn)二叉樹(shù)的層次遍歷算法,并對(duì)用”A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))”創(chuàng)建的二叉樹(shù)進(jìn)行測(cè)試。
    發(fā)表于 11-28 01:05 ?2067次閱讀
    <b class='flag-5'>二叉樹(shù)</b>層次遍歷算法的驗(yàn)證

    二叉樹(shù),一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)類型

    然后我們?cè)俣x一棵深度也為 3 的二叉樹(shù),該二叉樹(shù)的 n 個(gè)結(jié)點(diǎn)(n≤7),當(dāng)從 1 到 n 的每個(gè)結(jié)點(diǎn)都與上圖中的編號(hào)結(jié)點(diǎn)一一對(duì)應(yīng)時(shí),這二叉樹(shù)就稱為完全二叉樹(shù)。
    的頭像 發(fā)表于 04-13 10:48 ?4277次閱讀
    <b class='flag-5'>二叉樹(shù)</b>,一種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)類型

    詳解電源二叉樹(shù)到底是什么

    作為數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ),樹(shù)分很多種,像 AVL 樹(shù)、紅黑樹(shù)、二叉搜索樹(shù)....今天我想分享的是關(guān)于二叉樹(shù)
    的頭像 發(fā)表于 06-06 15:05 ?9930次閱讀
    詳解電源<b class='flag-5'>二叉樹(shù)</b>到底是什么

    C語(yǔ)言二叉樹(shù)代碼免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是C語(yǔ)言二叉樹(shù)代碼免費(fèi)下載。
    發(fā)表于 08-27 08:00 ?1次下載

    紅黑樹(shù)(Red Black Tree)是一種自平衡的二叉搜索樹(shù)

    平衡(Balance):就是當(dāng)結(jié)點(diǎn)數(shù)量固定時(shí),左右子樹(shù)的高度越接近,這棵二叉樹(shù)越平衡(高度越低)。而最理想的平衡就是完全二叉樹(shù)/滿二叉樹(shù),高度最小的二叉樹(shù)。
    的頭像 發(fā)表于 07-01 15:05 ?5601次閱讀
    紅黑<b class='flag-5'>樹(shù)</b>(Red Black Tree)是一種自平衡的<b class='flag-5'>二叉</b>搜索<b class='flag-5'>樹(shù)</b>

    二叉樹(shù)操作的相關(guān)知識(shí)和代碼詳解

    樹(shù)是數(shù)據(jù)結(jié)構(gòu)中的重中之重,尤其以各類二叉樹(shù)為學(xué)習(xí)的難點(diǎn)。在面試環(huán)節(jié)中,二叉樹(shù)也是必考的模塊。本文主要講二叉樹(shù)操作的相關(guān)知識(shí),梳理面試??嫉膬?nèi)容。請(qǐng)大家跟隨小編一起來(lái)復(fù)習(xí)吧。 本篇針對(duì)面
    的頭像 發(fā)表于 12-12 11:04 ?2007次閱讀
    <b class='flag-5'>二叉樹(shù)</b>操作的相關(guān)知識(shí)和代碼詳解

    二叉樹(shù)的前序遍歷非遞歸實(shí)現(xiàn)

    我們之前說(shuō)了二叉樹(shù)基礎(chǔ)及二叉的幾種遍歷方式及練習(xí)題,今天我們來(lái)看一下二叉樹(shù)的前序遍歷非遞歸實(shí)現(xiàn)。 前序遍歷的順序是, 對(duì)于樹(shù)中的某節(jié)點(diǎn),先遍歷該節(jié)點(diǎn),然后再遍歷其左子樹(shù),最后遍歷其右子
    的頭像 發(fā)表于 05-28 13:59 ?1911次閱讀

    二叉排序樹(shù)AVL如何實(shí)現(xiàn)動(dòng)態(tài)平衡

    ? 什么是AVL樹(shù) 大家好,我是bigsai,好久不見(jiàn),甚是想念,今天給大家講講AVL樹(shù)。 對(duì)于樹(shù)這種數(shù)據(jù)結(jié)構(gòu),想必大家也已經(jīng)不再陌生,我們簡(jiǎn)單回顧一下。 在樹(shù)的種類中,通常分成
    的頭像 發(fā)表于 10-28 17:02 ?1772次閱讀
    <b class='flag-5'>二叉排序樹(shù)</b>AVL如何實(shí)現(xiàn)動(dòng)態(tài)平衡

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu):什么是二叉樹(shù)?

    完全二叉樹(shù):完全二叉樹(shù)是效率很高的數(shù)據(jù)結(jié)構(gòu)。對(duì)于深度為K,有n個(gè)節(jié)點(diǎn)的二叉樹(shù),當(dāng)且僅當(dāng)每一個(gè)節(jié)點(diǎn)都與深度為K的滿二叉樹(shù)中編號(hào)從1至n的節(jié)點(diǎn)一一對(duì)應(yīng)時(shí),稱為完全
    的頭像 發(fā)表于 04-21 16:20 ?2412次閱讀

    怎么就能構(gòu)造成二叉樹(shù)呢?

    一直跟著公眾號(hào)學(xué)算法的錄友 應(yīng)該知道,我在二叉樹(shù):構(gòu)造二叉樹(shù)登場(chǎng)!,已經(jīng)講過(guò),只有 中序與后序 和 中序和前序 可以確定一顆唯一的二叉樹(shù)。前序和后序是不能確定唯一的二叉樹(shù)的。
    的頭像 發(fā)表于 07-14 11:20 ?1486次閱讀

    使用C語(yǔ)言代碼實(shí)現(xiàn)平衡二叉樹(shù)

    這篇博客主要總結(jié)平衡二叉樹(shù),所以,二叉排序樹(shù)知識(shí)不會(huì)提及,但是會(huì)用到。
    的頭像 發(fā)表于 09-21 11:00 ?1033次閱讀

    二叉樹(shù)的代碼實(shí)現(xiàn)

    二叉樹(shù)的主要操作有遍歷,例如有先序遍歷、中序遍歷、后序遍歷。在遍歷之前,就是創(chuàng)建一棵二叉樹(shù),當(dāng)然,還需要有刪除二叉樹(shù)的算法。
    的頭像 發(fā)表于 01-18 10:41 ?1190次閱讀
    <b class='flag-5'>二叉樹(shù)</b>的代碼實(shí)現(xiàn)

    C++構(gòu)建并復(fù)制二叉樹(shù)

    使用C++構(gòu)建一個(gè)二叉樹(shù)并復(fù)制、輸出。
    的頭像 發(fā)表于 01-10 15:17 ?973次閱讀
    C++構(gòu)建并復(fù)制<b class='flag-5'>二叉樹(shù)</b>

    C++自定義二叉樹(shù)并輸出二叉樹(shù)圖形

    使用C++構(gòu)建一個(gè)二叉樹(shù)并輸出。
    的頭像 發(fā)表于 01-10 16:29 ?1667次閱讀
    C++自定義<b class='flag-5'>二叉樹(shù)</b>并輸出<b class='flag-5'>二叉樹(shù)</b>圖形