二叉树的建立以及遍历的多种实现(python版)
二叉树是很重要的数据结构,在面试还是日常开发中都是很重要的角色。
首先是建立树的过程,对比C或是C++的实现来讲,其涉及到了较为复杂的指针操作,但是在面向对象的语言中,就不需要考虑指针, 内存等。首先我们需要定义一个树节点, 我们采用基于链表设计的节点, 首先定义一个数据域, 其次就是左孩子和右孩子。如下定义:
# 树节点的定义
class Node:
def __init__(self, data=-1, lchild=None, rchild=None):
self.lchild = lchild # 表示左子树
self.rchild = rchild # 表示右子树
self.data = data # 表示数据域
建立树的实现有两种,遍历建树与层次建树,这两种分别是基于堆栈和队列来实现的,先来看看最基本的递归建树。
递归建树的过程无非就是一路走到底,但是需要将节点的左右孩子节点对其余的节点相关联起来。因此,我们可以如此来实现:
def traversal_create(self, root):
data = input()
if data is "#":
return None
else:
root.data = data
root.lchild = self.traversal_create(root.lchild)
root.rchild = self.traversal_create(root.rchild)
return root
首先我们传入的参数是一个默认的节点,其data数据域为-1,然后我们接受输入的数据,赋值给节点数据域,然后就是递归了,将左右孩子节点关联起来。总体来讲,应该不难理解。
下面看看层次建树的实现,所谓层次建树其实就是基于队列的操作,利用队列先进先出的特点,每次我们访问一个节点的时候,将其存入队列中,待遍历玩当前节点的左右孩子节点,队列就弹出一个节点,之后的操作都是一样的。看看代码:
def add(self, elem):
node = Node(elem)
# 根节点
if self.root.data == -1:
self.root = node
self.myQueue.append(self.root)
else:
treeNode = self.myQueue[0] # 记录结点
if treeNode.lchild is None:
treeNode.lchild = node
self.myQueue.append(treeNode.lchild)
else:
treeNode.rchild = node
self.myQueue.append(treeNode.rchild)
self.myQueue.popleft() # 弹出已经处理好左右子树的父结点
我们输入一个数据,然后根据数据初始化一个节点,放入队列中,随后就是访问的操作了。
树的三序遍历就不用说了,基于递归的,很好理解,那么基于队列以及堆栈的的遍历呢?
对比下基于队列的建树,我们完全可以写出基于队列的遍历, 也是使用队列来存储节点,然后输出左右孩子的数据:
# 层次遍历 使用队列
def queue_tarversal(self, root):
if root is None:
return
q = deque()
q.append(root)
while q:
node = q.pop()
print(node.data)
if node.lchild is not None:
q.append(node.lchild)
else:
q.append(node.rchild)
基于堆栈的呢?联想下堆栈的特点,我们一路沿着左子树遍历下去,同时使用堆栈来存储元素,然后在弹出遍历右孩子节点:
# 使用堆栈来遍历
def stack_traversal(self, root):
if root is None:
return
mystack = []
node = root
while node or mystack:
while node:
print(node.data)
mystack.append(node)
node = node.lchild
node = mystack.pop()
node = node.rchild
数据结构是难点也是基础,不管怎么样都应该好好学习。
完整代码:
''' 二叉树的建立及实现 (递归与非递归) '''
from collections import deque # 树节点的定义
class Node:
def __init__(self, data=-1, lchild=None, rchild=None):
self.lchild = lchild # 表示左子树
self.rchild = rchild # 表示右子树
self.data = data # 表示数据域 class Create_Tree:
def __init__(self):
self.root = Node() # 表示结点
self.myQueue = deque() # 使用队列不会有太多的内存开销 # 按层次生成树
def add(self, elem):
node = Node(elem)
# 根节点
if self.root.data == -1:
self.root = node
self.myQueue.append(self.root)
else:
treeNode = self.myQueue[0] # 记录结点
if treeNode.lchild is None:
treeNode.lchild = node
self.myQueue.append(treeNode.lchild)
else:
treeNode.rchild = node
self.myQueue.append(treeNode.rchild)
self.myQueue.popleft() # 弹出已经处理好左右子树的父结点 # 递归建树
def traversal_create(self, root):
data = input()
if data is "#":
return None
else:
root.data = data
root.lchild = self.traversal_create(root.lchild)
root.rchild = self.traversal_create(root.rchild)
return root # 前序遍历输出
def digui(self, root):
if root is None:
return
print(root.data)
self.digui(root.lchild)
self.digui(root.rchild) # 使用堆栈来遍历
def stack_traversal(self, root):
if root is None:
return
mystack = []
node = root
while node or mystack:
while node:
print(node.data)
mystack.append(node)
node = node.lchild
node = mystack.pop()
node = node.rchild # 层次遍历 使用队列
def queue_tarversal(self, root):
if root is None:
return
q = deque()
q.append(root)
while q:
node = q.pop()
print(node.data)
if node.lchild is not None:
q.append(node.lchild)
else:
q.append(node.rchild) if __name__ == "__main__":
elems = range(10)
tree = Create_Tree()
for i in elems:
# 非递归建树,主要就是根据 队列FIFO的特点以及广度遍历的思路
tree.add(i) # 递归建树
# tree.traversal_create(tree.root) # 递归遍历
tree.digui(tree.root)
# 栈遍历
# tree.stack_traversal(tree.root)
二叉树的建立以及遍历的多种实现(python版)的更多相关文章
- C语言二叉树的建立与遍历
二叉树的建立和遍历都要用到递归,先暂时保存一下代码,其中主要是理解递归的思想,其它的就都好理解了.这里是三种遍历方式,其实理解一种,其它的几个就都理解了,就是打印出来的顺序不一样而已.建立和遍历的方式 ...
- 一步一步写数据结构(二叉树的建立和遍历,c++)
简述: 二叉树是十分重要的数据结构,主要用来存放数据,并且方便查找等操作,在很多地方有广泛的应用. 二叉树有很多种类,比如线索二叉树,二叉排序树,平衡二叉树等,本文写的是最基础最简单的二叉树. 思路: ...
- 二叉树的建立与遍历(c语言)入门
树其实在本质上就是一对多,链表就是一对一. 二叉树的建立: 这里的代码采用的是最粗暴的创建方法,无实际用处.但初次学习二叉树可以通过这个创建方法更好的理解二叉树. 二叉树的遍历: 遍历在大体上分为递归 ...
- 二叉树的建立与遍历(山东理工OJ)
题目描写叙述 已知一个按先序序列输入的字符序列,如abc,,de,g,,f,,,(当中逗号表示空节点).请建立二叉树并按中序和后序方式遍历二叉树,最后求出叶子节点个数和二叉树深度. 输入 输入一个长度 ...
- C语言实现二叉树的建立、遍历以及表达式的计算
实现代码 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <ctype ...
- python实现二叉树的建立以及遍历(递归前序、中序、后序遍历,队栈前序、中序、后序、层次遍历)
#-*- coding:utf-8 -*- class Node: def __init__(self,data): self.data=data self.lchild=None self.rchi ...
- C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历、中序遍历、后续遍历)
树 利用顺序存储和链式存储的特点,可以实现树的存储结构的表示,具体表示法有很多种. 1)双亲表示法:在每个结点中,附设一个指示器指示其双亲结点在数组中的位置. 2)孩子表示法:把每个结点的孩子排列起来 ...
- 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。
//归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...
- 数据结构实习 - problem K 用前序中序建立二叉树并以层序遍历和后序遍历输出
用前序中序建立二叉树并以层序遍历和后序遍历输出 writer:pprp 实现过程主要是通过递归,进行分解得到结果 代码如下: #include <iostream> #include &l ...
随机推荐
- iOS中 CocoaPods Mac App的安装和使用 韩俊强的博客
CocoaPods Mac App的安装和使用 CocoaPods桌面应用版下载地址:https://cocoapods.org/app打开应用会提示你是否安装命令行工具,选择install就也可以在 ...
- 显示图像的SIFT flow描述子
close all; % 模拟figure 5 im = zeros(401,401,3); im(:,:,:) = 0; im(2:200, 2:200, 2) = 255; im(202:400, ...
- 并发编程之ThreadLocal、Volatile、synchronized、Atomic关键字扫盲
前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别 ...
- iOS开发之六:常用控件--UIImageView的使用
UIImageView是我们做iOS开发用的非常多的一个控件,IOS中的各种图片,包括头像,有的背景图片等基本都要用到这个控件. 1.常用的属性以及方法 <span style="fo ...
- ASP.NET遇到HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容
当碰到这个问题的时候真的是让人很费解啊,就算是重新打开机器也不能够解决,但是下面的小技巧说不一定就可以解决这个问题了. 首先,打开IIS(Internet信息管理服务器),找到"功能&quo ...
- JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制
JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是clas ...
- pig的limit无效(返回所有记录)sample有效
pig中,limit可以取样少部分数据,但有很多问题,比如数据不能少于10条,否则返回全部. 今天又遇到另一个问题: group后的数据,limit无效:也就是group后的数据,不能用limit,估 ...
- 关于oracle表名区分大小写的问题
oracle不是区分大小写的,是建表的时候是没有去掉双引号. CREATE TABLE TableName(id number); //虽然写的时候是有大写和小写,但是在数据库里面是不区分的. ...
- Windows Mobile和Wince(Windows Embedded CE)的字符集问题
背景 开发过Windows Mobile和Wince(Windows Embedded CE)的开发者,特别是Native C++开发者,或多或少都遇到过ANSI字符集和Unicode字符集的转换问题 ...
- Linux特殊权限分析(第二版)
SetUID[权限值=4] 问题:为什么普通用户可以修改自己的密码? ll $(which passwd) 1.SetUID:当一个可执行程序/命令具有SetUID 权限,用户执行这个程序时,将以这个 ...