JAVA中二叉树和树的运用_Java数据结构之树和二叉树

从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~

Java中的数据结构模型可以分为一下几部分:

1.线性结构

2.树形结构

3.图形或者网状结构

接下来的几章,我们将会分别讲解这几种数据结构,主要也是通过Java代码的方式来讲解相应的数据结构。

今天要讲解的是:Java线性结构

Java数据结构之树形结构

之前我们前几章学习的都是Java数据结构的线性结构,都是一对一的,从现在开始我们将要学习Java的树形结构。

树对于我们来普通Java程序员而言,也许平常的时候我们似乎感觉不到它的存在。但其实不是这样的。

其实是jdk帮我们已经封装好了,所以给我们一种错觉,树这种数据结构似乎离我们很远。

随便举一个例子:TreeMap这种集合框架,底层使用的就是红黑树...

下面对树这种数据结构进行一下简单的介绍(如果想要了解详细的内容的话,请自己百度吧~亲)。

1.树中的节点可以有若干个子节点,但是每个子节点只能有一个父节点。

这就好比一对夫妇可能有多个孩子,但是每个孩子只能有唯一的一对父母。

2.树的分类

按照当前节点是否有父节点可以分为:根节点和普通节点。

按照当前节点是否有子节点可以分为:叶子节点和普通节点。

3.节点

树的最基本组成单元,通常包括当前元素内容和指向下一个元素的引用

4.节点的度

当前节点所包含的子树的个数被称为节点的度

5.树的度

树中节点度数最大的值,我们称之为树的度

6.叶子节点

树中度数为0的节点我们称之为叶子节点

7. 分支节点

树中度数不为0的节点,我们称之为分支节点

8.节点的层次

节点的层次从根开始算起,根的层次为1,其余节点的层次为父节点的层次加1

9.树的深度

树中节点的最大层次被称为树的深度

10.有序树和无序树

如果将树中的节点看成是从左往右的有序的,我们称之为有序树。否则的话我们称之为无序树。

...

好吧,树的基本概念就介绍到这里。下面是具体的java代码的实现了哦。

为了记录树这种数据结构,我们必须记录节点和节点之间的关系。

主要有两种记录树与树之间的关系

1.父节点表示法,每个子节点都记录它所对应的父节点

2.子节点表示法,每个父节点都记录它所对应的所有子节点

下面从代码的角度进行相应的讲解

一、父节点表示法

package com.yonyou.test;

import java.util.ArrayList;

import java.util.List;

import com.yonyou.test.TreeParent.Node;

/**

* 测试类

* @author 小浩

* @创建日期 2015-3-20

*/

public class Test

{

public static void main(String[] args){

TreeParent tp = new TreeParent("root");

TreeParent.Node root = tp.root();

System.out.println(root);

tp.addNode("节点1" , root);

System.out.println("此树的深度:" + tp.deep());

tp.addNode("节点2" , root);

// 获取根节点的所有子节点

List> nodes = tp.children(root);

System.out.println("根节点的第一个子节点:" + nodes.get(0));

// 为根节点的第一个子节点新增一个子节点

tp.addNode("节点3" , nodes.get(0));

System.out.println("此树的深度:" + tp.deep());

}

}

/**

* 父节点表示法,当前子节点记录他所对应的父节点的位置

* @author 小浩

* @创建日期 2015-3-23

* @param

*/

class TreeParent

{

//树中能够存储的最大节点的个数

private final int DEFAULT_TREE_SIZE = 100;

//树中实际节点对的个数

private int treeSize = 0;

//内部类,用于存储相应的节点内容

public static class Node

{

//保存对应的数据

T data;

// 记录其父节点的位置

int parent;

public Node()

{

}

public Node(T data)

{

this.data = data;

}

public Node(T data , int parent)

{

this.data = data;

this.parent = parent;

}

public String toString()

{

return "TreeParent$Node[data=" + data

+ ", parent=" + parent + "]";

}

}

// 使用一个Node[]数组来记录该树里的所有节点

private Node[] nodes;

// 记录节点数

private int nodeNums;

// 以指定根节点创建树

@SuppressWarnings("unchecked")

public TreeParent(E data)

{

treeSize = DEFAULT_TREE_SIZE;

nodes = new Node[treeSize];

nodes[0] = new Node(data , -1);

nodeNums++;

}

/**

* 以指定根节点、指定treeSize创建树

* @param data

* @param treeSize

*/

@SuppressWarnings("unchecked")

public TreeParent(E data ,int treeSize)

{

this.treeSize = treeSize;

nodes = new Node[treeSize];

nodes[0] = new Node(data , -1);

nodeNums++;

}

/**

* 为指定节点添加子节点

* @param data

* @param parent

*/

public void addNode(E data , Node parent)

{

for (int i = 0 ; i < treeSize ; i++)

{

// 找到数组中第一个为null的元素,该元素保存新节点

if (nodes[i] == null)

{

//创建新节点,并用指定的数组元素保存它

nodes[i] = new Node(data , pos(parent));;

nodeNums++;

return;

}

}

throw new RuntimeException("该树已满,无法添加新节点");

}

/**

* 判断树是否为空。

*/

public boolean empty()

{

// 根节点是否为null

return nodes[0] == null;

}

/**

* 返回根节点

* @return

*/

public Node root()

{

// 返回根节点

return nodes[0];

}

/**

* 返回指定节点(非根节点)的父节点。

*/

public Node parent(Node node)

{

// 每个节点的parent记录了其父节点的位置

return nodes[node.parent];

}

/**

* 返回指定节点(非叶子节点)的所有子节点。

* @param parent

* @return

*/

public List> children(Node parent)

{

List> list = new ArrayList>();

for (int i = 0 ; i < treeSize ; i++)

{

// 如果当前节点的父节点的位置等于parent节点的位置

if (nodes[i] != null &&

nodes[i].parent == pos(parent))

{

list.add(nodes[i]);

}

}

return list;

}

/**

* 返回该树的深度。

*/

public int deep()

{

// 用于记录节点的最大深度

int max = 0;

for(int i = 0 ; i < treeSize && nodes[i] != null

; i++)

{

// 初始化本节点的深度

int def = 1;

// m记录当前节点的父节点的位置

int m = nodes[i].parent;

// 如果其父节点存在

while(m != -1 && nodes[m] != null)

{

// 向上继续搜索父节点

m = nodes[m].parent;

def++;

}

if(max < def)

{

max = def;

}

}

// 返回最大深度

return max;

}

/**

* 返回包含指定值的节点。

* @param node

* @return

*/

public int pos(Node node)

{

for (int i = 0 ; i < treeSize ; i++)

{

// 找到指定节点

if (nodes[i] == node)

{

return i;

}

}

return -1;

}

}

二、子节点表示法

package com.yonyou.test;

import java.util.ArrayList;

import java.util.List;

/**

* 测试类

* @author 小浩

* @创建日期 2015-3-20

*/

public class Test

{

public static void main(String[] args){

TreeChild treeChild=new TreeChild("0");

TreeChild.Node root=treeChild.root();

System.out.println("当前树的根节点为:"+root.data);

treeChild.addNode("1",root);

treeChild.addNode("2",root);

treeChild.addNode("3",treeChild.children(root).get(0));

System.out.println("树的深度为:"+treeChild.deep());

}

}

/**

* 子节点表示法,当前子节点记录他所对应的所有子节点的位置

* @author 小浩

* @创建日期 2015-3-23

* @param

*/

class TreeChild

{

/**

* 静态内部子类链

* @author 小浩

* @创建日期 2015-3-23

*/

private static class SonNode

{

// 记录当前节点的位置

private int pos;

private SonNode next;

public SonNode(int pos , SonNode next)

{

this.pos = pos;

this.next = next;

}

}

/**

* 静态内部类Node,用于存储相关节点的内容和对应子节点的首个链

* @author 小浩

* @创建日期 2015-3-23

* @param

*/

public static class Node

{

T data;

// 记录第一个子节点

SonNode first;

public Node(T data)

{

this.data = data;

this.first = null;

}

public String toString()

{

if (first != null)

{

return "TreeChild$Node[data=" + data

+ ", first=" + first.pos + "]";

}

else

{

return "TreeChild$Node[data=" + data + ", first=-1]";

}

}

}

//树中能够存储的节点的最大数量

private final int DEFAULT_TREE_SIZE = 100;

//树中实际存储的节点个数

private int treeSize = 0;

// 使用一个Node[]数组来记录该树里的所有节点

private Node[] nodes;

// 记录节点数

private int nodeNums;

/**

* 以指定根节点创建树

* @param data

*/

@SuppressWarnings("unchecked")

public TreeChild(E data)

{

treeSize = DEFAULT_TREE_SIZE;

nodes = new Node[treeSize];

nodes[0] = new Node(data);

nodeNums++;

}

/**

* 以指定根节点、指定treeSize创建树

*/

@SuppressWarnings("unchecked")

public TreeChild(E data ,int treeSize)

{

this.treeSize = treeSize;

nodes = new Node[treeSize];

nodes[0] = new Node(data);

nodeNums++;

}

/**

* 为指定节点添加子节点

* @param data

* @param parent

*/

public void addNode(E data , Node parent)

{

for (int i = 0 ; i < treeSize ; i++)

{

// 找到数组中第一个为null的元素,该元素保存新节点

if (nodes[i] == null)

{

// 创建新节点,并用指定数组元素来保存它

nodes[i] = new Node(data);

if (parent.first == null)

{

parent.first = new SonNode(i , null);

}

else

{

SonNode next = parent.first;

while (next.next != null)

{

next = next.next;

}

next.next = new SonNode(i , null);

}

nodeNums++;

return;

}

}

throw new RuntimeException("该树已满,无法添加新节点");

}

/**

* 判断树是否为空。

* @return

*/

public boolean empty()

{

// 根节点是否为null

return nodes[0] == null;

}

/**

* 返回根节点

* @return

*/

public Node root()

{

// 返回根节点

return nodes[0];

}

/**

* 返回指定节点(非叶子节点)的所有子节点。

*/

public List> children(Node parent)

{

List> list = new ArrayList>();

// 获取parent节点的第一个子节点

SonNode next = parent.first;

// 沿着孩子链不断搜索下一个孩子节点

while (next != null)

{

// 添加孩子链中的节点

list.add(nodes[next.pos]);

next = next.next;

}

return list;

}

/**

* 返回指定节点(非叶子节点)的第index个子节点。

* @param parent

* @param index

* @return

*/

public Node child(Node parent , int index)

{

// 获取parent节点的第一个子节点

SonNode next = parent.first;

// 沿着孩子链不断搜索下一个孩子节点

for (int i = 0 ; next != null ; i++)

{

if (index == i)

{

return nodes[next.pos];

}

next = next.next;

}

return null;

}

/**

* 返回该树的深度。

* @return

*/

public int deep()

{

// 获取该树的深度

return deep(root());

}

/**

* 采用递归的方式方式查找出树的最大深度

* @param root

* @return

*/

private int deep(Node node) {

if(node.first==null)

return 1;

else{

int maxDeep=0;

SonNode sonNode=node.first;

while(sonNode!=null)

{

int tempDeep=deep(nodes[sonNode.pos]);

if(tempDeep>maxDeep)

maxDeep=tempDeep;

sonNode=sonNode.next;

}

return maxDeep+1;

}

}

/**

* 返回包含指定值的节点。

* @param node

* @return

*/

public int pos(Node node)

{

for (int i = 0 ; i < treeSize ; i++)

{

// 找到指定节点

if (nodes[i] == node)

{

return i;

}

}

return -1;

}

}

三、二叉树的讲解

对于普通树而言,由于它们没有特定的规律,所以在现实生活中的应用不如二叉树广泛。

所谓二叉树,指的就是让每棵树中的节点最多有两个子节点,而且它们是严格的区分左子节点和右子节点的。

下面简单说一下二叉树和普通树的区别和联系

1、树中节点的度数是没有限制的,而二叉树中的节点的最大度数是有限制,最大为2.

2、普通树的节点无左右节点之分,但是二叉树是严格区分左右节点的。

什么样的树为满二叉树?

一个深度为k的二叉树,它所包含的节点的个数为2^k-1个节点的话,那么这样的树被称为满二叉树。

什么样的树为完全二叉树呢?

如果一棵二叉树除最后一层外,其余层都是满的。并且最后一层或者是满的,或者仅在右边缺少若干连续的节点,则此二叉树

被称为完全二叉树。

下面简单讲解一下二叉树的常见特性,如果想要了解详细的内容的话,请自己百度...谢谢。

1.二叉树第n层上面节点的个数为2^(n-1)。

2.深度为k的二叉树最多有2^n-1个节点,即我们所说的满二叉树。

3.在任何一棵二叉树上面,如果其叶子节点的度数为n0,度数为2的节点的个数为n2,那么下面的等式是一定成立的。

n0=n2+1;

4.具有n个节点的完全二叉树的深度为log2(n+1);

下面以具体的代码为例讲解二叉树的实现过程

1.二叉树的顺序存储

首先进行一下说明,当使用数组进行存储二叉树的时候可能会产生一定的浪费。

如果该树是完全二叉树的话,那么很好,不会产生任何的空间浪费,但是如果当前二叉树仅仅有右子节点的话

那样的话会产生很大的空间的浪费哦。

package com.yonyou.test;

import java.util.ArrayList;

import java.util.List;

/**

* 测试类

* @author 小浩

* @创建日期 2015-3-20

*/

public class Test

{

public static void main(String[] args){

ArrayBinTree binTree =new ArrayBinTree(4, "根");

binTree.add(0 , "第二层右子节点" , false);

binTree.add(2 , "第三层右子节点" , false);

binTree.add(6 , "第四层右子节点" , false);

System.out.println(binTree);

}

}

/**

* 子节点表示法,当前子节点记录他所对应的所有子节点的位置

* @author 小浩

* @创建日期 2015-3-23

* @param

*/

class ArrayBinTree

{

// 使用数组来记录该树的所有节点

private Object[] datas;

// 使用数组的深度

private int DEFAULT_DEEP = 8;

// 保存该树的深度

private int deep;

//树中实际节点的个数

private int arraySize;

/**

* 以默认的深度来创建二叉树

*/

public ArrayBinTree()

{

this.deep = DEFAULT_DEEP;

this.arraySize = (int)Math.pow(2 , deep) - 1;

datas = new Object[arraySize];

}

/**

* 以指定深度来创建二叉树

* @param deep

*/

public ArrayBinTree(int deep)

{

this.deep = deep;

this.arraySize = (int)Math.pow(2 , deep) - 1;

datas = new Object[arraySize];

}

/**

* 以指定深度,指定根节点创建二叉树

* @param deep

* @param data

*/

public ArrayBinTree(int deep , T data)

{

this.deep = deep;

this.arraySize = (int)Math.pow(2 , deep) - 1;

datas = new Object[arraySize];

datas[0] = data;

}

/**

* 为指定节点添加子节点。

* @param index 需要添加子节点的父节点的索引

* @param data 新子节点的数据

* @param left 是否为左节点

*/

public void add(int index , T data , boolean left)

{

if (datas[index] == null)

{

throw new RuntimeException(index + "处节点为空,无法添加子节点");

}

if (2 * index + 1 >= arraySize)

{

throw new RuntimeException("树底层的数组已满,树越界异常");

}

// 添加左子节点

if (left)

{

datas[2 * index + 1] = data;

}

else

{

datas[2 * index + 2] = data;

}

}

/**

* 判断二叉树是否为空。

* @return

*/

public boolean empty()

{

// 根据根元素来判断二叉树是否为空

return datas[0] == null;

}

/**

* 返回根节点。

* @return

*/

@SuppressWarnings("unchecked")

public T root()

{

return (T)datas[0] ;

}

/**

* 返回指定节点(非根节点)的父节点。

* @param index

* @return

*/

@SuppressWarnings("unchecked")

public T parent(int index)

{

return (T)datas[(index - 1) / 2] ;

}

/**

* 返回指定节点(非叶子)的左子节点。

* @param index

* @return

*/

// 当左子节点不存在时返回null。

@SuppressWarnings("unchecked")

public T left(int index)

{

if (2 * index + 1 >= arraySize)

{

throw new RuntimeException("该节点为叶子节点,无子节点");

}

return (T)datas[index * 2 + 1] ;

}

/**

* 返回指定节点(非叶子)的右子节点。

* @param index

* @return

*/

// 当右子节点不存在时返回null。

@SuppressWarnings("unchecked")

public T right(int index)

{

if (2 * index + 1 >= arraySize)

{

throw new RuntimeException("该节点为叶子节点,无子节点");

}

return (T)datas[index * 2 + 2] ;

}

/**

* 返回该二叉树的深度。

* @param index

* @return

*/

public int deep(int index)

{

return deep;

}

/**

* 返回指定节点的位置。

* @param data

* @return

*/

public int pos(T data)

{

// 该循环实际上就是按广度遍历来搜索每个节点

for (int i = 0 ; i < arraySize ; i++)

{

if (datas[i].equals(data))

{

return i;

}

}

return -1;

}

/**

* 重写toString方法

*/

public String toString()

{

return java.util.Arrays.toString(datas);

}

}

2.二叉树的二叉链表存储

package com.yonyou.test;

import java.util.ArrayList;

import java.util.List;

/**

* 测试类

* @author 小浩

* @创建日期 2015-3-20

*/

public class Test

{

public static void main(String[] args){

TwoLinkBinTree binTree = new TwoLinkBinTree("根节点");

// 依次添加节点

TwoLinkBinTree.TreeNode tn1 = binTree.addNode(binTree.root()

, "第二层左节点" , true);

TwoLinkBinTree.TreeNode tn2 = binTree.addNode(binTree.root()

, "第二层右节点" ,false );

TwoLinkBinTree.TreeNode tn3 = binTree.addNode(tn2

, "第三层左节点" , true);

TwoLinkBinTree.TreeNode tn4 = binTree.addNode(tn2

, "第三层右节点" , false);

TwoLinkBinTree.TreeNode tn5 = binTree.addNode(tn3

, "第四层左节点" , true);

System.out.println("tn2的左子节点:" + binTree.leftChild(tn2));

System.out.println("tn2的右子节点:" + binTree.rightChild(tn2));

System.out.println(binTree.deep());

}

}

/**

* 二叉树的二叉链表存储法

* @author 小浩

* @创建日期 2015-3-23

* @param

*/

class TwoLinkBinTree

{

/**

* 存储相应节点的内部类

* @author 小浩

* @创建日期 2015-3-23

*/

public static class TreeNode

{

Object data;

TreeNode left;

TreeNode right;

public TreeNode()

{

}

public TreeNode(Object data)

{

this.data = data;

}

public TreeNode(Object data , TreeNode left

, TreeNode right)

{

this.data = data;

this.left = left;

this.right = right;

}

}

//当前树的根节点

private TreeNode root;

// 以默认的构造器来创建二叉树

public TwoLinkBinTree()

{

this.root = new TreeNode();

}

// 以指定根元素来创建二叉树

public TwoLinkBinTree(E data)

{

this.root = new TreeNode(data);

}

/**

* 为指定节点添加子节点。

* @param index 需要添加子节点的父节点的索引

* @param data 新子节点的数据

* @param isLeft 是否为左节点

* @return 新增的节点

*/

public TreeNode addNode(TreeNode parent , E data

, boolean isLeft)

{

if (parent == null)

{

throw new RuntimeException(parent +

"节点为null,无法添加子节点");

}

if (isLeft && parent.left != null)

{

throw new RuntimeException(parent +

"节点已有左子节点,无法添加左子节点");

}

if (!isLeft && parent.right != null)

{

throw new RuntimeException(parent +

"节点已有右子节点,无法添加右子节点");

}

TreeNode newNode = new TreeNode(data);

if (isLeft)

{

// 让父节点的left引用指向新节点

parent.left = newNode;

}

else

{

// 让父节点的right引用指向新节点

parent.right = newNode;

}

return newNode;

}

/**

* 判断二叉树是否为空。

* @return

*/

public boolean empty()

{

// 根据根元素来判断二叉树是否为空

return root.data == null;

}

/**

* 返回根节点。

* @return

*/

public TreeNode root()

{

if (empty())

{

throw new RuntimeException("树为空,无法访问根节点");

}

return root;

}

/**

* 返回指定节点(非根节点)的父节点。

* @param node

* @return

*/

public E parent(TreeNode node)

{

// 对于二叉链表存储法,如果要访问指定节点的父节点必须遍历二叉树

return null;

}

/**

* 返回指定节点(非叶子)的左子节点。当左子节点不存在时返回null

* @param parent

* @return

*/

@SuppressWarnings("unchecked")

public E leftChild(TreeNode parent)

{

if (parent == null)

{

throw new RuntimeException(parent +

"节点为null,无法添加子节点");

}

return parent.left == null ? null : (E)parent.left.data;

}

/**

* 返回指定节点(非叶子)的右子节点。当右子节点不存在时返回null

* @param parent

* @return

*/

@SuppressWarnings("unchecked")

public E rightChild(TreeNode parent)

{

if (parent == null)

{

throw new RuntimeException(parent +

"节点为null,无法添加子节点");

}

return parent.right == null ? null : (E)parent.right.data;

}

/**

* 返回该二叉树的深度。

* @return

*/

public int deep()

{

// 获取该树的深度

return deep(root);

}

/**

* 这是一个递归方法:每棵子树的深度为其所有子树的最大深度 + 1

* @param node

* @return

*/

private int deep(TreeNode node)

{

if (node == null)

{

return 0;

}

// 没有子树

if (node.left == null

&& node.right == null)

{

return 1;

}

else

{

int leftDeep = deep(node.left);

int rightDeep = deep(node.right);

// 记录其所有左、右子树中较大的深度

int max = leftDeep > rightDeep ?

leftDeep : rightDeep;

// 返回其左右子树中较大的深度 + 1

return max + 1;

}

}

}

3.二叉树的三叉链表存储

package com.yonyou.test;

/**

* 测试类

* @author 小浩

* @创建日期 2015-3-20

*/

public class Test

{

public static void main(String[] args)

{

ThreeLinkBinTree binTree = new ThreeLinkBinTree("根节点");

//依次添加节点

ThreeLinkBinTree.TreeNode tn1 = binTree.addNode(binTree.root()

, "第二层左节点" , true);

ThreeLinkBinTree.TreeNode tn2 = binTree.addNode(binTree.root()

, "第二层右节点" ,false );

ThreeLinkBinTree.TreeNode tn3 = binTree.addNode(tn2

, "第三层左节点" , true);

ThreeLinkBinTree.TreeNode tn4 = binTree.addNode(tn2

, "第三层右节点" , false);

ThreeLinkBinTree.TreeNode tn5 = binTree.addNode(tn3

, "第四层左节点" , true);

System.out.println("tn2的父节点:" + binTree.parent(tn2));

System.out.println("tn2的左子节点:" + binTree.leftChild(tn2));

System.out.println("tn2的右子节点:" + binTree.rightChild(tn2));

System.out.println(binTree.deep());

}

}

/**

* 二叉树的二叉链表存储法

* @author 小浩

* @创建日期 2015-3-23

* @param

*/

class ThreeLinkBinTree

{

public static class TreeNode

{

Object data;

TreeNode left;

TreeNode right;

TreeNode parent;

public TreeNode()

{

}

public TreeNode(Object data)

{

this.data = data;

}

public TreeNode(Object data , TreeNode left

, TreeNode right , TreeNode parent)

{

this.data = data;

this.left = left;

this.right = right;

this.parent = parent;

}

}

private TreeNode root;

// 以默认的构造器来创建二叉树

public ThreeLinkBinTree()

{

this.root = new TreeNode();

}

// 以指定根元素来创建二叉树

public ThreeLinkBinTree(E data)

{

this.root = new TreeNode(data);

}

/**

* 为指定节点添加子节点。

* @param index 需要添加子节点的父节点的索引

* @param data 新子节点的数据

* @param isLeft 是否为左节点

* @return 新增的节点

*/

public TreeNode addNode(TreeNode parent , E data

, boolean isLeft)

{

if (parent == null)

{

throw new RuntimeException(parent +

"节点为null,无法添加子节点");

}

if (isLeft && parent.left != null)

{

throw new RuntimeException(parent +

"节点已有左子节点,无法添加左子节点");

}

if (!isLeft && parent.right != null)

{

throw new RuntimeException(parent +

"节点已有右子节点,无法添加右子节点");

}

TreeNode newNode = new TreeNode(data);

if (isLeft)

{

// 让父节点的left引用指向新节点

parent.left = newNode;

}

else

{

// 让父节点的right引用指向新节点

parent.right = newNode;

}

// 让新节点的parent引用到parent节点

newNode.parent = parent;

return newNode;

}

// 判断二叉树是否为空。

public boolean empty()

{

// 根据根元素来判断二叉树是否为空

return root.data == null;

}

// 返回根节点。

public TreeNode root()

{

if (empty())

{

throw new RuntimeException("树为空,无法访问根节点");

}

return root;

}

// 返回指定节点(非根节点)的父节点。

@SuppressWarnings("unchecked")

public E parent(TreeNode node)

{

if (node == null)

{

throw new RuntimeException(node +

"节点为null,无法访问其父节点");

}

return (E)node.parent.data;

}

// 返回指定节点(非叶子)的左子节点,当左子节点不存在时返回null

@SuppressWarnings("unchecked")

public E leftChild(TreeNode parent)

{

if (parent == null)

{

throw new RuntimeException(parent +

"节点为null,无法添加子节点");

}

return parent.left == null ? null : (E)parent.left.data;

}

// 返回指定节点(非叶子)的右子节点,当右子节点不存在时返回null

@SuppressWarnings("unchecked")

public E rightChild(TreeNode parent)

{

if (parent == null)

{

throw new RuntimeException(parent +

"节点为null,无法添加子节点");

}

return parent.right == null ? null : (E)parent.right.data;

}

// 返回该二叉树的深度。

public int deep()

{

// 获取该树的深度

return deep(root);

}

// 这是一个递归方法:每棵子树的深度为其所有子树的最大深度 + 1

private int deep(TreeNode node)

{

if (node == null)

{

return 0;

}

// 没有子树

if (node.left == null

&& node.right == null)

{

return 1;

}

else

{

int leftDeep = deep(node.left);

int rightDeep = deep(node.right);

// 记录其所有左、右子树中较大的深度

int max = leftDeep > rightDeep ?

leftDeep : rightDeep;

// 返回其左右子树中较大的深度 + 1

return max + 1;

}

}

}

4.二叉树的几种遍历方法的讲解

如果采用顺序存储来保存二叉树的话,那么遍历此二叉树很简单,直接遍历数组就可以了,但是如果要是采用三叉链表或者

而叉链表的话,那么就会有很多的不同哦。

如果采用链表来存储二叉树的话,那么我们可以有两种遍历二叉树的方法:

1)深度优先遍历

a、先序遍历二叉树(前序遍历二叉树)

b、中序遍历二叉树

c、后序遍历二叉树

2)广度优先遍历,右称为按层遍历。

下面将会从具体的代码进行相关内容的讲解:

a、先序遍历二叉树

// 实现先序遍历

public List preIterator()

{

return preIterator(root);

}

private List preIterator(TreeNode node)

{

List list = new ArrayList();

// 处理根节点

list.add(node);

// 递归处理左子树

if (node.left != null)

{

list.addAll(preIterator(node.left));

}

// 递归处理右子树

if (node.right != null)

{

list.addAll(preIterator(node.right));

}

return list;

}

b、中序遍历二叉树

// 实现中序遍历

public List inIterator()

{

return inIterator(root);

}

private List inIterator(TreeNode node)

{

List list = new ArrayList();

// 递归处理左子树

if (node.left != null)

{

list.addAll(inIterator(node.left));

}

// 处理根节点

list.add(node);

// 递归处理右子树

if (node.right != null)

{

list.addAll(inIterator(node.right));

}

return list;

}

public List postIterator()

{

return postIterator(root);

}

c、后序遍历二叉树

// 实现后序遍历

private List postIterator(TreeNode node)

{

List list = new ArrayList();

// 递归处理左子树

if (node.left != null)

{

list.addAll(postIterator(node.left));

}

// 递归处理右子树

if (node.right != null)

{

list.addAll(postIterator(node.right));

}

// 处理根节点

list.add(node);

return list;

}

d、广度优先遍历二叉树

// 广度优先遍历

public List breadthFirst()

{

Queue queue = new ArrayDeque();

List list = new ArrayList();

if( root != null)

{

// 将根元素加入“队列”

queue.offer(root);

}

while(!queue.isEmpty())

{

// 将该队列的“头部”的元素添加到List中

list.add(queue.peek());

// 将该队列的“头部”的元素移出队列

TreeNode p = queue.poll();

// 如果左子节点不为null,将它加入“队列”

if(p.left != null)

{

queue.offer(p.left);

}

// 如果右子节点不为null,将它加入“队列”

if(p.right != null)

{

queue.offer(p.right);

}

}

return list;

}

好吧,由于篇幅的限制,今天先到这里,下一篇我们将要继续探讨树和二叉树的相关内容。

下一篇的地址为:

你可能感兴趣的:(JAVA中二叉树和树的运用)