Pstree源码分析
Python入门篇-数据结构树(tree)篇
Python⼊门篇-数据结构树(tree)篇 Python⼊门篇-数据结构树(tree)篇 作者:尹正杰版权声明:原创作品,谢绝转载!否则将追究法律责任。
⼀.树概述1>.树的概念⾮线性结构,每个元素可以有多个前躯和后继树是n(n>=0)个元素的集合:n = 0时,称为空树树只有⼀个特殊的没有前驱的元素,称为树的根root树中除了根结点外,其余元素只能有⼀个前驱,可以有零个或者多个后继递归定义:数T是n(n>=0)个元素的集合。
n=0时,称为空树有且只有⼀个特殊元素根,剩余元素都可以被划分为m个互不相交的集合T1,T2,T3,...,Tm,⽽每⼀个集合都是树,称为T的⼦树subtree⼦树也有⾃⼰的根2>.数的相关术语结点: 树中的数据元素。
结点的度degree: 结点拥有的⼦树的数⽬称为度,记作d(v)。
叶⼦结点: 结点的度为0,称为叶⼦结点leaf,终端结点,末端结点。
分⽀结点: 结点的度不为0,称为⾮终端结点或分⽀结点。
分⽀: 结点之间的关系。
内部结点: 除根结点外的分⽀结点,当然也不包括叶⼦结点。
如下图所⽰,数的度是树内各结点的度的最⼤值。
D结点度最⼤为3,树的度数就是3. 孩⼦结点(⼉⼦Child)结点: 结点的⼦树的根结点称为该结点的孩⼦。
双亲(⽗Parent)结点: ⼀个结点是它各⼦树的根结点的双亲。
兄弟(Sibling)结点: 具有相同双亲结点的节点。
祖先节点: 从根结点到该结点所有分⽀上所有的节点,如上图所⽰:A,B,D都是G的祖先结点。
⼦孙结点: 结点的所有⼦树上的结点称为该结点的⼦孙。
B的⼦孙是D,G,H,I结点的层次(Level): 根节点为第⼀层,根的孩⼦为第⼆层,以此类推,记作L(v)。
树的深度(⾼度Depth): 树的层次的最⼤值。
上图的树深度为4.堂兄弟: 双亲在同⼀层的结点。
有序树: 结点的⼦树是有顺序的(兄弟有⼤⼩,有先后次序),不能交换。
SharpDevelop源码分析总结
SharpDevelop源码分析总结2011-12-06总结人:张洪林总结正文:(标题形式)1.插件核心类AddInTree为插件管理容器的插件组织形式,包含多个AddIn树节点(插件),同时提供了对AddInTreeNode的操作接口(DisableAddin,Load,GetTreeNode,InsertAddIn等),树节点包含多个Codon实例, Codon定义了插件中需要实例化类型(Class, FileFilter, String等)的配置信息。
2.AddInTreeNode类是对该节点下包含的Codon进行管理,并提供实例创建的接口。
3.ExtensionPath类代表AddInTreeNode创建时的路径信息及目录下的所有Codon的加载.每个插件的扩展性就体现在该类中,通过增加配置文件中的Path属性进行ExtensionPath的增加,同时在AddInTree 中会增加该路径上的AddInTreeNode实例。
4.IDoozer是Codon对象的抽象工厂,支持各种名称的Codon的创建工作。
5.AddInManager Manages all actions performed on AddIns. There are three types of AddIns:- Preinstalled AddIns (added by host application) -> can only be disabled- External AddIns -> can be added, disabled and removedRemoving external AddIns only removes the reference to the .addin filebut does not delete the AddIn.- User AddIns -> are installed to UserAddInPath, can be installed, disabled and uninstalled6.SharpDevelopHost This class can host an instance of SharpDevelop inside another AppDomain7.ICSharpCode.Core项目为插件管理的设计核心。
代码转成树形结构__概述说明以及解释
代码转成树形结构概述说明以及解释1. 引言1.1 概述代码转成树形结构是一种将源代码以树的形式来表示和展现的技术。
通过将代码转换为树形结构,可以更加直观地理解和管理代码的结构和层次关系。
本文将介绍代码转成树形结构的概念、原因以及实现方法,并分析树形结构与代码之间的关系。
1.2 文章结构本文按照以下目录进行组织:- 引言:对文章进行概述和说明。
- 代码转成树形结构:介绍什么是代码转成树形结构,为什么要将代码转成树形结构以及实现该技术的方法。
- 树形结构与代码的关系分析:探讨在编程中使用树形结构的作用,以及代码在树形结构中的表示方式,并分析树形结构对于理解和维护代码的意义。
- 实例演示与应用场景讨论:通过示例将编程语言中的代码转换为树形结构,并讨论使用树形结构进行代码分析和优化的应用场景,最后探讨了树形结构在软件开发中可能具有的潜在价值。
- 结论:总结文章内容并提出未来的展望。
1.3 目的本文的目的是介绍和解释代码转成树形结构这一技术,使读者了解该技术的背景、原因和实现方法。
同时,通过分析树形结构与代码之间的关系,探讨树形结构在编程中的作用以及对代码理解和维护的意义。
此外,本文还将通过实例演示和应用场景讨论,展示代码转成树形结构的实际应用价值,并提供未来发展方向的展望。
通过阅读本文,读者将能够更好地理解代码转成树形结构技术及其潜在好处,从而更加高效地进行软件开发工作。
2. 代码转成树形结构2.1 什么是代码转成树形结构代码转成树形结构是指将程序代码按照语法和层次结构,转化为一棵包含各级子节点的树形数据结构。
在这个树形结构中,每个节点代表代码的一个语法单元或块。
2.2 为什么要将代码转成树形结构将代码转成树形结构有以下几个优点:首先,通过将代码映射到树形结构中,可以清晰地展现出代码间的关系和逻辑流程。
这对于理解复杂的程序非常有帮助。
其次,通过使用树形结构表示代码,我们可以更轻松地对程序进行静态分析和优化。
语法树解析 python
语法树解析python在自然语言处理领域,语法树发挥着至关重要的作用。
它是句子结构的一种树状表示,能帮助我们更好地理解句子的语法结构和意义。
Python作为一门流行的编程语言,拥有丰富的自然语言处理库,可以方便地进行语法树的解析。
本文将详细介绍如何使用Python进行语法树解析。
一、什么是语法树?语法树(Syntax Tree),又称作句法树,是源代码、自然语言句子等结构的一种抽象语法结构的树状表示。
在自然语言处理中,语法树能够清晰地展示句子的成分结构,如主语、谓语、宾语等,以及它们之间的关系。
二、Python中的语法树解析在Python中,可以使用自然语言处理库(如NLTK、spaCy等)进行语法树的解析。
以下以NLTK库为例,介绍如何实现语法树的解析。
1.安装NLTK库首先,需要安装NLTK库。
在命令行执行以下命令:```pip install nltk```2.使用NLTK解析语法树(1)导入所需模块```pythonimport nltkfrom nltk import CFGfrom nltk.parse import ChartParser```(2)定义语法规则使用上下文无关文法(CFG)定义语法规则。
```pythongrammar = CFG.fromstring("""S -> NP VPVP -> V NPNP -> "I" | "you"V -> "love"""")```(3)创建解析器```pythonparser = ChartParser(grammar)```(4)解析句子将句子转换为词列表,然后使用解析器进行解析。
```pythonsentence = "I love you".split()trees = list(parser.parse(sentence))```(5)显示语法树```pythonfor tree in trees:tree.pretty_print()```三、总结通过使用Python中的自然语言处理库,如NLTK,我们可以方便地进行语法树的解析。
tree.xpath语法结构
文章标题:深入探讨tree.xpath语法结构1. 介绍在网络爬虫和数据提取中,xpath是一种强大的定位和提取工具,而tree.xpath则是xpath在Python语言中的应用。
本文将深入探讨tree.xpath的语法结构,以帮助读者更深入地理解和掌握这一重要工具。
2. 什么是tree.xpath让我们简单地了解一下tree.xpath是什么。
tree.xpath是在Python 中用于解析和提取HTML或XML文档中特定元素的工具,它基于xpath语法,提供了一种灵活而强大的方式来定位和获取文档中的数据。
通过深入研究tree.xpath的语法结构,我们可以更好地利用它来实现网页数据的抓取和分析。
3. tree.xpath的基本语法tree.xpath的语法结构十分灵活,但基本的使用方式包括以下几个要点:3.1 元素选择在tree.xpath中,可以使用xpath语法来选择特定的元素。
通过指定元素的标签名、类名、ID或特定属性来选择相应的元素。
3.2 属性提取除了选择元素本身,tree.xpath还可以用于提取元素的特定属性。
这包括元素的文本内容、信息、图片位置区域等各种属性。
3.3 路径定位xpath语法中的路径定位也是tree.xpath中的重要部分。
通过指定元素在文档中的路径,可以精确地定位到需要的元素。
4. 在实际应用中的使用示例为了更好地理解tree.xpath的语法结构,让我们通过一些实际的使用示例来加深对它的理解。
4.1 选择特定元素比如我们要从一个网页中提取所有的标题元素,可以使用如下的tree.xpath语法:```pythontitles = tree.xpath('//h1')```4.2 提取属性内容如果我们想获取所有信息的URL位置区域,可以使用如下的tree.xpath语法:```pythonlinks = tree.xpath('//a/@href')```4.3 路径定位另外,如果我们要定位到某个特定元素下的子元素,可以使用下面的tree.xpath语法:```pythonsub_element = tree.xpath('//div[@class="sub"]//p')```通过这些简单的示例,我们可以更直观地理解tree.xpath的语法结构及其灵活性和强大性。
通过pstree命令查看进程树和关系
通过pstree命令查看进程树和关系进程是计算机中正在运行的程序的实例。
在操作系统中,多个进程可以同时运行并相互影响。
了解进程之间的关系对于系统管理和故障排除非常重要。
在Linux系统中,可以使用pstree命令来查看进程树和进程之间的关系。
一、什么是进程树和进程关系在Linux系统中,每个进程都有一个唯一的进程号(PID),同时还有一个父进程号(PPID),表示它的直接父进程。
进程树是由父进程和它的所有子进程组成的层次结构,类似于家族树或公司组织结构图。
通过进程树,我们可以清楚地了解每个进程的起源和关系。
进程之间的关系可以分为以下三种:1. 父进程(Parent process):生成其他进程的进程称为父进程。
2. 子进程(Child process):由父进程生成的进程称为子进程。
子进程可以再生成其他子进程,形成进程树。
3. 兄弟进程(Sibling process):同一父进程生成的多个子进程称为兄弟进程。
了解进程树和进程之间的关系对于理解系统的运行状态、资源分配和进程相互之间的协作非常重要。
二、使用pstree命令查看进程树pstree是一个常用的Linux命令,用于以树状结构显示进程的关系。
它将系统中的所有进程按照层次结构进行展示,方便我们查看进程之间的关系。
在终端中输入以下命令可以查看进程树:```pstree```执行该命令后,系统会以树状结构展示所有进程及其关系。
例如:```systemd─┬─accounts-daemon───2*[{accounts-daemon}]├─agetty├─avahi-daemon───avahi-daemon├─containerd───10*[{containerd}]├─cron├─dbus-daemon├─dockerd───9*[{dockerd}]├─firewalld───3*[{firewalld}]├─gnome-keyring-d─┬─ssh-agent│ └─2*[{gnome-keyring-d}]├─gpg-agent├─irqbalance───{irqbalance}├─libvirtd───7*[{libvirtd}]├─lvmetad───3*[{lvmetad}]├─master─┬─pickup│ └─5*[qmgr]├─polkitd───3*[{polkitd}]├─rsyslogd───2*[{rsyslogd}]├─snapd───17*[{snapd}]├─sssd─┬─sssd_be│ └─sssd_nss├─systemd─┬─(sd-pam)│ ├─at-spi-bus-laun─┬─dbus-daemon......```在显示的树状结构中,每个进程通过短横线和管道符号连接到它的子进程。
linux中tree的源码
linux中tree的源码全文共四篇示例,供读者参考第一篇示例:在Linux操作系统中,tree命令是一款非常实用的工具,它可以帮助用户以树状图的形式展示文件夹及文件的结构,让用户更直观地了解目录的层次关系。
不过,你是否想过tree命令的背后是如何实现的呢?其实,tree命令的源码是开源的,我们可以通过阅读其源码来深入了解其实现原理。
tree命令的源码主要由C语言编写,其核心功能在tree.c文件中实现。
在阅读源码之前,我们需要了解tree命令的基本功能:1. 遍历指定目录下的所有文件夹及文件;2. 以树状图的形式展示目录结构;3. 支持控制输出格式,如显示文件大小、文件权限等信息;4. 支持过滤指定文件或文件夹;5. 支持递归展示子目录。
接下来,让我们深入分析tree命令的源码实现:1. 主函数:tree命令的主函数主要负责解析命令行参数,并调用相应的函数实现功能。
在主函数中,通过解析命令行参数获取用户的选项,如-a(显示所有文件)、-h(以人类可读的形式显示文件大小)等。
2. 遍历目录:tree命令的核心功能是遍历目录树并以树状图的形式展示。
在tree.c文件中,定义了一个名为print_tree的函数,该函数通过递归方式遍历目录,并输出目录结构。
在遍历目录时,需要注意排除当前目录和父目录(.和..)以及过滤用户指定的文件或文件夹。
3. 输出格式:tree命令支持多种输出格式,如显示文件大小、文件权限等信息。
在tree.c文件中,定义了多个辅助函数用于输出文件信息,如print_size函数用于输出文件大小,print_mode函数用于输出文件权限等。
4. 递归展示:当tree命令遍历目录时,如果遇到子目录,需要递归展示子目录下的文件及目录。
在print_tree函数中,通过调用自身实现递归展示目录。
递归展示子目录是tree命令实现树状展示的关键之一。
第二篇示例:在Linux系统中,tree命令是一个非常常用的工具,它可以以树状结构显示指定目录下的所有文件和子目录。
linux中tree的源码
Linux中tree的源码tree 是一个在Linux 系统中常用的命令行工具,用于显示目录结构的树形图。
它的源码是用C 语言编写的。
以下是一个简单的 tree 命令的源码示例。
这个示例版本非常简单,不包含所有 tree 命令的功能,但它演示了如何使用递归函数来显示目录树。
c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dirent.h>#include<sys/stat.h>#include<unistd.h>#define MAX_PATH 1024void print_directory(const char *path, int depth) {DIR *dir;struct dirent *entry;char full_path[MAX_PATH];if (!(dir = opendir(path))) {perror("opendir");return;}while ((entry = readdir(dir))) {if (strcmp(entry->d_name, ".") == 0 ||strcmp(entry->d_name, "..") == 0) {continue;}snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);for (int i = 0; i < depth; i++) {printf(" ");}printf("%s\n", entry->d_name);if (entry->d_type == DT_DIR) {print_directory(full_path, depth + 1);}}closedir(dir);}int main(int argc, char *argv[]) {if (argc != 2) {fprintf(stderr, "Usage: %s <directory>\n", argv[0]);return1;}print_directory(argv[1], 0);return0;}这个示例中的 print_directory 函数使用递归方式遍历指定目录下的所有文件和子目录,并根据目录的深度打印出相应的缩进。
avl tree的python代码
AVL树的Python代码一级标题:AVL树介绍二级标题:什么是AVL树AVL树是一种自平衡二叉搜索树,它的特点是任意节点的左子树和右子树的高度差不超过1。
AVL树是以其发明者Adelson-Velsky和Landis的名字命名的。
二级标题:AVL树的特点AVL树具有以下特点: 1. 每个节点都有一个平衡因子,它是左子树高度减去右子树高度。
2. 平衡因子可以为-1、0或1。
如果平衡因子为k,表示该节点的左子树高度比右子树高度大k。
3. 所有叶子节点的平衡因子都为0。
4. 插入或删除节点后,AVL树会自动调整以保持平衡性。
二级标题:为什么使用AVL树使用AVL树的好处有: 1. AVL树的高度始终保持在O(log n),使得搜索、插入和删除的平均时间复杂度为O(log n)。
2. AVL树自动调整以保持平衡性,不会像普通二叉搜索树一样退化成链表。
3. AVL树相比红黑树来说,旋转操作更少,具有更好的搜索性能。
一级标题:AVL树的实现二级标题:Node类的定义在实现AVL树之前,我们首先需要定义一个Node类,用于表示AVL树的节点。
Node类包含以下属性: - key:节点的键值 - left:指向左子节点的指针 - right:指向右子节点的指针 - height:节点的高度class Node:def __init__(self, key):self.key = keyself.left = Noneself.right = Noneself.height = 1二级标题:AVL树的插入操作AVL树的插入操作是通过递归实现的,基本思想是先执行二叉搜索树的插入操作,然后在返回的过程中进行平衡操作。
具体的插入操作分为以下几步: 1. 如果树为空,直接创建一个新节点并返回。
2. 如果插入的值小于当前节点的键值,则插入到左子树中。
3. 如果插入的值大于当前节点的键值,则插入到右子树中。
4. 更新当前节点的高度。
[转]3D游戏中的场景管理(八叉树和BSP树简介)
如何很好地表示出包含着成千上万物体的复杂场景,是设计系统必须要考虑的。
这也是场景管理需要做得,给场景提供良好的层次关系,以便更好地进行筛选(Culling)和隐藏面消除(Hidden surface removal)。
场景管理涉及到可视性处理(Visibility processing)和碰撞检测(Collision detection),系统需要判断场景的哪些部分在视见约束体之内,另外如果两个物体有碰撞关系,则需要计算碰撞点的值。
为了达到游戏中的实时效果,传统的技术不可能适用,因为场景己经非常复杂,如果只采用Z 缓冲的方法进行可见性处理是不现实的。
目前己经有了将场景分层的方法,可以把辅助数据结构应用于场景中,先把场景分区,再分物体,甚至一直分割到多边形。
如在室内场景管理中有两个经常用到的层次体系:BSP(Binary Space Partitioning)树,这是八叉树的推广,和包围体树(Boundingvolume tree)。
前者用于加速剔除,而后者主要用于碰撞检测。
本节简单讨论如何使用层次体系进行更加高效的筛选以及可以采用什么样的数据结构来组织场景。
1.2 场景的组织和管理场景的组织结构是渲染系统最基础和最重要的部分,也是一个实现的难点。
它的决定会决定很多后续的工作,如碰撞检测,消隐,阴影等。
首先要涉及到的概念是空间细分,空间细分考虑整个物体空间并且根据物体的空间占有(Object occupancy)对空间中的每一个点进行分类。
可以把世界空间中的物体细分为立方体素(voxel),再对体素进行分类。
八叉树(octree)是一种描述三维空间的树状数据结构,它可以描述一个三维场景内物体的分布情况,并简单地将体素安排在层次结构中。
因此场景管理可以在预处理的时候建立一棵树,这里可以忽略物体的表示方法,而把焦点集中在场景的划分上。
在树建立起来之后,通过实时遍历这棵树来发现是否有两个物体占据了同一个空间而发生冲突,或者一个物体的空间是否不在视见约束体之内。
linux中tree的源码
Tree是一个在Linux环境下常用的命令行工具,用于以树状结构展示目录结构。
它有助于用户快速了解目录中的文件和子目录的层次关系,提高了查看目录结构的效率。
Tree的源码主要由C语言编写,主要包括对目录结构的操作以及输出格式的处理。
在源码中,可以看到对文件和目录的遍历操作,以及递归调用来实现树状结构的展示。
同时,源码中还包括了对命令行参数的解析和处理,以及对输出格式的控制,使得Tree可以根据用户的需求来展示目录结构。
在源码中,还可以看到对路径处理、文件类型判断等相关操作,以保证Tree在展示目录结构时能够准确地反映出文件和子目录之间的关系。
同时,对于不同操作系统的兼容性以及错误处理也都有相应的代码实现,以保证Tree在不同环境中都能正常运行。
总的来说,Tree的源码实现了对目录结构的递归遍历和树状展示,并且考虑了不同环境下的兼容性和用户需求,使得Tree成为了Linux环境下一个非常好用的目录结构展示工具。
关于实现二叉树,平衡树的代码及每一行代码的解释
关于实现二叉树,平衡树的代码及每一行代码的解释以下为python实现二叉树的代码,每一行代码的解释已在注释中说明:# 定义二叉树的节点class BinaryTree:def __init__(self, value):# 节点的值self.value = value# 左子树self.leftchild = None# 右子树self.rightchild = None# 添加左子树节点def add_leftchild(self, node):self.leftchild = node# 添加右子树节点def add_rightchild(self, node):self.rightchild = node# 创建二叉树root = BinaryTree(1)node2 = BinaryTree(2)node3 = BinaryTree(3)node4 = BinaryTree(4)node5 = BinaryTree(5)root.add_leftchild(node2)root.add_rightchild(node3)node2.add_leftchild(node4)node2.add_rightchild(node5)以下为python实现平衡树的代码(基于AVL树),每一行代码的解释已在注释中说明:# 定义AVL树节点class AVLNode:def __init__(self, value):# 节点值self.value = value# 左子树self.leftchild = None# 右子树self.rightchild = None# 高度self.height = 1# 定义AVL树class AVLTree:def __init__(self):# 根节点self.root = None# 获取树高def get_height(self, root):if root is None:return 0else:return root.height# 获取平衡因子def get_balance_factor(self, root): if root is None:return 0else:return self.get_height(root.leftchild) -self.get_height(root.rightchild)# 右旋转def right_rotate(self, root):lefttree = root.leftchildrighttree = lefttree.rightchild# 右旋转lefttree.rightchild = rootroot.leftchild = righttree# 更新节点高度root.height = 1 + max(self.get_height(root.leftchild), self.get_height(root.rightchild))lefttree.height = 1 + max(self.get_height(lefttree.leftchild), self.get_height(lefttree.rightchild))# 返回新的根节点return lefttree# 左旋转def left_rotate(self, root):righttree = root.rightchildlefttree = righttree.leftchild# 左旋转righttree.leftchild = rootroot.rightchild = lefttree# 更新节点高度root.height = 1 + max(self.get_height(root.leftchild),self.get_height(root.rightchild))righttree.height = 1 + max(self.get_height(righttree.leftchild), self.get_height(righttree.rightchild))# 返回新的根节点return righttree# 插入节点def insert_node(self, root, value):# 如果树为空,则插入新节点if root is None:return AVLNode(value)# 如果插入的值小于根节点,则插入到左子树中if value < root.value:root.leftchild = self.insert_node(root.leftchild, value) # 如果插入的值大于根节点,则插入到右子树中else:root.rightchild = self.insert_node(root.rightchild, value)# 更新节点高度root.height = 1 + max(self.get_height(root.leftchild), self.get_height(root.rightchild))# 获取平衡因子balance_factor = self.get_balance_factor(root)# 平衡树# 左左情况if balance_factor > 1 and value < root.leftchild.value:return self.right_rotate(root)# 左右情况if balance_factor > 1 and value > root.leftchild.value:root.leftchild = self.left_rotate(root.leftchild)return self.right_rotate(root)# 右右情况if balance_factor < -1 and value > root.rightchild.value: return self.left_rotate(root)# 右左情况if balance_factor < -1 and value < root.rightchild.value: root.rightchild = self.right_rotate(root.rightchild)return self.left_rotate(root)return root# 中序遍历def in_order(self, root):res = []if root is not None:res = self.in_order(root.leftchild)res.append(root.value)res = res + self.in_order(root.rightchild)return res# 创建AVL树avl_tree = AVLTree()# 插入节点root = Noneroot = avl_tree.insert_node(root, 10) root = avl_tree.insert_node(root, 20) root = avl_tree.insert_node(root, 30) root = avl_tree.insert_node(root, 40) root = avl_tree.insert_node(root, 50) root = avl_tree.insert_node(root, 25)# 中序遍历print(avl_tree.in_order(root))。
pso优化bp算法python代码精选全文完整版
可编辑修改精选全文完整版pso优化bp算法python代码PSO优化BP算法Python代码BP神经网络是一种常用的人工神经网络,它可以用于分类、回归等任务。
但是,BP神经网络的训练过程需要大量的计算和时间,而且容易陷入局部最优解。
为了解决这些问题,我们可以使用粒子群优化(PSO)算法来优化BP神经网络。
PSO算法是一种基于群体智能的优化算法,它模拟了鸟群或鱼群等生物的行为,通过不断地搜索和迭代,找到最优解。
在PSO算法中,每个粒子代表一个解,它们通过不断地移动和更新自己的位置和速度,来寻找最优解。
下面是使用Python实现PSO优化BP算法的代码:```pythonimport numpy as npimport random# 定义BP神经网络类class BPNN:def __init__(self, input_size, hidden_size, output_size):self.input_size = input_sizeself.hidden_size = hidden_sizeself.output_size = output_sizeself.W1 = np.random.randn(self.input_size, self.hidden_size) self.W2 = np.random.randn(self.hidden_size, self.output_size) # 定义sigmoid函数def sigmoid(self, x):return 1 / (1 + np.exp(-x))# 定义前向传播函数def forward(self, X):self.z2 = np.dot(X, self.W1)self.a2 = self.sigmoid(self.z2)self.z3 = np.dot(self.a2, self.W2)y_hat = self.sigmoid(self.z3)return y_hat# 定义损失函数def loss(self, X, y):y_hat = self.forward(X)J = 0.5 * sum((y - y_hat) ** 2)return J# 定义反向传播函数def backward(self, X, y):y_hat = self.forward(X)delta3 = np.multiply(-(y - y_hat), self.sigmoid(self.z3) * (1 - self.sigmoid(self.z3)))dJdW2 = np.dot(self.a2.T, delta3)delta2 = np.dot(delta3, self.W2.T) * self.sigmoid(self.z2) * (1 - self.sigmoid(self.z2))dJdW1 = np.dot(X.T, delta2)return dJdW1, dJdW2# 定义PSO算法类class PSO:def __init__(self, n_particles, input_size, hidden_size, output_size, max_iter, c1, c2, w):self.n_particles = n_particlesself.input_size = input_sizeself.hidden_size = hidden_sizeself.output_size = output_sizeself.max_iter = max_iterself.c1 = c1self.c2 = c2self.w = wself.particles = []self.gbest = Noneself.gbest_loss = float('inf')# 初始化粒子群for i in range(self.n_particles):bpnn = BPNN(self.input_size, self.hidden_size, self.output_size) particle = {'position': [bpnn.W1, bpnn.W2], 'velocity': [np.zeros((self.input_size, self.hidden_size)), np.zeros((self.hidden_size, self.output_size))], 'pbest': None, 'pbest_loss': float('inf')}self.particles.append(particle)# 定义更新粒子位置和速度的函数def update(self):for particle in self.particles:# 更新速度particle['velocity'][0] = self.w * particle['velocity'][0] + self.c1 * random.random() * (particle['pbest'][0] - particle['position'][0]) + self.c2 * random.random() * (self.gbest[0] - particle['position'][0])particle['velocity'][1] = self.w * particle['velocity'][1] + self.c1 * random.random() * (particle['pbest'][1] - particle['position'][1]) + self.c2 * random.random() * (self.gbest[1] - particle['position'][1])# 更新位置particle['position'][0] += particle['velocity'][0]particle['position'][1] += particle['velocity'][1]# 更新pbest和gbestbpnn = BPNN(self.input_size, self.hidden_size, self.output_size) bpnn.W1 = particle['position'][0]bpnn.W2 = particle['position'][1]loss = bpnn.loss(X, y)if loss < particle['pbest_loss']:particle['pbest'] = [bpnn.W1, bpnn.W2]particle['pbest_loss'] = lossif loss < self.gbest_loss:self.gbest = [bpnn.W1, bpnn.W2]self.gbest_loss = loss# 定义训练函数def train(self, X, y):for i in range(self.max_iter):self.update()print('Iteration:', i, 'Loss:', self.gbest_loss)# 测试代码X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])y = np.array([[0], [1], [1], [0]])pso = PSO(n_particles=10, input_size=2, hidden_size=4, output_size=1,max_iter=100, c1=2, c2=2, w=0.8)pso.train(X, y)```在上面的代码中,我们首先定义了一个BP神经网络类,包括前向传播、损失函数和反向传播等方法。
SharpDevelop源码分析
目录序 (2)一、基本概念 (2)二、主程序 (5)三、插件系统 (7)SharpDevelop的AddInTree View 插件 (20)转载:/passos/article/details/124722序最近开始学习.Net,遇到了一个比较不错的开源的IDE SharpDevelop。
这个开发工具是使用C#开发的,比较吸引我的一点就是它是采用了和Eclipse类似的插件技术来实现整个系统的。
而这个插件系统是我最感兴趣的地方,因此开始了一段代码的研究。
在本篇之后,我会陆续把我研究的心得写下来。
由于是在网吧上网,有诸多不便,因此可能会拖比较长的时间。
一、基本概念首先,我们先来对SharpDevelop 有一个比较感性的认识。
你可以从这里下载到它的可执行程序和代码包/,安装的废话就不说了,先运行一下看看。
感觉跟VS很像吧?不过目前的版本是1.0.0.1550,还有很多地方需要完善。
关于代码和系统结构,SharpDevelop的三个作者写了一本书,各位看官可以参考一下,不过我看过之后还是有很多地方不太理解。
然后,让我来解释一下什么叫插件以及为什么要使用插件系统。
我们以往的系统,开发人员编译发布之后,系统就不允许进行更改和扩充了,如果要进行某个功能的扩充,则必须要修改代码重新编译发布。
这就给我们带来了比较大的不方便。
解决的方法有很多,例如提供配置等等方法。
在解决方案之中,插件是一个比较好的解决方法。
大家一定知道PhotoShop、WinAmp吧,他们都有“插件”的概念,允许其他开发人员根据系统预定的接口编写扩展功能(例如PhotoShop中各种各样的滤镜)。
所谓的插件就是系统的扩展功能模块,这个模块是以一个独立文件的形式出现的,与系统是相对独立。
在系统设计期间并不知道插件的具体功能,仅仅是在系统中为插件留下预定的接口,系统启动的时候根据插件的配置寻找插件,根据预定的接口把插件挂接到系统中。
这样的方式带来什么样的优点呢?首先是系统的扩展性大大的增强了,如果我们在系统发布后需要对系统进行扩充,不必重新编译,只需要修改插件就可以了。
Pstree源码分析
Pstree源码分析一.getopt_long获取参数,根据参数设置相应的变量。
二.read_proc ()主要函数,获取所有的process,生成tree.#define PROC_BASE "/proc"dir =opendir (PROC_BASE))while ((de = readdir (dir)) != NULL)if ((pid = (pid_t) atoi (de->d_name)) != 0) //即读取/proc/numbersprintf (path, "%s/%d/stat", PROC_BASE, pid);//path赋值为/proc/number/statif ((file = fopen (path, "r")) != NULL)sprintf (path, "%s/%d", PROC_BASE, pid); //path赋值为/proc/numberfread(readbuf, 1, BUFSIZ, file) ; //读取/proc/number/stat内容到readbufif ((comm = strchr(readbuf, '('))&& (tmpptr = strrchr(comm, ')')))//comm指向/proc/number/stat第一次出现’(‘的位置//tmpptr指向/proc/number/stat最后一次出现’)‘的位置++comm; *tmpptr = 0; //即comm为/proc/number/stat中command内容if (sscanf(tmpptr+2, "%*c %d", &ppid) == 1)//从tmpptr+2位置开始的第一个整数指向为ppidsprintf (taskpath, "%s/task", path);//taskpath赋值为/proc/number/taskif ((taskdir=opendir(taskpath))!=0)sprintf(threadname,"{%s}",comm);// threadname赋值为commandwhile ((dt = readdir(taskdir)) != NULL)if ((thread=atoi(dt->d_name)) !=0)//读取/proc/number/task中的numberif (thread != pid)//即该number!=pid,也就是该process有子线程add_proc(threadname, thread, pid, st.st_uid, NULL, 0);………………..…………………略add_proc (comm, pid, ppid, st.st_uid, NULL, 0);add_proc()函数add_proc (const char *comm, pid_t pid, pid_t ppid, uid_t uid,const char *args, int size)if (!(this = find_proc (pid)))this = new_proc (comm, pid, uid); //如果没有该process,则生成该pid对应的PROC结构else{strcpy (this->comm, comm);this->uid = uid;}if (!(parent = find_proc (ppid)))parent = new_proc ("?", ppid, 0);//如果没有该ppid对应的process,则生成ppid对应的PROC结构…………………略add_child (parent, this);add_child()函数add_child (PROC * parent, PROC * child)CHILD *new, **walk;new = malloc (sizeof (CHILD))new->child = child;for (walk = &parent->children; *walk; walk = &(*walk)->next)//在该parent对应的children链中循环if ((cmp = strcmp ((*walk)->child->comm, child->comm)) > 0) break;else if (!cmp && (*walk)->child->uid > child->uid)break;new->next = *walk;*walk = new;//在children链中找到合适的位置将该child添加进去添加规则:1.按children的command项的字母排序2.如果command相同,按children的uid从小到大排序三.dump_tree主要函数,将tree按规则输出dump_tree (PROC * current, int level, int rep, int leaf, int last, uid_t prev_uid, int closing)if (!leaf) …………输出一些符号if(rep>=2) out_string ("*[") //即该PROC不止一个,有重复的for (here = current->comm; *here; here++)………out_char (*here); ……将该process对应的command输出if (print_args || !current->children) //该process没有children…….. ut_char (']');……..else //该process有childrenfor (walk = current->children; walk; walk = next)count = 0;next = walk->next;scan = &walk->next;while (*scan)if (!tree_equal (walk->child, (*scan)->child))//如果该child和parent的下一个child形成的tree并不equalscan = &(*scan)->next;else //如果tree是equal的{if (next == *scan)next = (*scan)->next;count++; //count加,即表示该tree有多少*scan = (*scan)->next;……..dump_tree (walk->child, level + 1, count + 1,walk == current->children, !next, current->uid, closing + (count ? 1 : 0));//递归调用dump_tree,dump该process的children四.改进需求:所有由supervise启动的程序,显示程序目录,gpid 。
简单分析ztree源码
简单分析ztree源码为了把 SVG标注代码抽成⼀个库,我要学习⼀下是怎么写的。
开始正⽂。
这只是⼀个很简单的版本,以后可能会详细分析...(function ($) {var settings = {},roots = {},caches = {},_consts = { /*...*/ },_setting = { /*...*/ },_initRoot = function (setting) { /*...*/ },_initCache = function (setting) { /*...*/ },_bindEvent = function (setting) { /*...*/ },_unbindEvent = function (setting) { /*...*/ },_eventProxy = function (setting) { /*...*/ },_initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { /*...*/ },_init = { /*...*/ },data = { /*...*/ },event = { /*...*/ },handler = { /*...*/ },tools = { /*...*/ },view = { /*...*/ };$.fn.zTree = {consts: _consts,_z: { /*...*/ },getZTreeObj: function (treeId) { /*...*/ },destroy: function (treeId) { /*...*/ },init: function (obj, zSetting, zNodes) { /*...*/ }};var zt = $.fn.zTree,$$ = tools.$,consts = zt.consts;})(jQuery);整个 ztree 是个⾃执⾏函数。
linux命令之pstree命令
linux命令之pstree命令
linux系统下pstree命令能够以树状图的方式来显示每个进程之间的派生关系。
下面由店铺为大家整理了linux命令之pstree命令的相关知识,希望对大家有所帮助!
linux命令之pstree命令详解
pstree命令以树状图的方式展现进程之间的派生关系,显示效果比较直观。
语法
pstree(选项)
选项
-a:显示每个程序的完整指令,包含路径,参数或是常驻服务的标示;
-c:不使用精简标示法;
-G:使用VT100终端机的列绘图字符;
-h:列出树状图时,特别标明现在执行的程序;
-H<程序识别码>:此参数的效果和指定"-h"参数类似,但特别标明指定的程序;
-l:采用长列格式显示树状图;
-n:用程序识别码排序。
预设是以程序名称来排序;
-p:显示程序识别码;
-u:显示用户名称;
-U:使用UTF-8列绘图字符;
-V:显示版本信息。
linux命令之pstree命令实例
显示当前所有进程的进程号和进程id
pstree -p
显示所有进程的所有详细信息,遇到相同的进程名可以压缩显示。
pstree -a。
sorcetree中psswd文件解析
SORCETREE 中 psswd 文件是一种加密文件,它存储了用户在使用Sourcetree 软件时需要输入的密码。
对于一些用户来说,他们可能想要了解 psswd 文件的解析方式,以便在需要的时候能够找回自己的密码或者进行相应的操作。
下面将对 sorcetree 中 psswd 文件的解析进行详细介绍。
一、psswd 文件的结构在 sorcetree 软件中,psswd 文件的结构是经过加密的,通常以二进制形式存在。
这使得直接打开 psswd 文件进行查看是不可行的。
二、psswd 文件的解密方法1.使用 Sorcetree 软件的相关功能Sorcetree 软件本身提供了一些密码管理和恢复密码的功能,用户可以尝试通过软件内置的功能来解密 psswd 文件。
在软件中找到密码管理工具,输入相关的信息,尝试恢复密码或者查看保存的密码信息。
2.使用第三方工具除了使用 Sorcetree 软件自带的密码管理功能外,还可以尝试使用一些第三方工具来解密 psswd 文件。
有一些专门用于解密加密文件的软件,用户可以搜索并尝试使用这些软件来解密 psswd 文件。
3.借助专业人士的帮助如果以上的方法都无法解决问题,用户还可以寻求专业人士的帮助。
有一些专业的数据恢复公司或者研究机构可能具有解密 psswd 文件的能力,用户可以通联他们寻求帮助。
三、注意事项1.在尝试解密 psswd 文件时,用户需要注意保护好自己的计算机和相关信息。
尤其是在使用第三方工具或寻求帮助时,要确保选择正规可靠的途径,避免遭受信息泄露或者其他安全风险。
2.在尝试解密psswd 文件时,用户需要根据自己的实际情况进行选择。
有些方法可能并不适用于所有情况,需要根据具体的情况进行灵活应对。
四、结论SORCETREE 中的 psswd 文件是一种加密文件,用户在尝试解密时需要注意保护好自己的计算机和相关信息,可以尝试使用软件自带的功能、第三方工具或者寻求专业人士的帮助来解决问题。
对plotTree的解释
对plotTree的解释1.>>>a = 1/2/2>>>a>>>0.252.def plotMidText(cntrPt,parentPt,txtString): #在⽗⼦节点间填充⽂本信息xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0]yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1]createPlot.ax1.text(xMid,yMid,txtString) #x和y的坐标轴和填充内容#为了⽅便理解这个函数我设定getNumLeafs=3 getDepth=21.def plotTree(myTree,parentPt,nodeTxt):2. numLeafs = getNumLeafs(myTree)3. depth = getTreeDepth(myTree) #这个变量没有⽤到4. firstStr = list(myTree.keys())[0] #得到字典的第⼀个键5. cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW,6. plotTree.yOff) #计算⼦节点的坐标(0.5,1.0)下⾯会改变哟7. plotMidText(cntrPt,parentPt,nodeTxt)8. plotNode(firstStr,cntrPt,parentPt,decisionNode)9. secondDict = myTree[firstStr] #{0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}, 3: 'maybe'}10. plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD #到这⾥⼦系欸但坐标 (0.5,0.5)11. for key in secondDict.keys():12. if type(secondDict[key]).__name__ == 'dict':13. plotTree(secondDict[key],cntrPt,str(key)) #递归调⽤plotTree14. else:15. plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW16. plotNode(secondDict[key],(plotTree.xOff,plotTree.yOff),17. cntrPt,leafNode) #调⽤上⾯的函数plotNode()18. plotMidText((plotTree.xOff,plotTree.yOff),cntrPt,str(key))19. plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD#为了⽅便理解这个函数我设定numLeafs=3 depth=2def createPlot(inTree): #画图函数fig = plt.figure(1,facecolor = 'white')fig.clf() #清空画布axprops = dict(xticks=[],yticks=[]) #此参数表⽰坐标刻度,[]表⽰不显⽰刻度,可以作为参数传⼊,也可以⽤plt.xticks([1,3,4])单独设置createPlot.ax1 = plt.subplot(111,frameon=False,**axprops)plotTree.totalW = float(getNumLeafs(inTree)) #宽度=3.0plotTree.totalD = float(getTreeDepth(inTree)) #深度=2.0plotTree.xOff = -0.5/plotTree.totalW;plotTree.yOff = 1.0; #得到两个全局变量 x和y (-1/6,1.0)plotTree(inTree,(0.5,1.0),'') #(0.5,1.0)顶层节点的坐标plt.show()这段代码个⼈觉得⽐较难理解(为了⽅便理解我们这⾥将宽度设置为3.0,深度设置为2.0)顶点坐标为(0.5,1.0)采取的myTree={'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}}第⼀步我们画图时候调⽤的是createPlot()这个函数,从函数我们得知两个全局变量(-1/6,1.0)即xOff,yOff第⼆步我们看到该函数中存在plotTree(inTree,(0.5,1.0),'') 这段代码,即调⽤了上⾯⼀个函数plotTree,经过计算我们得到⼦节点的第⼀个坐标(0.5,1.0) 即函数中第6⾏第三步通过调⽤plotMidText和plotNode将顶点坐标内容(这⾥填充的内容是键的名称)填充和设置格式,即顶点坐标(这⾥因为⼦节点和⽗节点是同⼀个点,所以顶点没有指向的⾃⼰的箭头)第四步我们得到myTree第⼀个键对应的值并设为字典secondDict,第10⾏计算变量y的新值0.5,注意⼦节点此时还是(0.5,1.0)第五步遍历secondDict中的所有键,如果键对应的值是字典呢么递归调⽤plotTree注意⾥⾯的参数⼦节点(0.5,1.0)是panterPt的新参数,myTree对应的参数是secondDict[key]第六步由给出myTree得知for循环中存在不是字典的值,呢么进⼊else:改变了xOff的值(经计算的为1/6)调⽤plotNode(secondDict[key],(1/6,0.5),(0.5,1.0),leafnode)即该处为叶⼦第六步我们接着第五步递归调⽤,此时numLeafs变为2,depth变为1(这个depth没⽤到可以忽略)我们还是取新字典的第⼀个键,计算⼦节点得到(2/3,0.5)第七步同第三步骤,不过这⾥⼦节点和⽗节点不⼀致⼦节点(2/3,0.5)⽗节点(0.5,1.0)⼆者之间存在⽗节点指向⼦节点的箭头。
pstree原理
pstree 是一个用于显示进程树的Linux命令。
它以树状结构的形式展示当前系统中运行的进程及其关系。
pstree 命令的原理涉及到以下几个方面:
进程继承关系:在Linux系统中,进程可以通过父进程派生出子进程。
父进程通常是启动子进程的进程,子进程继承了父进程的一些属性和环境变量。
这种父子关系构成了进程树的基础。
进程信息存储:Linux内核维护了关于每个进程的信息,包括进程的标识号(PID)、父进程的PID、进程状态、进程优先级、程序名等。
这些信息存储在/proc 文件系统中的进程目录中。
pstree命令的工作:当您在终端中运行pstree 命令时,它会遍历/proc 文件系统中的进程信息,识别每个进程的PID和父进程的PID。
然后,pstree 将这些信息组织成一个树状结构,以显示进程树。
显示格式:pstree 命令通常以文本形式输出进程树。
树的根节点是最初的init进程(通常具有PID 1),然后它显示该进程的子进程,以及每个子进程的子进程,以此类推。
每个进程的名称通常是进程的命令行,可以通过-p 选项来显示PID。
选项和自定义:pstree 命令支持一些选项,可以用来自定义输出格式,例如-a 选项用来显示完整的命令行,-n 选项用来按照数字顺序排序进程。
您可以使用man pstree 命令来查看pstree 的完整文档和选项列表。
总之,pstree 命令的原理涉及到遍历进程信息、识别进程的父子关系,并将这些信息组织成树状结构来显示系统中运行的进程。
这有助于用户更好地了解进程之间的关系,特别是在排查进程问题或分析系统性能时非常有用。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Pstree源码分析
一.getopt_long获取参数,根据参数设置相应的变量。
二.read_proc ()主要函数,获取所有的process,生成tree.
#define PROC_BASE "/proc"
dir =opendir (PROC_BASE))
while ((de = readdir (dir)) != NULL)
if ((pid = (pid_t) atoi (de->d_name)) != 0) //即读取/proc/number
sprintf (path, "%s/%d/stat", PROC_BASE, pid);
//path赋值为/proc/number/stat
if ((file = fopen (path, "r")) != NULL)
sprintf (path, "%s/%d", PROC_BASE, pid); //path赋值为/proc/number
fread(readbuf, 1, BUFSIZ, file) ; //读取/proc/number/stat内容到readbuf
if ((comm = strchr(readbuf, '('))&& (tmpptr = strrchr(comm, ')')))
//comm指向/proc/number/stat第一次出现’(‘的位置
//tmpptr指向/proc/number/stat最后一次出现’)‘的位置
++comm; *tmpptr = 0; //即comm为/proc/number/stat中command内容
if (sscanf(tmpptr+2, "%*c %d", &ppid) == 1)
//从tmpptr+2位置开始的第一个整数指向为ppid
sprintf (taskpath, "%s/task", path);
//taskpath赋值为/proc/number/task
if ((taskdir=opendir(taskpath))!=0)
sprintf(threadname,"{%s}",comm);
// threadname赋值为command
while ((dt = readdir(taskdir)) != NULL)
if ((thread=atoi(dt->d_name)) !=0)
//读取/proc/number/task中的number
if (thread != pid)
//即该number!=pid,也就是该process有子线程
add_proc(threadname, thread, pid, st.st_uid, NULL, 0);
………………..
…………………略
add_proc (comm, pid, ppid, st.st_uid, NULL, 0);
add_proc()函数
add_proc (const char *comm, pid_t pid, pid_t ppid, uid_t uid,
const char *args, int size)
if (!(this = find_proc (pid)))
this = new_proc (comm, pid, uid); //如果没有该process,则生成该pid对应的PROC结构else
{
strcpy (this->comm, comm);
this->uid = uid;
}
if (!(parent = find_proc (ppid)))
parent = new_proc ("?", ppid, 0);
//如果没有该ppid对应的process,则生成ppid对应的PROC结构…………………略
add_child (parent, this);
add_child()函数
add_child (PROC * parent, PROC * child)
CHILD *new, **walk;
new = malloc (sizeof (CHILD))
new->child = child;
for (walk = &parent->children; *walk; walk = &(*walk)->next)
//在该parent对应的children链中循环
if ((cmp = strcmp ((*walk)->child->comm, child->comm)) > 0) break;
else if (!cmp && (*walk)->child->uid > child->uid)
break;
new->next = *walk;
*walk = new;
//在children链中找到合适的位置将该child添加进去
添加规则:
1.按children的command项的字母排序
2.如果command相同,按children的uid从小到大排序
三.dump_tree主要函数,将tree按规则输出
dump_tree (PROC * current, int level, int rep, int leaf, int last, uid_t prev_uid, int closing)
if (!leaf) …………输出一些符号
if(rep>=2) out_string ("*[") //即该PROC不止一个,有重复的for (here = current->comm; *here; here++)
………out_char (*here); ……将该process对应的command输出
if (print_args || !current->children) //该process没有children
…….. ut_char (']');……..
else //该process有children
for (walk = current->children; walk; walk = next)
count = 0;
next = walk->next;
scan = &walk->next;
while (*scan)
if (!tree_equal (walk->child, (*scan)->child))
//如果该child和parent的下一个child形成的tree并不equal
scan = &(*scan)->next;
else //如果tree是equal的
{
if (next == *scan)
next = (*scan)->next;
count++; //count加,即表示该tree有多少
*scan = (*scan)->next;
……..
dump_tree (walk->child, level + 1, count + 1,walk == current->children, !next, current->uid, closing + (count ? 1 : 0));
//递归调用dump_tree,dump该process的children
四.改进
需求:所有由supervise启动的程序,显示程序目录,gpid 。
Pstree在不加user显示的时候,出现
init--2*[supervise---tncache---tncache---35*[tncache]] 两个supervise并成一行
改为分开显示
思路:程序目录:/proc/number/exe符号链接,指向被执行的二进制代码.
gpid : /proc/number/stat获取
判断是否supervise启动:循环parent,找出是否直接或者间接parent的comand 是supervise
分开显示:改变dump_tree的时候,tree_equal的逻辑
将parent是init进程,command是supervise,并且supervise所在的tree是equal 的,按照原来非equal的逻辑处理。