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

来源:互联网 发布:mac版阿里旺旺打不开 编辑:程序博客网 时间:2024/06/17 06:19

上一篇文章写了使用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.getLeftChild()!=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    }}
简单的链式存储二叉树便实现了。

原创粉丝点击