前面我们介绍了队列、堆栈、链表,你亲自动手实践了吗?今天我们来到了树的部分,树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树。其他各种各样的树将来我将会一一为大家介绍,记得关注我的文章哦~

首先,树的形状就是类似这个样子的:

它最顶上面的点叫做树的根节点,一棵树也只能有一个根节点,在节点下面可以有多个子节点,子节点的数量,我们这里不做要求,而没有子节点的节点叫做叶子节点。

好,关于树的基本概念就介绍到这里了,话多千遍不如动手做一遍,接下来我们边做边学,我们来创建一棵树:

# 定义一个普通的树类
class Tree:
def __init__(self, data):
self.data = data
self.children = [] def get(self):
return self.data def set(self):
return self.data def addChild(self, child):
self.children.append(child) def getChildren(self):
return self.children

这就是我们定义好的树类了,并给树添加了三个方法,分别是获取节点数据、设置节点数据、添加子节点、获取子节点。

这里的树类其实是一个节点类,很多个这样的节点可以构成一棵树,而我们就用根节点来代表这颗树。

接下来我们实例化一棵树:

# 初始化一个树
tree = Tree(0)
# 添加三个子节点
tree.addChild(Tree(1))
tree.addChild(Tree(2))
tree.addChild(Tree(3))
children = tree.getChildren()
# 每个子节点添加两个子节点
children[0].addChild(Tree(4))
children[0].addChild(Tree(5))
children[1].addChild(Tree(6))
children[1].addChild(Tree(7))
children[2].addChild(Tree(8))
children[2].addChild(Tree(9))

我们实例化好的树大概是这个样子的:

OK,我们的树已经实例化好了,我们先来对它分别采用递归和非递归的方式进行广度优先遍历:

广度优先遍历

广度优先遍历,就是从上往下,一层一层从左到右对树进行遍历。

在用非递归方式进行广度优先遍历的时候,我们需要用到前面介绍过的队列类型,所以我们来定义一个队列类:

# 用以实现广度优先遍历
class Queue():
def __init__(self):
self.__list = list() def isEmpty(self):
return self.__list == [] def push(self, data):
self.__list.append(data) def pop(self):
if self.isEmpty():
return False
return self.__list.pop(0)

用队列实现广度优先遍历

利用队列我们只要在节点出队的时候让该节点的子节点入队即可。

# 广度优先遍历
def breadthFirst(tree):
queue = Queue()
queue.push(tree)
result = []
while not queue.isEmpty():
node = queue.pop()
result.append(node.data)
for c in node.getChildren():
queue.push(c)
return result

调用一下:

print(breadthFirst(tree))

输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

递归实现广度优先遍历

# 递归方式实现广度优先遍历
def breadthFirstByRecursion(gen, index=0, nextGen=[], result=[]): if type(gen) == Tree:
gen = [gen]
result.append(gen[index].data) children = gen[index].getChildren() nextGen += children
if index == len(gen)-1:
if nextGen == []:
return
else:
gen = nextGen
nextGen = []
index = 0
else:
index += 1
breadthFirstByRecursion(gen, index, nextGen,result) return result

调用一下:

print(breadthFirstByRecursion(tree))

输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

深度优先遍历

深度优先遍历,就是从上往下,从左到右,先遍历节点的子节点再遍历节点的兄弟节点。

采用非递归方式实现深度优先遍历呢,我们需要用到前面介绍过的堆栈结构,所以我们现在定义一个堆栈类吧:

# 用以实现深度优先遍历
class Stack():
def __init__(self):
self.__list = list() def isEmpty(self):
return self.__list == [] def push(self, data):
self.__list.append(data) def pop(self):
if self.isEmpty():
return False
return self.__list.pop()

利用堆栈实现深度优先遍历

实现深度优先遍历,我们只要在节点出栈的时候把该节点的子节点从左到右压入堆栈即可。

# 深度优先遍历
def depthFirst(tree):
stack = Stack()
stack.push(tree)
result = []
while not stack.isEmpty():
node = stack.pop()
result.append(node.data)
children = node.getChildren()
children = reversed(children)
for c in children:
stack.push(c)
return result

调用一下:

# 深度优先遍历
print(depthFirst(tree))

输出:[0, 1, 4, 5, 2, 6, 7, 3, 8, 9]

递归实现深度优先遍历

# 递归方式实现深度优先遍历
def depthFirstByRecursion(tree, result=[]):
result.append(tree.data)
children = tree.getChildren()
for c in children:
depthFirstByRecursion(c, result)
return result

调用一下:

print(depthFirstByRecursion(tree))

输出:[0, 1, 4, 5, 2, 6, 7, 3, 8, 9]

好啦,今天我们的树就介绍到这里了,对于广度优先遍历的递归实现,你有更好的方法吗?请留言告诉我吧。

数据结构-树以及深度、广度优先遍历(递归和非递归,python实现)的更多相关文章

  1. 数据结构二叉树的递归与非递归遍历之java,javascript,php实现可编译(1)java

    前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序 ...

  2. 数据结构作业——图的存储及遍历(邻接矩阵、邻接表+DFS递归、非递归+BFS)

    邻接矩阵存图 /* * @Author: WZY * @School: HPU * @Date: 2018-11-02 18:35:27 * @Last Modified by: WZY * @Las ...

  3. Java实现二叉树的先序、中序、后序、层序遍历(递归和非递归)

    二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易 ...

  4. C实现二叉树(模块化集成,遍历的递归与非递归实现)

    C实现二叉树模块化集成 实验源码介绍(源代码的总体介绍):header.h : 头文件链栈,循环队列,二叉树的结构声明和相关函数的声明.LinkStack.c : 链栈的相关操作函数定义.Queue. ...

  5. 二叉树的创建、遍历(递归和非递归实现)、交换左右子数、求高度(c++实现)

    要求:以左右孩子表示法实现链式方式存储的二叉树(lson—rson),以菜单方式设计并完成功能任务:建立并存储树.输出前序遍历结果.输出中序遍历结果.输出后序遍历结果.交换左右子树.统计高度,其中对于 ...

  6. 二叉树之AVL树的平衡实现(递归与非递归)

    这篇文章用来复习AVL的平衡操作,分别会介绍其旋转操作的递归与非递归实现,但是最终带有插入示例的版本会以递归呈现. 下面这张图绘制了需要旋转操作的8种情况.(我要给做这张图的兄弟一个赞)后面会给出这八 ...

  7. 二叉树3种递归和非递归遍历(Java)

    import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...

  8. 二叉树前中后/层次遍历的递归与非递归形式(c++)

    /* 二叉树前中后/层次遍历的递归与非递归形式 */ //*************** void preOrder1(BinaryTreeNode* pRoot) { if(pRoot==NULL) ...

  9. JAVA递归、非递归遍历二叉树(转)

    原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { priva ...

随机推荐

  1. 微信小程序把玩(十五)checkbox组件

    原文:微信小程序把玩(十五)checkbox组件 不得不吐糟下checkbox默认样式真是有点略丑!!!checkbox组件为一个多选框被放到checkbox-group组中,并在checkbox-g ...

  2. shell中select、case的使用

    case和select结构在技术上说并不是循环, 因为它们并不对可执行代码块进行迭代. 但是和循环相似的是, 它们也依靠在代码块顶部或底部的条件判断来决定程序的分支. select   select结 ...

  3. GzipStream的简单使用压缩和解压

    压缩和解压都需要用到三个流实例,分别是文件读取流.文件写入流.压缩流. 读取流和写入流有多种形式,压缩流就一种GzipStream. 不同的是对于压缩,是需要用文件写入流作为创建压缩流实例的参数, 压 ...

  4. 声谱预测网络(Tacotron2)

    整个特征预测网络是一个带有注意力机制(attention)的seq2seq网络. 编码器-解码器(Encoder-Decoder)结构 在原始的编码器-解码器结构中,编码器(encoder)输入一个序 ...

  5. MySQL操作详解

    创建并使用数据库 查看服务器上的数据库:SHOW DATABASES; 创建数据库:CREATE DATABASE <数据库名>; 指明使用何数据库:USE <数据库名> 创建 ...

  6. WIFI Manager

    Vistumbler - wifi managerhttps://www.vistumbler.net/downloads.htmlhttps://github.com/RIEI

  7. 关于Windows更新窗口内容的问题(作为一个实验,效果很明显)

    Windows中的窗口在特定情况下会由系统进行重绘,如无效区域重新显现时,,会向窗口的处理过程发送VM_PAINT消息,但是,可能还有Windows自己的更新窗口处理,如在下面的代码中,将击键显式地转 ...

  8. OpenCv的python环境搭建

    1.python的安装参看 http://www.cnblogs.com/samo/p/6734403.html 2.OpenCv安装.opencv2.4.10可以支持vc10/vc11/vc12,o ...

  9. 简单有趣的hover

    一张图片在鼠标悬浮的时候换另一张图片 平常写张图片用img我们换一种方法用背景,然后就悬浮出 我们在加个边框试试 怎么才能让边框一起换哪? 我们嵌套一下 然后打开就是 是不是一个很简单的hover

  10. ZooKeeper 系列(三)—— Zookeeper常用 Shell 命令

    一.节点增删改查         1.1 启动服务和连接服务         1.2 help命令         1.3 查看节点列表         1.4 新增节点         1.5 查看 ...