java数据结构之三叉链表示的二叉树
三叉链表示的二叉树定义
所畏的三叉链表示是指二叉树由指向左孩子结点、右孩子结点、父亲结点【三叉】的引用(指针)数据和数据组成。
package datastructure.tree.btree;
/**
* 三叉链表示的二叉树定义
* @author Administrator
*
*/
public class BinTreeNode{
private Object data; // 数据域
private BinTreeNode parent; // 父节点
private BinTreeNode lChild; // 左孩子
private BinTreeNode rChild; // 右孩子
private int height; // 以该节点为根的子树的高度
private int size; // 该节点子孙数(包括结点本身)
public BinTreeNode() {
this(null);
}
public BinTreeNode(Object e) {
data = e;
height = 0;
size = 1;
parent = lChild = rChild = null;
}
//************ Node接口方法 *************/
/**
* 获得结点的数据
*/
public Object getData() {
return data;
}
public void setData(Object obj) {
data = obj;
}
//-------------辅助方法,判断当前结点位置的情况------------
/**
* 判断是否有父亲
* @return
*/
public boolean hasParent() {
return parent != null;
}
/**
* 判断是否有左孩子
* @return 如果有左孩子结点返回true,否则返回false
*/
public boolean hasLChild() {
return null != lChild;
}
/**
* 判断是否有右孩子
* @return
*/
public boolean hasRChild() {
return null != rChild;
}
/**
* 判断是否为叶子结点
* @return
*/
public boolean isLeaf() {
return (!hasLChild() && !hasRChild());
}
/**
* 判断是否为某节点的左孩子
* @return
*/
public boolean isLChild() {
return (hasParent() && this == parent.lChild);
}
/**
* 判断是否为某结点的右孩子
* @return
*/
public boolean isRChild() {
return (hasParent()) && this == parent.rChild;
}
//-------------- 与height相关的方法-----------------
/**
* 取结点的高度,即以该节点为根的树的高度
* @return
*/
public int getHeight() {
return height;
}
/**
* 更新当前结点及其祖先的高度
*/
public void updateHeight() {
int newH = 0;// 新高度初始化为0,高度等于左右子树加1中的较大值
if (hasLChild())
newH = Math.max(newH, (lChild.getHeight() + 1));// //////////////???
if (hasRChild())
newH = Math.max(newH, (rChild.getHeight() + 1));// 先0和左孩子的高度加1进行比较,后左孩子高度加1和右孩子高度加1进行比较
if (newH == height)
return; // 高度没有发生变化则直接返回
height = newH; // 否则,更新高度
if (hasParent()) // 递归更新祖先的高度
parent.updateHeight();
}
/********* 与size相关的方法 **********/
/**
* 取以该节点为根的树的结点数
* @return
*/
public int getSize() {
return size;
}
/**
* 更新当前结点及祖先的子孙数
*/
public void updateSize() {
size = 1; // 初始化为1,结点本身
if (hasLChild())
size = size + lChild.getSize(); // 加上左子树的规模
if (hasRChild())
size = size + rChild.getSize(); // 加上右子树的规模
if (hasParent())
parent.updateSize();
}
/********** 与parent相关的方法 **********/
/**
* 取父节点
* @return
*/
public BinTreeNode getParent() {
return parent;
}
/**
* 断开与父亲的关系
*/
public void sever() {
if (!hasParent())
return;
if (isLChild())
parent.lChild = null;
else
parent.rChild = null;
parent.updateHeight(); // 更新父节点及其祖先的高度
parent.updateSize(); // 更新父节点及其祖先的规模
parent = null;
}
//********** 与lChild相关的方法 ********/
/**
* 取左孩子
* @return
*/
public BinTreeNode getLChild() {
return lChild;
}
/**
* 设置当前结点的左孩子,返回原左孩子
* @param lc
* @return
*/
public BinTreeNode setLChild(BinTreeNode lc) {
BinTreeNode oldLC = this.lChild;
if (hasLChild()) {
lChild.sever();
} // 断开当前左孩子与结点的关系
if (null != lc) {
lc.sever(); // 判断lc与其父节点的关系
this.lChild = lc; // 确定父子关系
lc.parent = this;
this.updateHeight(); // 更新当前结点及其祖先的高度
this.updateSize(); // 更新当前结点及其祖先的规模
}
return oldLC; // 返回原左孩子
}
//********** 与rChild相关的方法 *********/
/**
* 取右孩子
* @return
*/
public BinTreeNode getRChild() {
return rChild;
}
/**
* 设置当前结点为右孩子,返回原右孩子
* @param rc
* @return
*/
public BinTreeNode setRChild(BinTreeNode rc) {
BinTreeNode oldRC = this.rChild;
if (hasRChild()) {
rChild.sever();
} // 断开当前右孩子与结点的关系
if (null != rc) {
rc.sever(); // 断开rc与其父节点的关系
this.rChild = rc; // 确定父子关系
rc.parent = this;
this.updateHeight(); // 更新当前结点及其祖先的高度
this.updateSize(); // 更新当前结点及其祖先的规模
}
return oldRC; // 返回原右孩子
}
/**
* 重写toString方法
*/
public String toString() {
return "" + data;
}
}
三叉链表示的二叉树的遍历
package datastructure.tree.btree;
import java.util.*;
import datastructure.common.Strategy;
import datastructure.queue.Queue;
import datastructure.queue.ArrayQueue;
/**
* 三叉链表示的二叉树的遍历
* @author luoweifu
*
*/
public class BinaryTreeOrder {
private int leafSize = 0;
private BinTreeNode root = null;
Strategy strategy = new StrategyEqual();
/**
* 构造函数,传入树的根结点
* @param node
* 树的根结点
*/
public BinaryTreeOrder(BinTreeNode node) {
this.root = node;
Strategy strategy = new StrategyEqual();
}
public BinTreeNode getRoot() {
return root;
}
/**
* 前序遍历
*
* @return 返回一个Iterator容器
*/
public Iterator preOrder() {
List<BinTreeNode> list = new LinkedList();
preOrderRecursion(this.root, list);
return list.iterator();
}
/**
* 递归定义前序遍历
* @param rt
* 树根结点
* @param list
* LinkedList容器
*/
private void preOrderRecursion(BinTreeNode rt, List list) {
if (null == rt)
return; // 递归基,空树直接返回
list.add(rt); // 访问根节点
preOrderRecursion(rt.getLChild(), list);// 遍历左子树
preOrderRecursion(rt.getRChild(), list);// 遍历右子树
}
/**
* 中序遍历
*
* @return
*/
public Iterator inOrder() {
List<BinTreeNode> list = new LinkedList();
inOrderRecursion(this.root, list);
return list.iterator();
}
/**
* 递归定义中序遍历
* @param rt
* 树根结点
* @param list
* LinkedList容器
*/
private void inOrderRecursion(BinTreeNode rt, List list) {
if (null == rt)
return; // 递归基,空树直接返回
inOrderRecursion(rt.getLChild(), list);// 遍历左子树
list.add(rt); // 访问根节点
inOrderRecursion(rt.getRChild(), list);// 遍历右子树
}
/**
* 后序遍历
* @return
*/
public Iterator postOrder() {
List<BinTreeNode> list = new LinkedList();
postOrderRecursion(this.root, list);
return list.iterator();
}
/**
* 递归定义后序遍历
* @param rt
* 树根结点
* @param list
* LinkedList容器
*/
private void postOrderRecursion(BinTreeNode rt, List list) {
if (null == rt)
return; // 递归基,空树直接返回
postOrderRecursion(rt.getLChild(), list);// 遍历左子树
postOrderRecursion(rt.getRChild(), list);// 遍历右子树
list.add(rt);// 访问根节点
}
/**
* 按层遍历
* @return
*/
public Iterator levelOrder() {
List<BinTreeNode> list = new LinkedList();
levelOrderTraverse(this.root, list);
return list.iterator();
}
/**
* 使用队列完成二叉树的按层遍历
* @param rt
* @param list
*/
private void levelOrderTraverse(BinTreeNode rt, List list) {
if (null == rt)
return;
Queue q = new ArrayQueue();
q.push(rt);// 根节点入队列
while (!q.isEmpty()) {
BinTreeNode p = (BinTreeNode) q.deQueue(); // 取出队首节点p并访问
list.add(p);
if (p.hasLChild())
q.push(p.getLChild()); // 将p的非空左右孩子依次入队列
if (p.hasRChild())
q.push(p.getRChild());
}
}
/**
* 在树中查找元素e,并返回其所在的结点
* @param e 要查找的数据元素
* @return 返回找到的结点
*/
public BinTreeNode find(Object e) {
return searchE(root, e);
}
/**
* 递归查找元素e
* @param rt 树的根
* @param e 要查找的数据元素
* @return 返回找到的结点
*/
private BinTreeNode searchE(BinTreeNode rt, Object e) {
if (null == rt)
return null;
if (strategy.equal(rt.getData(), e))
return rt;
BinTreeNode v = searchE(rt.getLChild(), e);
if (null == v)
v = searchE(rt.getRChild(), e);
return v;
}
/**
* 打印二叉树
* @return
*/
public String printBinTree() {
StringBuilder sb = new StringBuilder();
printBinTree(root, 0, sb);
return sb.toString();
}
/**
* 打印二叉树
* @param btree 根结点
* @param n 结点层数
* @param sb 用于保存记录的字符串
*/
private void printBinTree(BinTreeNode btree, int n, StringBuilder sb) {
if (null == btree)
return;
printBinTree(btree.getRChild(), n + 1, sb);
for (int i = 0; i < n; i++)
sb.append("\t");
if (n >= 0)
sb.append(btree.getData() + "\n");
printBinTree(btree.getLChild(), n + 1, sb);
}
/**
* 求叶结点的个数
* @return 叶结点的个数
*/
public int sizeLeaf() {
searchLeaf(this.root);
return leafSize;
}
/**
* 叶结点的个数
* @param rt
*/
private void searchLeaf(BinTreeNode rt) {
if (null == rt)
return;
if (rt.isLeaf())
leafSize++;
else {
searchLeaf(rt.getLChild());
searchLeaf(rt.getRChild());
}
}
}
测试
package datastructure.tree.btree;
import java.util.Iterator;
public class BTreeTest2 {
// 测试功能
// 结果:所有功能都能实现,正确
public static void main(String args[]) {
//构造二叉树
BinTreeNode roots = new BinTreeNode();
BinTreeNode node = new BinTreeNode();
roots.setData('A');
roots.setLChild(new BinTreeNode('B'));
roots.setRChild(new BinTreeNode('C'));
node = roots.getLChild();
node.setLChild(new BinTreeNode('D'));
node.setRChild(new BinTreeNode('E'));
node = roots.getRChild();
node.setLChild(new BinTreeNode('F'));
BinaryTreeOrder order = new BinaryTreeOrder(roots);
//------遍历--------
Iterator<BinTreeNode> iter1 = order.preOrder();
System.out.println("前序遍历:");
printIterator(iter1);
Iterator<BinTreeNode> iter2 = order.inOrder();
System.out.println("中序遍历:");
printIterator(iter2);
Iterator<BinTreeNode> iter3 = order.postOrder();
System.out.println("后序遍历:");
printIterator(iter3);
Iterator<BinTreeNode> iter4 = order.levelOrder();
System.out.println("层次遍历:");
printIterator(iter4);
String str = order.printBinTree();
System.out.println("打印二叉树:\n" + str);
System.out.println("叶结点的个数:" + order.sizeLeaf());
BinTreeNode nodeone = order.find('E');
System.out.println("根结点的数据元素:" + nodeone.getData());
}
public static void printIterator(Iterator<BinTreeNode> iter) {
while(iter.hasNext()) {
System.out.print("\t" + iter.next().getData());
}
System.out.println();
}
}
结果:
前序遍历:
A BD
E C F
中序遍历:
D BE
A F C
后序遍历:
D EB
F C A
层次遍历:
A BC
D E F
打印二叉树:
C
F
A
E
B
D
叶结点的个数:3
根结点的数据元素:E
转载至:http://blog.csdn.net/luoweifu/article/details/9089551
java数据结构之三叉链表示的二叉树的更多相关文章
- Java数据结构和算法 - 链表
Q: 为什么要引入链表的概念?它是解决什么问题的? A: 数组作为数据存储结构有一定的缺陷,在无序数组中,搜索是低效的:而在有序数组中,插入效率又很低:不管在哪一个数组中删除效率都很低:况且一个数组创 ...
- Java数据结构和算法(十)——二叉树
接下来我们将会介绍另外一种数据结构——树.二叉树是树这种数据结构的一员,后面我们还会介绍红黑树,2-3-4树等数据结构.那么为什么要使用树?它有什么优点? 前面我们介绍数组的数据结构,我们知道对于有序 ...
- 图解Java数据结构之环形链表
本篇文章介绍数据结构中的环形链表. 介绍 环形链表,类似于单链表,也是一种链式存储结构,环形链表由单链表演化过来.单链表的最后一个结点的链域指向NULL,而环形链表的建立,不要专门的头结点,让最后一个 ...
- Java数据结构之单链表
这篇文章主要讲解了通过java实现单链表的操作,一般我们开始学习链表的时候,都是使用C语言,C语言中我们可以通过结构体来定义节点,但是在Java中,我们没有结构体,我们使用的是通过类来定义我们所需要的 ...
- Java数据结构-03单链表(二)
在之前我们封装了一些操作在接口类中,并在抽象类实现了相同的方法.下面我们开始写代码: 无头结点单链表:(注意下面的AbstractList是之前抽取的类,不是java.util包下的类) public ...
- Java数据结构——双端链表
//================================================= // File Name : FirstLastList_demo //------------ ...
- java 数据结构与算法---链表
原理来自百度百科 一.链表的定义 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运 ...
- Java 数据结构之双链表
package Linked; public class Mylinked { private Node first;//链表的第一个节点 private Node last;//链表的最后一个节点 ...
- 图解Java数据结构之单链表
本篇文章介绍数据结构中的单链表. 链表(Linked List)介绍 链表可分为三类: 单链表 双向链表 循环列表 下面具体分析三个链表的应用. 单链表 链表是有序的列表,它在内存中存储方式如下: 虽 ...
随机推荐
- IntelliJ IDEA 2017版 导入项目项目名称为红色
1.导入的项目全部是红色的,原因是版本控制问题,所以修改如下:(File--->settings) 2.找到如图位置的字样,选中当前项目,选择铅笔位置 选择铅笔 弹出对话框(默认选择的是proj ...
- html自适应布局,@media screen,媒体查询
html自适应布局,@media screen,媒体查询 自适应代码示例: <!doctype html> <html> <head> <meta chars ...
- timescale
`timescale 1ns/100ps 表示时延单位为1ns, 时延精度为100ps.`timescale 编译器指令在模块说明外部出现, 并且影响后面所有的时延值.
- 11) 生成可执行jar文件 maven-shade-plugin
搜索 site:maven.apache.org maven-assembly-plugin http://maven.apache.org/plugins/maven-assembly-plugin ...
- matlab练习程序(生成希尔伯特曲线)
能够使用这样一条线遍历图像中所有的像素,不过这里没有这样做,而只是生成了这样一条曲线. 程序中h,w是最终图像的高和宽,n为希尔伯特曲线阶数. 这里如果n等于log2(h)或log2(w),则图像就全 ...
- hdu1257 最少拦截系统(贪心) 2016-05-19 20:28 90人阅读 评论(0) 收藏
最少拦截系统 Problem Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能 ...
- hdu 5001 从任意点出发任意走d步不经过某点概率
http://acm.hdu.edu.cn/showproblem.php?pid=5001 给定n个点m条边的无向图问从任意点出发任意走d步,从不经过某个点的概率 本想先算路过每个点的概率然后用1减 ...
- Windows 8/8.1 及 Windows Phone 8 应用神器 - APP Producer
继 App studio 以及 Project Siena 之后 微软再次打造应用生成器 APP Producer,这个版本的应用生成器功能相对比之前两个版本要简单许多,更适合入门并且真正的支持全平 ...
- paxos ---学习笔记
摘自维基百科:分布式系统中的节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing).基于消息传递通信模型的分布式系统,不可避免的会发生以下错误:进程 ...
- spring的事务传播属性
一.Propagation (事务的传播属性) Propagation : key属性确定代理应该给哪个方法增加事务行为.这样的属性最重要的部份是传播行为.有以下选项可供使用:PROPAGATION_ ...