继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

数据结构——树

胡子哥哥
关注TA
已关注
手记 230
粉丝 78
获赞 377

参考:Mark Allen Weiss 著《数据结构与算法分析——C语言描述》(第二版)

1 树的定义

  一棵树是一些节点的集合。这个集合可以是空集;若非空,则是一棵树由称作根的节点r以及0个或者多个非空的子树组成。这些子树中每一棵的根都被来自根 r的一条有向的边所连接。图1 就是一棵具体的树,

    https://img3.mukewang.com/5b718da20001551706160194.jpg

                图1 一棵具体的树

 

2 树中的基本术语

  2.1 叶子节点
    没有儿子的节点


  2.2 兄弟节点
    具有相同父亲的节点


  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: None10     """11     # 1.列举出,当前给定的文件夹下的所有文件,以及子文件12     file_list = os.listdir(dir)13 14     # 2. 获取当前路径下文件夹名称并打印15     # 2.1 获取当前文件夹名称16     index = dir.rfind("/")17     if index == -1:18         file = dir19     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 + "/" + fname27         # 3.2 控制每行打印时的段前空格数28         sizedepth = new_fname.count("/") - num29 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:

        https://img.mukewang.com/5b718dad0001c7f302310379.jpg

             图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         return13     global totalSize14     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 totalSize22 23 # K\B\G单位的转换24 def sizeConvert(size):                                   # 单位换算25     """26     :param size: a number,int27     :return: a number,float,Keep three decimal places after the decimal point.28     """29     K, M, G = 1024, 1024**2, 1024**330     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 = dir15     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 + "/" + fname25         # 3.2 控制每行打印时的段前空格数26         sizedepth = new_fname.count("/") - num27 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:

    https://img1.mukewang.com/5b718db600011d7204340362.jpg

             图3 打印目录及大小结果

6 树的分类

  树的分类如图4。

    https://img1.mukewang.com/5b718dbe00013c5909210527.jpg

                                   图4 树的分类

原文出处:https://www.cnblogs.com/cuizhu/p/9470312.html

打开App,阅读手记
3人推荐
发表评论
随时随地看视频慕课网APP