本文根据《大话数据结构》一书,对Java版的二叉树、线索二叉树进行了一定程度的实现

另:

二叉排序树(二叉搜索树)

平衡二叉树(AVL树)

二叉树的性质

性质1:二叉树第i层上的结点数目最多为 2{i-1} (i≥1)。

性质2:深度为k的二叉树至多有2{k}-1个结点(k≥1)。

性质3:在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1

    证明提示:分支线总数=n0+n1+n2-1=n1+2×n2

性质4:具有n个节点的完全二叉树的深度为[log2n]+1。([ ]代表向下取整)

    证明提示:假设深度为k,则有2{k-1} -1<n≤2{k} -1。

性质5:如果有一颗有n个节点的完全二叉树的节点按层次序编号,对任一层的节点i(1<=i<=n)有

1.如果i=1,则节点是二叉树的根,无双亲,如果i>1,则其双亲节点为[i/2]

2.如果2i>n那么节点i没有左孩子(叶子结点),否则其左孩子为2i

3.如果2i+1>n那么节点没有右孩子,否则右孩子为2i+1

二叉链表的定义代码

  1. class BiTNode<E>{
  2. E data;
  3. BiTNode<E> lchild,rchild;
  4. public BiTNode(E data) {
  5. this.data=data;
  6. this.lchild=null;
  7. this.rchild=null;
  8. }
  9. }
  10.  
  11. public class BiTree<E> {
  12.  
  13. private BiTNode<E> root;
  14.  
  15. public BiTree() {
  16. root=null;
  17. }
  18.  
  19. ...
  20. }

  

  

二叉树的遍历

  1. /*
  2. * 前序遍历
  3. */
  4. public void preOrder() {
  5. preOrderTraverse(root);
  6. System.out.println();
  7. }
  8. private void preOrderTraverse(BiTNode<E> node) {
  9. if(node==null)
  10. return;
  11. System.out.print(node.data);
  12. preOrderTraverse(node.lchild);
  13. preOrderTraverse(node.rchild);
  14. }
  15.  
  16. /*
  17. * 中序遍历
  18. */
  19. public void inOrder() {
  20. inOrderTraverse(root);
  21. System.out.println();
  22. }
  23. private void inOrderTraverse(BiTNode<E> node) {
  24. if(node==null)
  25. return;
  26. inOrderTraverse(node.lchild);
  27. System.out.print(node.data);
  28. inOrderTraverse(node.rchild);
  29. }
  30.  
  31. /*
  32. * 后序遍历
  33. */
  34. public void postOrder() {
  35. postOrderTraverse(root);
  36. System.out.println();
  37. }
  38. private void postOrderTraverse(BiTNode<E> node) {
  39. if(node==null)
  40. return;
  41. postOrderTraverse(node.lchild);
  42. postOrderTraverse(node.rchild);
  43. System.out.print(node.data);
  44. }

  

二叉树的建立

  《大话》一书中,6.9节关于二叉树的建立如下:

  通过输入AB#D##C##,可以生成上述二叉树,其C语言的实现算法如下:

  暂时能力有限,还不懂如何改为Java代码。

  几点疑问:1.exit(OVERFLOW)不是很清楚什么意思;

       2.代码中为char类型,如何用于泛型?

         3.scanf()在Java中怎么实现?用scanner吗?程序如何知道输入完“AB#D##C##”就结束二叉树的构造呢?总的实现代码(包括main部分)是怎么样的?

以下为测试代码遍历的总体测试代码:

  1. package BiTree;
  2.  
  3. class BiTNode<E>{
  4. E data;
  5. BiTNode<E> lchild,rchild;
  6. public BiTNode(E data) {
  7. this.data=data;
  8. this.lchild=null;
  9. this.rchild=null;
  10. }
  11. }
  12.  
  13. public class BiTree<E> {
  14.  
  15. private BiTNode<E> root;
  16.  
  17. public BiTree() {
  18. //root=new BiTNode(null, null, null);
  19. root=null;
  20. }
  21.  
  22. /*
  23. * 前序遍历
  24. */
  25. public void preOrder() {
  26. preOrderTraverse(root);
  27. System.out.println();
  28. }
  29. private void preOrderTraverse(BiTNode<E> node) {
  30. if(node==null)
  31. return;
  32. System.out.print(node.data);
  33. preOrderTraverse(node.lchild);
  34. preOrderTraverse(node.rchild);
  35. }
  36.  
  37. /*
  38. * 中序遍历
  39. */
  40. public void inOrder() {
  41. inOrderTraverse(root);
  42. System.out.println();
  43. }
  44. private void inOrderTraverse(BiTNode<E> node) {
  45. if(node==null)
  46. return;
  47. inOrderTraverse(node.lchild);
  48. System.out.print(node.data);
  49. inOrderTraverse(node.rchild);
  50. }
  51.  
  52. /*
  53. * 后序遍历
  54. */
  55. public void postOrder() {
  56. postOrderTraverse(root);
  57. System.out.println();
  58. }
  59. private void postOrderTraverse(BiTNode<E> node) {
  60. if(node==null)
  61. return;
  62. postOrderTraverse(node.lchild);
  63. postOrderTraverse(node.rchild);
  64. System.out.print(node.data);
  65. }
  66.  
  67. /*
  68. * 6.9 二叉树的建立暂时不会,略
  69. */
  70.  
  71. public static void main(String[] args) {
  72. BiTree<String> aBiTree = new BiTree<String>();
  73. aBiTree.root=new BiTNode("A");
  74. aBiTree.root.lchild=new BiTNode("B");
  75. aBiTree.root.rchild=new BiTNode("C");
  76. aBiTree.root.lchild.rchild=new BiTNode("D");
  77. System.out.println("————前序————");
  78. aBiTree.preOrder();
  79. System.out.println("————中序————");
  80. aBiTree.inOrder();
  81. System.out.println("————后序————");
  82. aBiTree.postOrder();
  83. }
  84. }

  

  1. ————前序————
  2. ABDC
  3. ————中序————
  4. BDAC
  5. ————后序————
  6. DBCA

BiTree

线索二叉树

  对一个有n个节点的二叉链表(如上图),整表存在2n个指针域,但分支线只有n-1条,说明空指针域的个数为2n-(n-1) = n+1个,浪费了很多的内存资源。

  我们可以通过利用这些空指针域,存放节点在某种遍历方式下的前驱和后继节点的指针。我们把这种指向前驱和后继的指针成为线索,加上线索的二叉链表成为线索链表,对应的二叉树就成为“线索二叉树(Threaded Binary Tree)”,如下图所示。

  线索二叉树的Java代码如下:

  1. package BiThrTree;
  2.  
  3. /**
  4. * 线索二叉树
  5. * 包含二叉树的中序线索化及其遍历
  6. * @author Yongh
  7. *
  8. */
  9. class BiThrNode<E>{
  10. E data;
  11. BiThrNode<E> lChild,rChild;
  12. boolean lTag,rTag;
  13. public BiThrNode(E data) {
  14. this.data=data;
  15. //tag都先定义成左右孩子指针。
  16. lTag=false; //其实把Tag定义为IsThread更好
  17. rTag=false;
  18. lChild=null;
  19. rChild=null;
  20. }
  21. }
  22.  
  23. public class BiThrTree<T> {
  24. BiThrNode<T> root;
  25. boolean link=false,thread=true;
  26.  
  27. public BiThrTree() {
  28. root=null;
  29. }
  30.  
  31. /*
  32. * 中序线索化二叉树
  33. * 即:在遍历的时候找到空指针进行修改。
  34. */
  35. BiThrNode<T> pre; //线索化时记录的前一个结点
  36.  
  37. public void inThreading() {
  38. inThreading(root);
  39. }
  40. private void inThreading(BiThrNode<T> p) {
  41. if(p != null) {
  42. inThreading(p.lChild);
  43. if(p.lChild==null) {
  44. p.lTag=thread;
  45. p.lChild=pre;
  46. }
  47. if(pre!=null && pre.rChild==null) { //pre!=null一定要加上
  48. pre.rTag=thread;
  49. pre.rChild=p;
  50. }
  51. pre=p; //别忘了在这个位置加上pre=p
  52. inThreading(p.rChild);
  53. }
  54. }
  55.  
  56. /*
  57. * 中序遍历二叉线索链表表示的二叉树(按后继方式)
  58. * 书中添加了一个头结点,本程序中不含头结点
  59. * 思路:先找到最左子结点
  60. */
  61. public void inOrderTraverse() {
  62. BiThrNode<T> p = root;
  63. while(p!=null) {
  64. while(p.lTag==link)
  65. p=p.lChild; //找到最左子结点
  66. System.out.print(p.data);
  67. while(p.rTag==thread) { //不是if
  68. p=p.rChild;
  69. System.out.print(p.data);
  70. }
  71. p=p.rChild;
  72. }
  73. System.out.println();
  74. }
  75.  
  76. /*
  77. * 中序遍历方法二(按后继方式)
  78. * 参考别人的博客
  79. */
  80. public void inOrderTraverse2() {
  81. BiThrNode<T> node = root;
  82. while(node != null && node.lTag==link) {
  83. node = node.lChild;
  84. }
  85. while(node != null) {
  86. System.out.print(node.data + ", ");
  87. if(node.rTag==thread) {//如果右指针是线索
  88. node = node.rChild;
  89.  
  90. } else { //如果右指针不是线索,找到右子树开始的节点
  91. node = node.rChild;
  92. while(node != null && node.lTag==link) {
  93. node = node.lChild;
  94. }
  95. }
  96. }
  97. System.out.println();
  98. }
  99.  
  100. public static void main(String[] args) {
  101. BiThrTree<String> aBiThrTree = new BiThrTree<String>();
  102. aBiThrTree.root=new BiThrNode<String>("A"); // A
  103. aBiThrTree.root.lChild=new BiThrNode<String>("B"); // / \
  104. aBiThrTree.root.lChild.lChild=new BiThrNode<String>("C"); // B D
  105. aBiThrTree.root.rChild=new BiThrNode<String>("D"); // / / \
  106. aBiThrTree.root.rChild.lChild=new BiThrNode<String>("E"); // C E F
  107. aBiThrTree.root.rChild.rChild=new BiThrNode<String>("F");
  108. aBiThrTree.inThreading();
  109. aBiThrTree.inOrderTraverse();
  110. aBiThrTree.inOrderTraverse2();
  111. }
  112. } 

  

  1. CBAEDF
  2. C, B, A, E, D, F,

BiThrTree

推荐阅读:

  线索二叉树原理及前序、中序线索化(Java版)(文中对线索二叉树的介绍和代码都比较清晰,且更加全面)。

赫夫曼树及其应用

  带权路径长度WPL最小的二叉树称为最优二叉树,也称为赫夫曼树(Huffman Tree)

  赫夫曼编码:

  推荐阅读:哈夫曼树(三)之 Java详解

 

【Java】 大话数据结构(9) 树(二叉树、线索二叉树)的更多相关文章

  1. 【PHP数据结构】完全二叉树、线索二叉树及树的顺序存储结构

    在上篇文章中,我们学习了二叉树的基本链式结构以及建树和遍历相关的操作.今天我们学习的则是一些二叉树相关的概念以及二叉树的一种变形形式. 完全二叉树 什么叫完全二叉树呢?在说到完全二叉树之前,我们先说另 ...

  2. 树和二叉树->线索二叉树

    文字描述 从二叉树的遍历可知,遍历二叉树的输出结果可看成一个线性队列,使得每个结点(除第一个和最后一个外)在这个线形队列中有且仅有一个前驱和一个后继.但是当采用二叉链表作为二叉树的存储结构时,只能得到 ...

  3. 从Java看数据结构之——树和他的操作集

    写在前面 树这种数据结构在计算机世界中有广泛的应用,比如操作系统中用到了红黑树,数据库用到了B+树,编译器中的语法树,内存管理用到了堆(本质上也是树),信息论中的哈夫曼编码等等等等.而树的实现和他的操 ...

  4. Python与数据结构[3] -> 树/Tree[0] -> 二叉树及遍历二叉树的 Python 实现

    二叉树 / Binary Tree 二叉树是树结构的一种,但二叉树的每一个节点都最多只能有两个子节点. Binary Tree: 00 |_____ | | 00 00 |__ |__ | | | | ...

  5. 线索二叉树的详细实现(C++)

    线索二叉树概述 二叉树虽然是非线性结构,但二叉树的遍历却为二又树的结点集导出了一个线性序列.希望很快找到某一结点的前驱或后继,但不希望每次都要对二叉树遍历一遍,这就需要把每个结点的前驱和后继信息记录下 ...

  6. Java数据结构之树和二叉树

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ Java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  7. 数据结构之二叉树篇卷四 -- 二叉树线索化(With Java)

    一.线索二叉树简介 二叉树本身是一种非线性结构,然而当你对二叉树进行遍历时,你会发现遍历结果是一个线性序列.这个序列中的节点存在前驱后继关系.因此,如何将这种前驱后继信息赋予给原本的二叉树呢?这就是二 ...

  8. 【Java】 大话数据结构(12) 查找算法(3) (平衡二叉树(AVL树))

    本文根据<大话数据结构>一书及网络资料,实现了Java版的平衡二叉树(AVL树). 平衡二叉树介绍 在上篇博客中所实现的二叉排序树(二叉搜索树),其查找性能取决于二叉排序树的形状,当二叉排 ...

  9. 数据结构《9》----Threaded Binary Tree 线索二叉树

    对于任意一棵节点数为 n 的二叉树,NULL 指针的数目为  n+1 , 线索树就是利用这些 "浪费" 了的指针的数据结构. Definition: "A binary ...

随机推荐

  1. 【BZOJ4883】棋盘上的守卫(最小生成树)

    [BZOJ4883]棋盘上的守卫(最小生成树) 题面 BZOJ 题解 首先\(n\)行\(m\)列的棋盘显然把行列拆开考虑,即构成了一个\(n+m\)个点的图.我们把格子看成边,那么点\((x,y)\ ...

  2. 【AGC006E】 Rotate 3x3

    Description ​ 题目链接 Solution ​ 显然每一列只能一起动,乱动则无解. ​ 对原网格按列黑白染色,显然每一列数只能在相同颜色之间交换,乱动则无解. ​ 之后考虑构造方案. ​ ...

  3. HDFS之append数据到已存在文件中

    遇到一个问题,想往已存在的hdfs文件中直接添加数据,默认的话应该是被拒绝的.查看了一些资料,可以这样操作: 在pdfs-site.xml中添加append支持: <property> & ...

  4. 在ubuntu server上搭建Hadoop

    1. Java安装: Because everything work with java. $ sudo apt-get install openjdk-7-jdk 安装之后,可以查看java的版本信 ...

  5. 一些常见修改命令(针对ubuntu 14.04 持续更新中...)

    1.PS1 在哪: echo $PS1    vi /etc/bash.bashrc      /W输出最后一个目录    /w输出完整目录 2.设置静态IP地址:vim /etc/network/i ...

  6. css中实现ul两端的li对齐外面边缘

    其实就是设置ul的宽度大一些就好

  7. [转载]AngularJS 指令 用法

    http://book.2cto.com/201312/37782.html http://www.itnose.net/detail/6144038.html http://www.cnblogs. ...

  8. [ASP.NET]初试Web API

    Web API 1: 需要环境(VS2010/.Net4.0/MVC4 ) http://www.asp.net/web-api/overview/creating-web-apis/creating ...

  9. VMware Linux 下 Nginx 安装配置 (一)

    资源准备 1. pcre-8.34.tar.gz: ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ 2. zlib-1.2.8.tar.g ...

  10. zTree的简单例子

    <%@ page language="java" pageEncoding="UTF-8" %> <%@ include file=" ...