zoukankan      html  css  js  c++  java
  • 数据结构——树

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

    1 树的定义

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

        

                    图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: 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="	" * sizedepth)
    33             listDir(new_fname, num)
    34         else:
    35             # 打印文件名称
    36             print("	" * (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 # KBG单位的转换
    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, "	(%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="	" * sizedepth)
    31             listDir(new_fname, num)
    32         else:
    33             # 打印文件名称及大小
    34             fsize = sizedir.sizeConvert(os.path.getsize(new_fname))
    35             print("	" * (sizedepth) + fname, "	(%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 树的分类

  • 相关阅读:
    02-17 位图验证码(一般处理程序)+AJAX
    02-18 报表
    SQLite 函数大全
    SQLite中的时间日期函数(转)
    DES,AeS加解密,MD5,SHA加密
    suspendlayout
    AES--高级数据加密标准
    C#中Validating和Validated事件
    Net操作Excel(终极方法NPOI)
    decimal,float和double的区别
  • 原文地址:https://www.cnblogs.com/cuizhu/p/9470312.html
Copyright © 2011-2022 走看看