基本数据结构的说明(三)
来源:互联网 发布:如何打开8080端口 编辑:程序博客网 时间:2024/06/06 00:59
3.树的说明
树:T={K,R}。K是包含n个结点的有穷集合(n>0),关系R满足以下条件:
(1)有且仅有一个结点k0∈K,它对于关系R来说没有前驱结点,结点k0称作树的根。
(2)除结点k0外,K中的每个结点对于关系R来说都有且仅有一个前驱结点。
(3)K中每个结点对于关系R来说可以有多个后继结点。
我这里主要讨论的是二叉树,因为这个是用的最广泛的,二叉树也称为二次树或二分树,它是有限的结点集合,这个集合或者是空,或者由一个根结点和两棵互不相交的称为左子树和右子树的二叉树组成。
二叉树的节点定义形式如下:
class TreeNode<E>{
Comparable<E> key;//节点的值
TreeNode<E> llink;//左子树的指针
TreeNode<E> rlink;//右子树的指针
}
假如我们有这样一棵树
2
/ /
4 5
/ / / /
7 3 10 8
/ / /
1 9 6
1)树的遍历:就是访问所有的节点一遍。一般来说,有四种遍历的方式,前序遍历:先访问节点本身,在访问左子树,之后再访问右子树,例如上面的树,前序遍历的次序是2 4 7 1 9 3 6 5 10 8;中序遍历,就是先访问左子树,再访问节点本身,最后访问右子树,上面的树中序遍历的次序是1 7 9 4 6 3 2 10 5 8;后序遍历,就是先访问左子树,再访问右子树,最后访问节点,上面的树后序遍历的次序是1 9 7 6 3 4 10 8 5 2;层次遍历就是按层次访问树的节点,上面的树层次遍历的属次序是2 4 5 7 3 10 8 1 9 6
具体代码实现,可以采用递归的方式实现,也可以采用非递归的方式实现。
递归方式实现(注意,我写的大体过程,具体使用时大家根据实际情况修改一下):
前序遍历:
public static void preOrder(TreeNode root){
if(root==null) return;
visit(root);
preOrder(root.llink);
preorder(root.rlink);
}
中序遍历:
public static void inOrder(TreeNode root){
if(root==null) return;
inOrder(root.link);
visit(root);
inOrder(root.rlink);
}
后序遍历:
public static void postOrder(TreeNode root){
if(root==null) return;
postOrder(root.llink);
postOrder(root.rlink);
visit(root);
}
层次遍历:
public static void layerOrder(TreeNode root){
if(root==null) return;
ListQueue<TreeNode> q=new ListQueue<TreeNode>();
q.insert(root);
while(!q.empty()){
TreeNode temp=q.remove();
visit(temp);
if(temp.llink!=null) q.insert(temp.llink);
if(temp.rlink!=null) q.insert(temp.rlink);
}
}
我前面已经说过,使用递归只不过由系统在为我们维护一个调用栈,我们也可以具体明确的使用堆栈来非递归的实现树的遍历。
非递归实现树的遍历,我们先构建好一棵树,初始化一个栈,之后我们进入一个循环,我们不断弹出堆栈里的元素,直到堆栈为空,如果弹出的树节点表示一棵空树,我们就访问此节点,否则,我们根据下面的规则执行一系列的push操作。
对于前序:压入右子树,然后是左子树,再后是节点
对于中序:压入右子树,然后是节点,再后是左子树
对于后序:压入节点,然后是右子树,再后是左子树
当我们把一个节点的左右节点及本节点都入栈后,我们的节点本身就可以看成一棵空树了。为了标识这一特性,我们修改树节点为:
class TreeNode<E>{
Comparable<E> key;//节点的值
TreeNode<E> llink;//左子树的指针
TreeNode<E> rlink;//右子树的指针
boolean flag;//是否是空树
}
前序遍历的代码:
public static void preOrder(TreeNode<E> node){
if(node==null)return;
ListStack<TreeNode<E>> stack=new ListStack<TreeNode<E>>();
stack.push(node);
while(!stack.empty()){
TreeNode<E> t=stack.pop();
if(t.flag){
System.out.print(t.item+",");
}else{
if(t.rlink!=null)
stack.push(t.rlink);
if(t.llink!=null)
stack.push(t.llink);
stack.push(t);
t.flag=true;
}
}
}
中序遍历的代码:
public static void preOrder(TreeNode<E> node){
if(node==null)return;
ListStack<TreeNode<E>> stack=new ListStack<TreeNode<E>>();
stack.push(node);
while(!stack.empty()){
TreeNode<E> t=stack.pop();
if(t.flag){
System.out.print(t.item+",");
}else{
if(t.rlink!=null)
stack.push(t.rlink);
stack.push(t);
if(t.llink!=null)
stack.push(t.llink);
t.flag=true;
}
}
}
后序遍历的代码:
public static void preOrder(TreeNode<E> node){
if(node==null)return;
ListStack<TreeNode<E>> stack=new ListStack<TreeNode<E>>();
stack.push(node);
while(!stack.empty()){
TreeNode<E> t=stack.pop();
if(t.flag){
System.out.print(t.item+",");
}else{
stack.push(t);
if(t.rlink!=null)
stack.push(t.rlink);
if(t.llink!=null)
stack.push(t.llink);
t.flag=true;
}
}
}
- 基本数据结构的说明(三)
- 基本数据结构的说明(一)
- 基本数据结构的说明(二)
- 基本数据结构的说明(四)
- 数据结构(三)栈1:栈的基本运算
- 三、Python的基本数据结构--列表
- OpenCV笔记(三)基本数据结构
- nginx 学习笔记(三)基本数据结构
- 【python入门笔记】(三)基本数据结构
- 三.数据结构与基本绘图(4.基本图形的绘制)
- 基本数据结构和函数说明
- 三.数据结构与基本绘图(2.常用图形数据结构)
- 监听以太网(三) Packet32数据结构说明(转)
- php实现递归的三种基本方式及其说明
- 第十五周--数据结构(项目三)--B-树的基本操作
- 【数据结构作业】实验三 单链表的基本操作(必做,设计性实验,4学时)
- 数据结构笔记(三)静态链表的实现和基本操作
- 数据结构+算法系列三:A 一些基本的概念
- C_简单的子函数调用
- 基于电子商务平安的公钥实现
- C_利用函数的引用调用实现两数的交换
- 试析在电子商务中如何正确的使用数据挖掘技术
- C_向函数传递数组实现矩阵转置
- 基本数据结构的说明(三)
- 分析电子商务服务器和电子商务购物过程
- 透视开发基于SQL SERVER 的C/S数据库应用系统
- 略论软件项目管理常见新问题及解决方案
- C#中调用EXCEL和将datagridview数据导出到execle
- HTTP协议中session与cookie的联系与区别——UCWEB笔试题
- tokyo cabinet源码分析-mdb设计和实现
- 探讨基于SOAP的Web服务攻击及防范
- 有关对数据库系统平安性的思索