數據結構——樹

參考:Mark Allen Weiss 著《數據結構與算法分析——C語言描述》(第二版)python

1 樹的定義git

  一棵樹是一些節點的集合。這個集合能夠是空集;若非空,則是一棵樹由稱做根的節點r以及0個或者多個非空的子樹組成。這些子樹中每一棵的根都被來自根 r的一條有向的邊所鏈接。圖1 就是一棵具體的樹,算法

    

                圖1 一棵具體的樹數據結構

 

2 樹中的基本術語post

  2.1 葉子節點
    沒有兒子的節點測試


  2.2 兄弟節點
    具備相同父親的節點spa


  2.3 深度(deep)
    對任意節點n的深度 = 根到節點n的惟一路徑的長
    補充:根的深度爲0操作系統


  2.4 高度
    節點X處的高度是從X到一片樹葉的最長路徑的長
    補充:一棵樹的高度 = 它的根的高設計

  2.5 舉例說明指針

  在圖1中,根節點爲A,A的兒子節點爲B、C、D、E、F、G。葉子節點有B、C、H、I、P、Q、K、L、M、N。互爲兄弟節點的有K、L和M。K、L和M的父節點爲F。圖1 是一棵高度爲3的樹。圖中還有其它關係,這裏就不一一舉例了,有興趣的話,能夠本身找一找。

 

3 樹的實現

  3.1 實現思路

    每個節點除數據外還要一些指針,使得該節點的每個兒子都有一個指針指向它。因爲每一個節點的兒子數能夠變化很大且事先不知道。

  所以,在數據結構中創建到各兒子節點直接的連接是不可行的,此方法會浪費太多的空間。能夠將每一個節點的全部兒子都放在樹節點的鏈表中。

 

  3.2 實現的僞代碼

typedef struct TreeNode *PtrToNode;

struct TreeNode
{
    ElementType Element;        //存儲數據
    PtrToNode FirstChild;          //指向第一個兒子節點的指針
    PtrToNode NextChild;          //指向下一兄弟節點的指針
};

 

4 樹的基本操做

  若是一個樹只能存儲而沒法讀取,也就沒法使用。那麼咱們還設計這種結構還有什麼意義!遍歷又分爲先序遍歷(preorder traversal)和後序遍歷(postorder traversal)兩種。

  (1)先序遍歷(preorder traversal)思想:對節點的處理工做是在它的諸兒子節點被處理以前進行的。

  (2)後序遍歷(postorder traversal)思想:在一個節點處的工做是在它的諸兒子節點被計算後進行的

 

5 樹的應用

  包括UNIX、VAX/VMS 和DOS在內的許多經常使用操做系統中的目錄結構。下面列舉兩個案例來講明:「列出分級文件系統中目錄的例程」和「計算一個目錄大小的例程」。

  5.1 僞代碼

    (1)「列出分級文件系統中目錄的例程」的僞代碼以下, 

static void ListDir(DirectoryOrFile D, int Depth)
{
    if(D is a legitimate entry)
    {
        PrintName(D, Depth);
        if(D is a directory)
            for each child, C of D:
                ListDir(C, Depth + 1);
    }
}

void ListDirectory(DirectoryOrFile D)
{
    ListDir(D, 0);
}

 

    (2)「計算一個目錄大小的例程」的僞代碼以下,

static int SizeListDirectory(DirectoryOrFile D)
{
    int TotalSize;
    
    TotalSize = 0;
    if(D is a directiry)
        for each child, C of D:
            TotalSize += SizeListDirectory(C);
    return TotalSize;
}

 

  5.2 python語言實現

    (1)「列出分級文件系統中目錄的例程」的python語言實現代碼以下, 

 1 import os
 2 
 3 
 4 # 按照必定格式打印文件或目錄名稱
 5 def listDir(dir, num):
 6     """
 7     :param dir: absolute path
 8     :param num: the number of "/" before your firstinput path
 9     :return: None
10     """
11     # 1.列舉出,當前給定的文件夾下的全部文件,以及子文件
12     file_list = os.listdir(dir)
13 
14     # 2. 獲取當前路徑下文件夾名稱並打印
15     # 2.1 獲取當前文件夾名稱
16     index = dir.rfind("/")
17     if index == -1:
18         file = dir
19     file = dir[index + 1:]
20     # 2.2 打印文件名及
21     print(file)
22 
23     # 3.針對於列舉出的列表,進行遍歷
24     for fname in file_list:
25         # 3.1 拼接當前文件的路徑
26         new_fname = dir + "/" + fname
27         # 3.2 控制每行打印時的段前空格數
28         sizedepth = new_fname.count("/") - num
29 
30         # 3.3 判斷是否爲目錄
31         if os.path.isdir(new_fname):
32             print(end="\t" * sizedepth)
33             listDir(new_fname, num)
34         else:
35             # 打印文件名稱
36             print("\t" * (sizedepth) + fname)
37 
38 # 測試代碼
39 
40 
41 if __name__ == '__main__':
42     path = "F:/python_AI/python基礎/python文件操做/files1"
43     num = path.count("/")
44     print("num = ", num)
45     listDir(path, num)

 

  執行後結果如圖2:

        

             圖2 打印目錄結果

       

    (2)「計算一個目錄大小的例程」的python語言實現代碼以下,

         (i)文件大小計算模塊sizedir.py文件,文件內容以下:     

 1 import os
 2 
 3 totalSize = 0
 4 # 計算文件或目錄下的所佔大小
 5 def cal_size(path):
 6     """
 7     :param path: an absolute path
 8     :return: the size of the input path(file or directory)
 9     """
10     if not os.path.isdir(path):
11         print('Error:"', path, '" is not a directory or does not exist.')
12         return
13     global totalSize
14     for lists in os.listdir(path):
15         sub_path = os.path.join(path, lists)
16         # print(sub_path)
17         if os.path.isfile(sub_path):
18             totalSize = totalSize+os.path.getsize(sub_path)  # 文件總大小
19         elif os.path.isdir(sub_path):
20             cal_size(sub_path)                           # 遞歸遍歷子文件夾
21     return totalSize
22 
23 # K\B\G單位的轉換
24 def sizeConvert(size):                                   # 單位換算
25     """
26     :param size: a number,int
27     :return: a number,float,Keep three decimal places after the decimal point.
28     """
29     K, M, G = 1024, 1024**2, 1024**3
30     if size >= G:
31         return str(round(size/G, 3))+' G Bytes'
32     elif size >= M:
33         return str(round(size/M, 3))+' M Bytes'
34     elif size >= K:
35         return str(round(size/K, 3))+' K Bytes'
36     else:
37         return str(size)+' Bytes'

    (ii)打印文件名稱及大小模塊my_size_dir.py,文件內容以下,

 1 import os
 2 import sizedir
 3 
 4 # 打印文件或目錄名稱及所佔內存大小
 5 def listDir(dir, num):
 6 
 7     # 1.列舉出,當前給定的文件夾下的全部文件,以及子文件
 8     file_list = os.listdir(dir)
 9 
10     # 2. 獲取當前路徑下文件夾名稱並打印
11     # 2.1 獲取當前文件夾名稱
12     index = dir.rfind("/")
13     if index == -1:
14         file = dir
15     file = dir[index + 1:]
16     # 2.2 計算當前目錄下的文件總大小
17     dir_size = sizedir.cal_size(dir)
18     # 2.3 打印文件名及文件大小
19     print(file, "\t(%s)" % sizedir.sizeConvert(dir_size))
20 
21     # 3.針對於列舉出的列表,進行遍歷
22     for fname in file_list:
23         # 3.1 拼接當前文件的路徑
24         new_fname = dir + "/" + fname
25         # 3.2 控制每行打印時的段前空格數
26         sizedepth = new_fname.count("/") - num
27 
28         # 3.3 判斷是否爲目錄
29         if os.path.isdir(new_fname):
30             print(end="\t" * sizedepth)
31             listDir(new_fname, num)
32         else:
33             # 打印文件名稱及大小
34             fsize = sizedir.sizeConvert(os.path.getsize(new_fname))
35             print("\t" * (sizedepth) + fname, "\t(%s)" % fsize)
36 
37 # 測試代碼
38 if __name__ == '__main__':
39     path = "F:/python_AI/python基礎/python文件操做/files1"
40     num = path.count("/")
41     # print(num)
42     listDir(path, num)

  上面代碼執行結果如圖3:

    

             圖3 打印目錄及大小結果

6 樹的分類

  樹的分類如圖4。

    

                                   圖4 樹的分類

相關文章
相關標籤/搜索