`
luoweifu
  • 浏览: 62573 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

二叉树(3)——三叉链表示的二叉树

 
阅读更多

三叉链表示的二叉树定义

所畏的三叉链表示是指二叉树由指向左孩子结点、右孩子结点、父亲结点【三叉】的引用(指针)数据和数据组成。
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

分享到:
评论

相关推荐

    数据结构 三叉链表表示的二叉树

    本文将深入探讨一种特殊的数据结构表示——三叉链表表示的二叉树。这种表示方式在C++语言中尤为常见,它允许我们高效地创建、插入、删除节点以及进行循环算法遍历二叉树。 首先,我们要理解什么是二叉树。二叉树是...

    数据结构5.9二叉树的链式存储-三叉链表

    下面通过一个具体的例子来说明三叉链表是如何表示二叉树的: 考虑一棵简单的二叉树,其中包含了7个节点,分别为A、B、C、D、E、F、G。按照字母顺序排列,它们的父子关系如下: - A是根节点; - B和C是A的左右子节点...

    基于二叉树模型的期权定价.pdf

    五、模型改进——三叉树 在二叉树模型的基础上,可以进一步改进为三叉树模型。三叉树模型可以更加准确地模拟期权价格,且计算速度更快。 六、结论 基于二叉树模型的期权定价是一个复杂的问题,需要结合多种数学...

    数据结构java实验四.pdf

    《数据结构(JAVA)》实验报告——树和二叉树的基本操作 实验主要围绕二叉树和树的定义、性质、存储结构以及相关操作展开,旨在让学生深入理解非线性数据结构的实现方法。实验内容分为三个部分: 1. 二叉树的基本...

    基于二叉树模型的期权定价.docx

    ##### 3.3 模型改进——三叉树 虽然二叉树方法已经足够强大,但对于某些特殊情况,比如波动率较高的情况,其准确性可能会受到影响。为了提高模型的精度,可以采用三叉树模型,即在每个时间点允许三种可能的价格变动...

    c语言实现三叉哈夫曼树

    传统的哈夫曼编码基于二叉哈夫曼树,但作者提出了一种新的思路——利用三叉哈夫曼树来进一步优化编码效率。 #### 二叉哈夫曼树概述 在数据结构中,哈夫曼树是一种特殊的树形结构,它的主要目的是最小化数据的带权...

    数据结构第6章习题分享.pdf

    1. 二叉树的存储结构:二叉树有三种常见的存储方式——顺序存储、二叉链表存储和三叉链表存储。顺序存储通常用于完全二叉树,通过数组实现,每个节点的位置对应数组的索引;二叉链表存储每个节点包含左右子节点的...

    关于数据结构中的树的课件

    树的度是所有结点出度中的最大值,例如度为3的树被称为三叉树。根节点的入度为0,其他非叶节点的入度通常为1,叶节点的出度为0。 树的运算主要包括插入、删除、查找等操作。二叉树是特殊类型的树,每个节点最多有两...

    3%%-第3章 复杂数据结构.ppt

    链式存储包括二叉链表和三叉链表,每个节点包含指向其子节点和(对于线索二叉树)前驱和后继节点的指针,便于遍历操作。 操作二叉树涉及的基本操作包括创建二叉树、初始化、添加节点、获取子树、检查树的状态、在树...

    一种新型有序数据结构:容量平衡三叉查找树.pdf

    为了解决这一问题,本文提出了一种新型的有序数据结构——容量平衡三叉查找树(Capacity Balanced Trigeminal Search Tree,简称CBTT)。CBTT在每个节点中存储两个键值,并维护三棵子树。这种结构的设计使得在进行...

    树型数据结构在铁路车站信号计算机联锁系统中的应用.pdf

    通过二叉树的特性和三叉链表的存储结构,作者建立了一个适合描述铁路车站信号系统的数学模型,并在此基础上实现了进路的搜索与信号联锁的处理。这种方法不仅提高了车站信号系统的处理效率,还提升了整个铁路运输的...

    2009最新考研计算机专业大纲——数据结构

    二叉树的存储结构(如二叉链表、三叉链表)和线索二叉树也是考察的重点,考生需要能进行二叉树的构造、复制、查找和删除等操作。 总的来说,2009年考研计算机专业大纲对数据结构的要求是全面而深入的,不仅要求理论...

    c#与数据结构.docx

    本文详细介绍了二叉树的两种存储结构——顺序存储结构和链式存储结构,以及三种常见的遍历方式——先序遍历、中序遍历和后序遍历。在实际应用中,根据具体的需求选择合适的存储结构和遍历方式对于提高程序性能具有...

    数据结构导论(2142) PPT (中)

    二叉树是树的一个特殊类型,每个结点最多有两个子结点——左子树和右子树。二叉树有三种基本形态:空二叉树、只有一个根结点的二叉树和包含根结点及其左右子树的二叉树。二叉树的性质,如第i层最多有2i-1个结点,...

    2013年计算机408统考真题解析1

    3. **平衡二叉树**:问题3提到了构建平衡二叉树。平衡二叉树是一种特殊的二叉树,其中任意节点的两个子树的高度差不超过1。给定7个关键字构建平衡二叉树,可以构造出AVL树或者红黑树等类型的平衡二叉树,确保树的...

    图形算法.pdf

    基于凸剖分的多边形窗口线裁剪算法通过引入凸剖分技术和高效的二叉树(或三叉树)数据结构管理机制,实现了对传统线裁剪算法的有效改进。该方法不仅降低了裁剪计算的复杂度,而且提高了算法的整体执行效率,尤其是在...

    【职业技能大赛计算机程序设计员赛项】理论试题及参考答案.pdf

    9. **三叉树高度**:一棵有40个节点的三叉树的最小高度是log3(40)+1,约为4.6,向上取整为5,选项C正确。 10. **顺序栈**:如果元素出栈顺序为s2, s3, s4, s6, s5, s1,说明在s6出栈前s5不能出栈,因此顺序栈至少...

    大学专业试卷数据结构试卷下(A).doc

    15. 三叉树的最小深度:三叉树的最小深度是使得所有结点都在同一层的深度。对于50个结点,最小深度为log3(50)+1,取整后是4。 填空题: 1. 逻辑结构可以是线性结构(如数组、链表)、集合、树形结构、图。 2. 双向...

Global site tag (gtag.js) - Google Analytics