您的位置:首页 > 编程语言 > Java开发

使用java实现链式存储的二叉树

2017-11-18 12:09 387 查看
上一篇文章写了使用java实现顺序存储的二叉树,这次接着使用java实现链式存储的二叉树:
首先创建一个结点类TreeNode<E>:
package com.linkedTree;

public class TreeNode<E> {
private E item;
private TreeNode<E> leftChild;
private TreeNode<E> rightChild;
public TreeNode(E item){
this(item,null,null);
}
public TreeNode(E item, TreeNode<E> l , TreeNode<E> r){
this.item = item;
this.leftChild = l;
this.rightChild = r;
}
public TreeNode<E> getRightChild() {
return rightChild;
}
public void setRightSibling(TreeNode<E> rightChild) {
this.rightChild = rightChild;
}
public TreeNode<E> getLeftChild() {
return leftChild;
}
public void setLeftSibling(TreeNode<E> leftChild) {
this.leftChild = leftChild;
}
public E getItem() {
return item;
}
public void setItem(E item) {
this.item = item;
}
@Override
public int hashCode() {//重写hashCode和equals方法
final int prime = 31;
int result = 1;
result = prime * result + ((item == null) ? 0 : item.hashCode());
result = prime * result + ((leftChild == null) ? 0 : leftChild.hashCode());
result = prime * result + ((rightChild == null) ? 0 : rightChild.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TreeNode<?> other = (TreeNode<?>) obj;
if (item == null) {
if (other.item != null)
return false;
} else if (!item.equals(other.item))
return false;
if (leftChild == null) {
if (other.leftChild != null)
return false;
} else if (!leftChild.equals(other.leftChild))
return false;
if (rightChild == null) {
if (other.rightChild != null)
return false;
} else if (!rightChild.equals(other.rightChild))
return false;
return true;
}

}

然后创建一个接口LTree<E>,规范链式存储二叉树的方法:
package com.linkedTree;

import com.linkedTree.TreeNode;

public interface Ltree<E> {
boolean isEmpty();
TreeNode<E> getRoot();
TreeNode<E> getParent(TreeNode<E> node);
TreeNode<E> getLeftChild(TreeNode<E> node);
TreeNode<E> getRightChild(TreeNode<E> node);
void breadFirstOrder();//广度优先
void preOrder();//先序遍历
void inOrder();//中序遍历
void postOrder();//后序遍历
void clear();//删除整个树
}

接着创建一个类LinkedTree<E>来实现LTree<E>接口:
package com.linkedTree;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;

public class LinkedTree<E> implements Ltree<E> {

private TreeNode<E> root;
public LinkedTree(TreeNode<E> root){
this.root = root;
}
@Override
public boolean isEmpty() {
return root == null;
}

@Override
public TreeNode<E> getRoot() {
return root;
}

@Override
public TreeNode<E> getParent(TreeNode<E> node) {
/**
* 采用后序遍历来寻找其父节点
* 后序遍历:
* 从根结点开始,向左搜索,每搜索到一个结点就将其压入栈中,直到压入栈中的结点不再有左子树。读取栈顶元素,如果结点有右子树不为空且未被访问则入栈当前结点访问其右子树,否则访问当前元素弹栈访问
* */
Stack<TreeNode<E>> nodeStack = new Stack<TreeNode<E>>();
TreeNode<E> pointer = root;
Set<TreeNode<E>> visitedSet = new HashSet<TreeNode<E>>();
while(pointer != null){
while(pointer.getLeftChild()!=null){
nodeStack.push(pointer);
pointer = pointer.getLeftChild();
}
while( pointer != null&&
(pointer.getRightChild()==null||visitedSet.contains(pointer.getRightChild()))){
if(node.equals(pointer))
return nodeStack.pop();
visitedSet.add(pointer);
if(nodeStack.isEmpty())
return null;
pointer = nodeStack.pop();
}
nodeStack.push(pointer);
pointer = pointer.getRightChild();
}
return null;
}

@Override
public TreeNode<E> getLeftChild(TreeNode<E> node) {
return node.getLeftChild();
}

@Override
public TreeNode<E> getRightChild(TreeNode<E> node) {
return node.getRightChild();
}

@Override
public void breadFirstOrder() {
/**
* 广度优先遍历:
* 用队列来实现,对于根节点,进行访问,然后出队列将左孩子放入队列如果不为空,右孩子放入队列如果不为空,
* 然后继续分别访问左孩子,将左孩子的左孩子右孩子放入队列,同理右孩子,以此类推,直到队列为空
* */
String str = "";
Queue<TreeNode<E>> nodeList =new LinkedList<TreeNode<E>>();//LinkedLits实现了Queue而ArrayList没有实现 因此前者可以当队列用 后者不可以
nodeList.add(root);
while(!nodeList.isEmpty()){
TreeNode<E> node = nodeList.poll();
str+=node.getItem()+" ";
if(node.get
c810
LeftChild()!=null){
nodeList.add(node.getLeftChild());
}
if(node.getRightChild()!=null){
nodeList.add(node.getRightChild());
}
}
System.out.println(str);
}

@Override
public void preOrder() {
/**
* 先序遍历:
* 访问一个节点,然后遍历访问左子树,将右子树压入栈中,依次弹栈 直到栈空
* */
Stack<TreeNode<E>> nodeStack = new Stack<TreeNode<E>>();
TreeNode<E> pointer = root;
String str = "";
while(!nodeStack.isEmpty()||pointer!=null){
if(pointer!=null){
str += pointer.getItem()+" ";
TreeNode<E> l = pointer.getLeftChild();
TreeNode<E> r = pointer.getRightChild();
pointer = l;
if(r!=null){
nodeStack.push(r);
}
}
else{
pointer = nodeStack.pop();
}
}
System.out.println(str);
}

@Override
public void inOrder() {
/**
* 中序遍历:
* 从根节点开始,对左子树进行遍历,将遍历到的左子树压入栈中,遍历完后访问弹栈的结点,访问该节点的右子树,同理前面的方法继续遍历右子树的左子树 直到栈空
* */
Stack<TreeNode<E>> nodeStack = new Stack<TreeNode<E>>();
String str = "";
TreeNode<E> pointer = root;
while(!nodeStack.isEmpty()||pointer!=null){
if(pointer!=null){//将左子树一一放入栈
nodeStack.push(pointer);
pointer = pointer.getLeftChild();
}
else{//当前结点没有左子树了
pointer = nodeStack.pop();
str += pointer.getItem()+" ";
pointer = pointer.getRightChild();
}
}
System.out.println(str);
}

@Override
public void postOrder() {
/**
* 后序遍历:
* 从根结点开始,向左搜索,每搜索到一个结点就将其压入栈中,直到压入栈中的结点不再有左子树。读取栈顶元素,如果结点右右子树不为空且未被访问则当前结点入栈,访问其右子树,否则访问当前元素 弹栈
* */
Stack<TreeNode<E>> nodeStack = new Stack<TreeNode<E>>();
TreeNode<E> pointer = root;
Set<TreeNode<E>> visitedSet = new HashSet<TreeNode<E>>();//存放被访问过的元素
String str = "";
while(pointer!=null){
for(;pointer.getLeftChild()!=null;pointer = pointer.getLeftChild()){//最后一个有左子树的结点的左子树没有被压入栈
nodeStack.push(pointer);//将所有左子树结点压入栈中
}
while(pointer!=null && (pointer.getRightChild()==null||visitedSet.contains(pointer.getRightChild()))){//右子树被访问过了或者右子树为空
str += pointer.getItem()+" ";
visitedSet.add(pointer);//把pointer置为被访问了
if(nodeStack.isEmpty())
{
System.out.println(str);
return;
}
pointer = nodeStack.pop();
}
nodeStack.push(pointer);
pointer = pointer.getRightChild();
}
}

@Override
public void clear() {
root = null;//直接root=null就可以 因为剩下的结点会因为不可达而被GC回收
}

}

最后写测试类,来进行测试:
public class Test{
public static void main(String[] args) {
System.out.println("LinkedTree test:");
TreeNode<Integer> node7 = new TreeNode<Integer>(7);
TreeNode<Integer> node8 = new TreeNode<Integer>(8);
TreeNode<Integer> node3 = new TreeNode<Integer>(3,node7,node8);
TreeNode<Integer> node4 = new TreeNode<Integer>(4);
TreeNode<Integer> node5 = new TreeNode<Integer>(5);
TreeNode<Integer> node6 = new TreeNode<Integer>(6);
TreeNode<Integer> node2 = new TreeNode<Integer>(2,node5,node6);
TreeNode<Integer> node1 = new TreeNode<Integer>(1,node3,node4);
TreeNode<Integer> root = new TreeNode<Integer>(0, node1, node2);
LinkedTree<Integer> lt = new LinkedTree<Integer>(root);
lt.breadFirstOrder();//0 1 2 3 4 5 6 7 8
lt.preOrder();//0 1 3 7 8 4 2 5 6
lt.inOrder();//7 3 8 1 4 0 5 2 6
lt.postOrder();//7 8 3 4 1 5 6 2 0
System.out.println(lt.getParent(node7).getItem());//3
lt.clear();
System.out.println(lt.getRoot());//null
}
}简单的链式存储二叉树便实现了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: