ADT基础(二)—— Tree,Heap and Graph

1 Tree(二叉树)

  • 先根遍历 (若二叉树为空,则退出,否则进行下面操作)

    • 访问根节点
    • 先根遍历左子树
    • 先根遍历右子树
    • 退出

    访问顺序为:A、B、D、H、I、E、J、C、F、G

  • 中根遍历(若二叉树为空,则退出,否则进行下面操作)

    • 中根遍历左子树
    • 访问根节点
    • 中根遍历右子树
    • 退出

    访问顺序为:H、D、I、B、J、E、A、F、C、G

  • 后根遍历(若二叉树为空,则退出,否则进行下面操作)

    • 后根遍历左子树
    • 后根遍历右子树
    • 访问根节点
    • 退出

    访问顺序为:H、I、D、J、E、B、F、G、C、A

  • 广度优先遍历:

    访问顺序为:A、B、C、D、E、F、G、H、I、J

//链表表示
public class BinaryNode //节点类
{
Object element;
BinaryNode left; //lefft subtree
BinaryNode right; //right subtree
};
public class BinaryTree{ //节点树类
private BinaryNode root; public boolean isEmpty(){return root == null;}
//深度优先遍历,递归,非递归要用栈,而递归本质就是栈
public void PreOrder(BinaryNode node){ //先根遍历
if(node!=null){
System.out.println(node.element);
PreOrder(node.left);
PreOrder(node.right);
}
}
public void InOrder(BinaryNode node){ //中根遍历
if(node!=null){
InOrder(node.left);
System.out.println(node.element);
InOrder(node.right);
}
}
public void PostOrder(BinaryNode node){ //后根遍历
if(node!=null){
PostOrder(node.left);
PostOrder(node.right);
System.out.println(node.element);
}
}
//广度优先遍历,循环,使用队列
public void LevelOrder(BinaryNode node){
Queue q = new Queue();
while(node){
System.out.println(node.element);
if(node.left) q.add(node.left);
if(node.right) q.add(node.right);
try{ node = q.delete();} //弹出值赋给node
catch(OutOfBounds){return;}
}
}
} //清空
public void clear(BinaryNode node){ //清除某个子树的所有节点
if(node!=null){
clear(node.left);
clear(node.right);
node = null; //删除节点
}
}
public void clear(){ ////清空树
clear(root);
}
//求高度
public int height(BinaryNode node){ //获取以某节点为子树的高度
if(node==null){
return 0; //递归结束,空子树高度为0
}else{
//递归获取左子树高度
int l = height(node.left);
//递归获取右子树高度
int r = height(node.right);
//高度应该算更高的一边,(+1是因为要算上自身这一层)
return l>r? (l+1):(r+1);
}
}
public int height(){ //获取二叉树的高度
return height(root);
}
//求节点数
public int size(BinaryNode node){ //获取以某节点为子树的节点数
if(node==null){
return 0;
}else{
int l = size(node.left);
int r = size(node.right);
return l+r+1;
}
}
public int size(){ //获取二叉树的节点数
return size(root);
}
//返回某节点的父亲节点,这种二叉树只能递归地靠从根节点遍历来比较获取
public BinaryNode getParent(BinaryNode node,BinaryNode root){
if(root==null) retun null;
if(root.left==node||root.right==node) return root;
if(getParent(root.left,node)!=null) return getParent(root.left,node);
else return getParent(root.right,node);
}
public BinaryNode getParent(BinaryTreeNode node){
return (root==null||root==node)? null:getParent(root,node);
}
//已知前序和中序,重新构造二叉树
//核心:找到根节点,分开左右子树
//前序第一个就是根节点,以该点把中序分成左右两部分,左未左子树,右为右子树;同样,左右两部分,同上,递归
public void createBT(String pres,String ins,BinaryNode root){
int inpos;
String prestmp,instmp;
if(pres.length==0) root = null;
else{
root = new BinaryNode();
root.element = pres.charAt(0);
inpos = 0;
while(ins.charAt(inpos) != root.element) inpos++; //找到中序的树根 prestmp = pres.substring(1,inpos+1);
instmp = ins.substring(0,inpos); //左子树
createBT(pres,ins,t.left); //递归构造左子树 prestmp = pres.substring(inpos+1,pres.length()-1);
instmp = ins.substring(inpos+1,prs.length()-1); //左子树
createBT(pres,ins,t.right); //递归构造左子树
}
}
//已知后序与中序。算法同,相当于后序反过来找
//已知先序和后序,可以得到不唯一的树。核心:找到树根,分开左右子树
/*
先序遍历中刚遍历到的下一个节点是后序遍历中最后遍历的节点,所以可以将后序遍历拆分成两个子序列,从而进行递归构造。
例如 先序遍历为aebdc,后序遍历为bcdea。
首先可以确定根节点为a,在后序中找先序的下一个节点(也就是e),将原序列拆分成两部分,其左子树包含的元素有bcde,右子树为空。
接着在bcd中寻找先序中e的后一个元素即b的位置,将这个子序列又拆分成了b和cd两部分。如此递归下去就能得到一种可能的二叉树。
*/

2 Tree(二叉搜索树)

//查找
private BinaryNode find( Comparable x, BinaryNode t ){
if( t = = null ) return null;
if( x. compareTo( t.element ) < 0 ) return find( x, t.left );
else if( x.compareTo( t.element ) > 0 ) return find( x, t.right );
else return t; //Match
}
private BinaryNode findMin( BinaryNode t ){
if( t = = null ) return null;
else if( t.left = = null ) return t;
return findMin(t.left);
}
//递归或循环都可
private BinaryNode findMax( BinaryNode t ){
if( t != null )
while( t.right != null )
t = t.right;
return t;
}
//插入
private BinaryNode insert( Comparable x, BinaryNode t )
{
if( t == null )
t = new BinaryNode( x, null, null );
else if( x.compareTo( t.element ) < 0 )
t.left = insert( x, t.left );
else if( x.compareTo( t.element ) > 0 )
t.right = insert( x, t.right );
else ;//duplicate; do nothing
return t;
}
//删除
//三种情况:叶,只有一个非空子树的节点,有两个非空子树的节点
//用左子树的最大或右子树的最小(都是叶节点)来换,然后把左子树最大和右子树最小删除
private BinaryNode remove( Comparable x, BinaryNode t){
if( t == null ) return t;
if( x.compareTo( t.element ) < 0 )
t.left = remove( x, t.left );
else if( x.compareTo( t.element ) > 0 )
t.right = remove( x, t.right );
else if( t.left != null && t.right != null ){ //找到了
t.element = findMin( t.right ).element; //左子树max或右子树min
t.right = remove(t.element, t.right );
}else //左右子树一边为空或全为空,可以替换成左子树或右子树
t = ( t.left != null ) ? t.left : t.right;
}

ADT基础(二)—— Tree,Heap and Graph的更多相关文章

  1. 【数据结构05】红-黑树基础----二叉搜索树(Binary Search Tree)

    目录 1.二分法引言 2.二叉搜索树定义 3.二叉搜索树的CRUD 4.二叉搜索树的两种极端情况 5.二叉搜索树总结 前言 在[算法04]树与二叉树中,已经介绍过了关于树的一些基本概念以及二叉树的前中 ...

  2. Java面试题总结之Java基础(二)

    Java面试题总结之Java基础(二) 1.写clone()方法时,通常都有一行代码,是什么? 答:super.clone(),他负责产生正确大小的空间,并逐位复制. 2.GC 是什么? 为什么要有G ...

  3. Python全栈开发【基础二】

    Python全栈开发[基础二] 本节内容: Python 运算符(算术运算.比较运算.赋值运算.逻辑运算.成员运算) 基本数据类型(数字.布尔值.字符串.列表.元组.字典) 其他(编码,range,f ...

  4. Bootstrap <基础二十九>面板(Panels)

    Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素添加 class .panel 和 class .pa ...

  5. Bootstrap <基础二十八>列表组

    列表组.列表组件用于以列表形式呈现复杂的和自定义的内容.创建一个基本的列表组的步骤如下: 向元素 <ul> 添加 class .list-group. 向 <li> 添加 cl ...

  6. Bootstrap<基础二十七> 多媒体对象(Media Object)

    Bootstrap 中的多媒体对象(Media Object).这些抽象的对象样式用于创建各种类型的组件(比如:博客评论),我们可以在组件中使用图文混排,图像可以左对齐或者右对齐.媒体对象可以用更少的 ...

  7. Bootstrap <基础二十六>进度条

    Bootstrap 进度条.在本教程中,你将看到如何使用 Bootstrap 创建加载.重定向或动作状态的进度条. Bootstrap 进度条使用 CSS3 过渡和动画来获得该效果.Internet ...

  8. Bootstrap <基础二十五>警告(Alerts)

    警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警告(Alerts)向用户提供了一种定义消息样式的方式.它们为典型的用户操作提供了上下文信息反馈. 您可以为警告框添加一个 ...

  9. Bootstrap<基础二十四> 缩略图

    Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ...

随机推荐

  1. Flink-v1.12官方网站翻译-P014-Flink Architecture

    Flink架构 Flink是一个分布式系统,为了执行流式应用,需要对计算资源进行有效的分配和管理.它集成了所有常见的集群资源管理器,如Hadoop YARN.Apache Mesos和Kubernet ...

  2. HTML复习day01

    1. 常见的浏览器内核 1 IE Trident 2 firefox Gecko 3 Safari webkit (安卓 苹果 大部分国产) 4 chrome Chromlum/blink 2. we ...

  3. Linux 防火墙相关操作

    目录 1.查看防火墙状态 2.部署防火墙 3.常用操作 4.其他操作 1.查看防火墙状态 systemctl status firewalld 绿字部分 Active:active(running) ...

  4. C - C(换钱问题)

    换钱问题: 给出n种钱,m个站点,现在有第 s种钱,身上有v 这么多: 下面 m行 站点有a,b两种钱,rab a->b的汇率,cab a-->b的手续费, 相反rba cba :  问在 ...

  5. 2020牛客暑期多校训练营(第八场)Game SET

    传送门:Game SET 题意 一套牌有四种属性,每种属性都有三种特征,shapes (one, two, or three), shape (diamond, squiggle, or oval), ...

  6. codeforces 86D D. Powerful array

    An array of positive integers a1, a2, ..., an is given. Let us consider its arbitrary subarray al, a ...

  7. js--执行上下文和作用域相关问题

    前言 如果你是或者你想成为一名合格的前端开发工作者,你必须知道JavaScript代码在执行过程,知道执行上下文.作用域.变量提升等相关概念,并且熟练应用到自己的代码中.本文参考了你不知道的JavaS ...

  8. 牛客多校第八场E Explorer(左开右闭线段树+可撤回并查集)题解

    题意: 传送门 有\(n\)个点构成一个无向图,每条边有\(L_i,R_i\)表示这条边只能允许编号为\(L_i\dots R_i\)的人通过,现在问你最多有几个人能从\(1\)走到\(n\). 思路 ...

  9. 牛客多校第三场J LRU management(双向链表)题解

    题意: 给一个长度为\(m\)的队列,现给定以下操作: \(opt=0\),插入一个串,如果不在队里直接插入栈尾,如果超出\(m\)删队首:在队里就拿出来重新放到队尾,返回\(v\)值. \(opt= ...

  10. UMD 模块 vs CJS 模块

    UMD 模块 vs CJS 模块 使用方式 UMD, window 全局注册后,直接使用 <!DOCTYPE html> <html lang="zh-Hans" ...