算法 树结构,基于树的算法

  算法 树结构,基于树的算法

  Yyds干货库存

  一.概述1。树的概念树(英文:tree)是一种抽象数据类型(ADT)或实现这种抽象数据类型的数据结构,用于模拟具有树状结构的数据集。它是由n(n=1)个有限节点组成的层次集合。它被称为“树”,因为它看起来像一棵颠倒的树,也就是说,它的根朝上,叶子朝下。它具有以下特点:

  每个节点有零个或多个子节点;没有父节点的节点称为根节点;每个非根节点只有一个父节点;除了根节点,每个子节点可以被分成多个不相交的子树;例如:

  2.树的术语:节点的度:一个节点所包含的子树的个数称为该节点的度;树的度:一棵树中最大节点的度称为树的度;叶节点或终端节点:零度的节点;父节点或父节点:如果一个节点包含子节点,则该节点称为其子节点的父节点;子节点或子节点:一个节点中包含的子树的根节点称为该节点的子节点;兄弟节点:具有相同父节点的节点称为兄弟节点;节点的层次结构:从根开始定义,根是第一级,其子节点是第二级,以此类推;树的高度或深度:树中节点的最高级别;堂兄弟节点:同一级父节点的节点是彼此的堂兄弟;节点的祖先:从根到节点的分支上的所有节点;后代:子树中以某个节点为根的任何节点都称为该节点的后代。森林:m(m=0)棵不相交的树的集合称为森林;3.树的类型无序树:树中任何节点的子节点之间都没有顺序关系。这种树叫无序树,也叫自由树;有序树:树中任何节点的子节点都具有有序关系。这种树叫做有序树。二叉树

  :每个节点最多有两个子树的树称为二叉树;完全二叉树:对于二叉树,假设其深度为d(d 1)。除了D层,其他层的节点数都达到了最大,D层的所有节点都是从左到右连续紧密排列的。这样的二叉树称为完全二叉树,其中完全二叉树定义为所有叶子节点都在底部的完全二叉树;平衡二叉树(AVL树):二叉树当且仅当任意节点的两个子树的高度差不大于1;排序二叉树(二叉查找树(英文:二叉查找树),又称二叉查找树和有序二叉树);霍夫曼树(用于信息编码):加权路径最短的二叉树称为霍夫曼树或最优二叉树;B-tree:一种自平衡二叉查找树,可以优化读写操作。它可以保持数据有序,并且有两个以上的子树。4.树形存储和呈现顺序存储:数据结构存储在固定数组中,但在遍历速度上有一定优势,但由于空间较大,是非主流二叉树。二叉树通常以链的形式存储。

  链式存储:

  因为节点数无法掌握,所以常见树的存储表示都转换成二叉树进行处理,子节点数最多为2。

  5.常见的树应用场景1)xml、html等。所以为这些东西写解析器的时候不可避免的要用到树。

  2)路由协议是一种使用树的算法。

  3)mysql数据库索引

  4)文件系统的目录结构

  5)那么多经典的AI算法其实都是树搜索,机器学习中的决策树也是树结构。

  二、二叉树1、二叉树的基本概念二叉树是每个节点最多有两个子树的树结构。通常子树被称为“左子树”和“右子树”。

  2.二叉树的性质(特征)性质1:二叉树的第I层最多有2 (I-1)个节点(i 0)。

  性质:深度为k的二叉树最多有(k ^ 0)个2^k-1节点

  3:对于任意二叉树,如果叶节点数为N0,度为2的节点总数为N2,则N0=N2 1;

  属性:具有n个节点的完整二叉树的深度必须是log2(n-1)

  5:对于一棵完整的二叉树,如果从上到下从左到右编号,编号为I的节点必有其左子编号2i和右子编号2i+1;父代的个数必须是I/2 (I=1是根,除外)

  1)完全二叉树3354如果二叉树的高度为H,则除H层外,其他所有层(1 ~ h-1)的节点数达到最大。h层有叶子节点,叶子节点从左到右依次排列,是一棵完整的二叉树。

  2)全二叉树3354除叶节点外,每个节点都有左右子叶,叶节点在底部。

  3.二叉树的节点表示和树的创建。通过在Node类中定义三个属性,它们是elem本身的值,lchild的左子和rchild的右子。

  类节点(对象):

  节点类

  def __init__(self,elem=-1,lchild=None,rchild=None):

  self.elem=elem

  self.lchild=lchild

  self.rchild=rchild

  创建一个树类,给一个根节点,一开始是空的,然后添加节点。

  类别树(对象):

  树类

  def __init__(self,root=None):

  self.root=root

  定义添加(self,elem):

  向树中添加节点

  节点=节点(元素)

  #如果树为空,则为根节点赋值

  如果self.root==None:

  self.root=node

  否则:

  队列=[]

  queue.append(自我. root)

  #分层遍历现有节点

  排队时:

  #弹出队列的第一个元素

  cur=queue.pop(0)

  如果cur.lchild==None:

  cur.lchild=node

  返回

  elif cur.rchild==None:

  cur.rchild=node

  返回

  否则:

  #如果左右子树不为空,加入队列继续判断。

  queue.append(cur.lchild)

  queue.append(cur.rchild)

  三、二叉树的遍历树的遍历是树的一个重要操作。遍历是指访问树中所有节点的信息,即树中每个节点依次访问一次,且只访问一次。我们称这种访问为所有节点的遍历。然后树的两种重要遍历模式是深度优先遍历和广度优先遍历。深度优先一般使用递归,广度优先一般使用队列。一般来说,大部分可以递归实现的算法也可以通过堆栈实现。

  1.深度优先遍历对于一棵二叉树,深度优先搜索就是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。那么深度遍历有三个重要的方法。这三种方法通常用于访问树的节点。两者的区别在于访问每个节点的顺序不同。这三种遍历称为前序遍历、中序遍历和后序遍历。我们先给它们一个详细的定义,然后用例子看看它们的应用。

  1)一阶遍历

  在前序遍历中,先访问根节点,然后递归使用前序遍历访问左子树,再递归使用前序遍历访问右子树。

  节点-左侧子树-右侧子树

  定义前序(自身,根):

  一阶遍历的递归实现

  如果root==None:

  返回

  打印root.elem

  self.preorder(root.lchild)

  self.preorder(root.rchild)

  2)中间顺序遍历

  在中序遍历中,我们递归地使用中序遍历来访问左边的子树,然后是根节点,最后递归地使用中序遍历来访问右边的子树。

  左子树-根节点-右子树

  定义顺序(自身,根):

  顺序遍历的递归实现

  如果root==None:

  返回

  self.inorder(root.lchild)

  打印root.elem

  self.inorder(root.rchild)

  3)后序遍历

  在后序遍历中,我们首先递归地使用后序遍历来访问左子树和右子树,最后访问根节点。

  左子树-右子树-根节点

  定义后序(自身,根):

  递归实现后续遍历

  如果root==None:

  返回

  self.postorder(root.lchild)

  self.postorder(root.rchild)

  打印root.elem

  2.广度优先遍历(层次遍历)从树的根开始,从左到右从上到下遍历整棵树的节点。

  def width _ travel(自己,根):

  使用队列实现树的层次遍历

  如果root==None:

  返回

  队列=[]

  queue.append(根)

  排队时:

  node=queue.pop(0)

  打印node.elem,

  if node.lchild!=无:

  queue.append(node.lchild)

  if node.rchild!=无:

  queue.append(node.rchild)

  转载请联系作者取得转载授权,否则将追究法律责任。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: