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. (史上最全)SNP位点与转录因子结合特异性数据库:GVATdb

    众所周知,全基因组关联分析(GWAS)发现的很多变异位点基本为非编码,这些变异位点1)要么调控基因表达(eQTL); 2)要么影响增强子活性; 3)要么影响转录因子(TF)结合特异性; 4)要么啥也不 ...

  2. windows10与linux进行ftp遇到550 Failed to change directory及553 Could not creat file

    第一个原因: 没有权限,可以使用带有l参数的ls命令来看文件或者目录的权限 ls -l 解决:给本地用户添加一个可写权限 chmod +w /home/student ##给对应的本地用户添加一个可写 ...

  3. P4570 [BJWC2011]元素 (线性基)

    题意:n个石头 每个石头有a,b两个属性 要求选出一些石头使得没有一个子集的a属性xor和为0 且b属性和最大 题解:线性基例题了.. 好像需要理解一些性质 1.原序列里任一数都可有由线性基xor得到 ...

  4. Java中赋值常量的注意事项

    写在前面: 从网上学习的赋值规则 摘录自网络,标明出处 byte,short,int,long 比如 int a = 234; 此处的常量234类型默认是int,如果要将大的整数赋值给变量的话 必须 ...

  5. 80x86/Pentium微机原理及接口技术-微处理器-学习笔记

    80x86/  Pentium微机原理及接口技术 1.    计算机基础... 1 1.1常用术语... 1 1.2计算机中数与编码的表示方法... 1 1.2.1进制表示及进制转换... 1 1.2 ...

  6. 【转】Kubernetes scheduler学习笔记

    简介 Kubernetes是一个强大的编排工具,可以用来很方便的管理许多台机器,为了使机器的资源利用率提高,同时也尽可能的把压力分摊到各个机器上,这个职责就是由scheduler来完成的. Kuber ...

  7. Chapter Zero 0.2.2 内存

    目录 内存 内存的多通道设计 DRAM 和 SRAM 只读存储器(ROM) RAM.ROM以及硬盘的区别(转自百度) 内存 CPU的数据都是来自主存储器(main memory),个人计算机的主寄存器 ...

  8. 鸟哥的linux私房菜——第九章学习(vim编辑器)

    第九章vim编辑器 1.0).vi与vim Linux下文本界面的文书编辑器通常会有常常听到的就有: emacs, pico, nano, joe, 与 vim 等等. vi的优势: 所有的 Unix ...

  9. Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

    最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不 ...

  10. 深入理解JavaScript中的箭头

    箭头函数可以使我们的代码更加简洁,如下: var sum = (a,b) => a+b; JavaScript 充满了我们需要编写在其他地方执行的小函数的情况. 例如: arr.forEach( ...