二叉树之二叉链表

来源:互联网 发布:4g通信软件 编辑:程序博客网 时间:2024/05/22 21:45

本文利用java语言模拟二叉树的二叉链表的实现,下面先对二叉树的相关概念作简单介绍:
二叉树:每个结点至多有两颗子树,且子树有左右之分,其次序不能任意颠倒; 基本形态:空、仅有根结点、左子树为空、右子树为空、左右子树均非空;
完全二叉树父子结点序号关系:
* 如果i=1,则结点i为根结点,否则其双亲结点为[i/2];
* 如果2i > n,则结点i无左孩子,否则其左孩子结点为2i;
* 如果2i+1 > n,则结点i无右孩子,否则右孩子结点为2i+1;
二叉链表:结点包含数据域和左右指针(引用)域的链表;

下面主要给出二叉链表的实现:

1. 二叉链表的结点

package org.sky.tree;/** * 二叉链表结点 *  * @author sky * * @param <E> */public class BinaryTreeNode<E> {    E element;    BinaryTreeNode<E> leftChild;    BinaryTreeNode<E> rightChild;    public BinaryTreeNode() {        super();        this.element = null;        this.leftChild = null;        this.rightChild = null;    }    public BinaryTreeNode(E element) {        super();        this.element = element;        this.leftChild = null;        this.rightChild = null;    }    public BinaryTreeNode(E element, BinaryTreeNode<E> leftChild,            BinaryTreeNode<E> rightChild) {        super();        this.element = element;        this.leftChild = leftChild;        this.rightChild = rightChild;    }    public E getElement() {        return element;    }    public void setElement(E element) {        this.element = element;    }    public BinaryTreeNode<E> getLeftChild() {        return leftChild;    }    public void setLeftChild(BinaryTreeNode<E> leftChild) {        this.leftChild = leftChild;    }    public BinaryTreeNode<E> getRightChild() {        return rightChild;    }    public void setRightChild(BinaryTreeNode<E> rightChild) {        this.rightChild = rightChild;    }       public boolean isLeaf() {        if (this.leftChild == null && this.rightChild == null) {            return true;        }        return false;    }}

2. 二叉链表实现

package org.sky.tree;import java.util.Collection;import java.util.LinkedList;import java.util.List;import java.util.Queue;import java.util.Scanner;import java.util.Stack;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.LinkedBlockingQueue;/** * 二叉链表实现 *  * @author sky * * @param <E> */public class BinaryTree<E> {    private BinaryTreeNode<E> root;    public BinaryTree() {        super();        this.root = new BinaryTreeNode<E>();    }    public boolean isEmpty() {        if (root == null) {            return true;        }        return false;    }    public BinaryTreeNode<E> getRoot() {        return root;    }       /**     * 将输入的数据随机分配在二叉树的结点,以生成随机二叉树     * @param node     * @param element     */    public void createTreeRandomly(BinaryTreeNode<E> node, E element){        if(root == null){            root = new BinaryTreeNode<E>();        }else{            if(Math.random() > 0.5){                if(node.leftChild == null){                    node.leftChild = new BinaryTreeNode<E>(element);                }else{                    createTreeRandomly(node.leftChild,element);                }            }else{                if(node.rightChild == null){                    node.rightChild = new BinaryTreeNode<E>(element);                }else{                    createTreeRandomly(node.rightChild,element);                }            }        }    }    /**     * 根据传入的集合创建完全二叉树     * 此处利用了完全二叉树父结点和子结点间的关系:如果i=1,则结点i为根结点,否则其双亲结点为[i/2];     *                              如果2i > n,则结点i无左孩子,否则其左孩子结点为2i;     *                              如果2i+1 > n,则结点i无右孩子,否则右孩子结点为2i+1;     * @param c     */    private BinaryTreeNode<E> node = null;    public void createCompleteBinaryTree(Collection<? extends E> c){        if(c != null && c.size() > 0){            List<BinaryTreeNode<E>> treeList = new LinkedList<BinaryTreeNode<E>>();            for(Object o : c){                              BinaryTreeNode<E> binaryTreeNode = new BinaryTreeNode<E>((E)o);                treeList.add(binaryTreeNode);            }            LinkedBlockingDeque<BinaryTreeNode<E>> queue = new LinkedBlockingDeque<BinaryTreeNode<E>>();            //对前treeList.size()/2 - 1个父节点按照父节点与孩子节点的数字关系建立二叉树             for(int parentIndex =  0; parentIndex < treeList.size()/2; parentIndex++){                              if(parentIndex == 0){                    root = treeList.get(parentIndex);                    //左子树                    root.leftChild = treeList.get(parentIndex*2 + 1);                    queue.add(root.leftChild);                    //右子树                    root.rightChild = treeList.get(parentIndex*2 +2);                    queue.add(root.rightChild);                }else{                    if(!queue.isEmpty() && parentIndex*2+1 < treeList.size()){                        node = (BinaryTreeNode<E>) queue.poll();                        if(parentIndex*2+1 < treeList.size()){                            //左子树                            node.leftChild = treeList.get(parentIndex*2 + 1);                            queue.add(node.leftChild);                        }                        if(parentIndex*2+2 < treeList.size()){                            //右子树                            node.rightChild = treeList.get(parentIndex*2 + 2);                            queue.add(node.rightChild);                        }                    }else{                        return ;                    };                }            }                   }    }    /**     * 先序遍历创建二叉树,其中输入的‘#’代表空结点;     * 例如输入input.txt:- + a # # * # # / e # # f # #;     * @param inputFile     */    public void preOrderCreateBinaryTree(String inputFile){        Scanner scanner = null;        try{            scanner = new Scanner(inputFile);        }catch(Exception  e){            e.printStackTrace();        }        this.root = preOrderCreateBinaryTree(root, scanner);    }       public BinaryTreeNode<E> preOrderCreateBinaryTree(BinaryTreeNode<E> node, Scanner scanner){        String temp = scanner.next();        if(temp.trim().equals("#")){            return null;        }else{            node = new BinaryTreeNode<E>((E)temp);            node.setLeftChild(preOrderCreateBinaryTree(node.getLeftChild(), scanner));            node.setRightChild(preOrderCreateBinaryTree(node.getRightChild(), scanner));            return node;        }    }    /**     * 递推:知道第一个,推出下一个,直到达到目的。     * 递归:要知道第一个,需要先知道下一个,直到一个已知的,再反回来,得到上一个,直到第一个。     */    /**     * 递归求二叉树结点个数     * @param root     * @return 二叉树结点个数     */    public int getNodeNumber(BinaryTreeNode<E> root){        if(root == null){            return 0;        }else{            return getNodeNumber(root.leftChild) + getNodeNumber(root.rightChild) + 1;        }    }    /**     * 递归求二叉树的深度     * @param root     * @return 二叉树的深度     */    public int getDepth(BinaryTreeNode<E> root){        if(root == null){            return 0;        }else{            int depthLeft = getDepth(root.leftChild);   //左子树深度            int depthRight = getDepth(root.rightChild); //右子树深度            return depthLeft > depthRight ? (depthLeft+1) : (depthRight+1);        }    }    /**     * 递归求二叉树第k层的结点个数     * @param root     * @param k     * @return 第k层的结点个数     */    public int getKthLevelNodeNumber(BinaryTreeNode<E> root, int k){        if(root == null || k < 1){            return 0;        }        if(k == 1){            return 1;        }        int leftNumber = getKthLevelNodeNumber(root.leftChild, k-1);        int rightNumber = getKthLevelNodeNumber(root.rightChild,k-1);        return (leftNumber + rightNumber);    }    /**     * 递归求二叉树的叶子结点数     * @param root     * @return     */    public int getLeafNodeNumber(BinaryTreeNode<E> root){        if(root == null){            return 0;        }        if(root.leftChild == null && root.rightChild == null){            return 1;        }        int leftNumber = getLeafNodeNumber(root.leftChild);        int rightNumber = getLeafNodeNumber(root.rightChild);        return (leftNumber + rightNumber);    }    /**     * 判定两个二叉树结构是否相同     * 递归解法:     * (1)如果两棵二叉树都为空,返回真     * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假     * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假     * @param root1     * @param root2     * @return 结构相同时,返回true;     */    public boolean strutureComp(BinaryTreeNode<E> root1, BinaryTreeNode<E> root2){        if(root1 == null && root2 == null){            return true;        }else if(root1 == null || root2 == null){            return false;        }        boolean leftResult = strutureComp(root1.leftChild, root2.leftChild);        boolean rightResult = strutureComp(root1.rightChild, root2.rightChild);        return (leftResult && rightResult);    }    /**     * 递归插入结点     * @param root     * @param element     * @return 二叉树     */    public BinaryTreeNode<E> insert(BinaryTreeNode<E> root, E element){        BinaryTreeNode<E> pointer = new BinaryTreeNode<E>(element);        if(root == null){            root = pointer;        }else if(root.leftChild == null){            root.leftChild = insert(root.leftChild, element);        }else if(root.rightChild == null){            root.rightChild = insert(root.rightChild, element);        }        return root;    }    /**     * 求二叉树中特定子结点的父结点     * @param root     * @param childNode     * @return 存在父结点时,返回父结点;否则,返回null     */    public BinaryTreeNode<E> getParent(BinaryTreeNode<E> root, BinaryTreeNode<E> childNode){        if(root == null){            return null;        }        if(root.leftChild == childNode || root.rightChild == childNode){            return root;        }        if(getParent(root.leftChild, childNode) != null){            return getParent(root.leftChild, childNode);        }else{            return getParent(root.rightChild, childNode);        }    }    /**     * 递归删除二叉树,释放相应的存储空间     * @param root     */    public void destoryBinaryTree(BinaryTreeNode<E> root){        if(root != null){            destoryBinaryTree(root.leftChild);            destoryBinaryTree(root.rightChild);            root = null;        }    }    /**     * 层序遍历(广度优先遍历)     * @param root     */    public void levelOrder(BinaryTreeNode<E> root){        Queue<BinaryTreeNode<E>> queue = new LinkedBlockingQueue<BinaryTreeNode<E>>();        BinaryTreeNode<E> pointer = root;        /**         * 当前结点非空时,放入队首         */        if(pointer != null){            queue.add(pointer);        }         /*         * 队列不为空时,先访问中间节点,访问完成后弹出队首节点;然后是左节点,再是右节点;         */        while(!queue.isEmpty()){            pointer = queue.peek();               visit(pointer);            queue.remove();            if(pointer.leftChild != null){                queue.add(pointer);            }            if(pointer.rightChild != null){                queue.add(pointer);            }        }    }    /**     * 递归先序遍历二叉树     * @param root     */    public void preOrder(BinaryTreeNode<E> root){        if (root == null){            return;        }                      visit(root);        preOrder(root.leftChild);        preOrder(root.rightChild);    }    /**     * 非递归先序遍历二叉树     * @param root     */    public void nPreOrder(BinaryTreeNode<E> root){        Stack<BinaryTreeNode<E>> stack = new Stack<BinaryTreeNode<E>>();        BinaryTreeNode<E> pointer = root;        while(!stack.isEmpty() || pointer != null){            if(pointer != null){                visit(pointer);                if(pointer.rightChild != null){                    stack.push(pointer.rightChild);                }                pointer = pointer.leftChild;            }else{                pointer = stack.pop();            }        }    }    /**     * 递归中序遍历     * @param root     */    public void inOrder(BinaryTreeNode<E> root){        if (root == null){            return;        }           inOrder(root.leftChild);        visit(root);        inOrder(root.rightChild);    }    /**     * 非递归中序遍历1     * @param root     */    public void nInOrder(BinaryTreeNode<E> root){        Stack<BinaryTreeNode<E>> stack = new Stack<BinaryTreeNode<E>>();        BinaryTreeNode<E> pointer = root;        while(pointer != null || !stack.isEmpty()){            if(pointer != null){                stack.push(pointer);                pointer = pointer.leftChild;            }else{                pointer = stack.pop();                visit(pointer);                pointer = pointer.rightChild;                           }        }    }    /**     * 非递归中序遍历2     * @param root     */    public void nInOrders(BinaryTreeNode<E> root){        Stack<BinaryTreeNode<E>> stack = new Stack<BinaryTreeNode<E>>();        BinaryTreeNode<E> pointer = root;        stack.push(pointer);        while(!stack.isEmpty()){            while(pointer != null){                stack.push(pointer.leftChild);                pointer = pointer.leftChild;            }            stack.pop();            if(!stack.isEmpty()){                pointer = stack.pop();                visit(pointer);                pointer = pointer.rightChild;                stack.push(pointer);            }        }    }    /**     * 递归后序遍历     * @param root     */    public void postOrder(BinaryTreeNode<E> root){        if (root == null){            return;        }           postOrder(root.leftChild);        postOrder(root.rightChild);        visit(root);    }    /**     * 非递归后序遍历     * @param root     */    public void nPostOrder(BinaryTreeNode<E> root){        Stack<BinaryTreeNode<E>> stack = new Stack<BinaryTreeNode<E>>(); //初始化栈,用于保存带访问的节点        BinaryTreeNode<E> pointer = root;                                //保存根节点        BinaryTreeNode<E> preNode = root;                                //保存前一个被访问的节点        while(!stack.isEmpty() || pointer != null){            //若当前节点不空,就一直进栈,然后继续向左走            while(pointer.leftChild != null){                stack.push(pointer);                pointer = pointer.leftChild;            }             /*             * 当前节点为空时,分两种情况:             * 1、当前节点移动到栈顶处,然后访问栈顶元素的右节点             * 2、当前节点移动到栈顶,但是栈顶元素没有右节点,这就需要弹出栈顶元素,再对此元素访问;             * 然后再对新的栈顶元素进行判断即可             */            while((pointer != null && pointer.rightChild == null) || pointer.rightChild == preNode){                visit(pointer);                preNode = pointer;                if(stack.isEmpty()){                    return;                }                pointer = stack.pop();            }            stack.push(pointer);            pointer = pointer.rightChild;        }    }    /**     * 访问当前结点     * @param current     */    public void visit(BinaryTreeNode<E> current){        if(current != null && current.element != null){            System.out.println(current.element);        }else{            System.out.println("null");        }    }}

3. 参考文献

1. java创建二叉树并递归遍历二叉树
2. java实现二叉树相关代码—–数据结构
3. Java实现二叉树的创建、递归/非递归遍历
4. Java实现二叉树的创建和遍历操作(有更新)

0 0