Java数据结构与排序算法 (二)

416 阅读22分钟

回顾

前面学习了一些数据结构,根据其实现方式,这些数据结构可以划分为两种类型:基于数组的实现与基于链表的实现。

正如我们已经看到的,就其效率而言,这两种实现方式各有长短

具体来说,基于数组实现的结构允许我们通过下标或秩,在常数的时间内找到目标对象,并读取或更新其内容。然而,一旦需要对这类结构进行修改,那么无论是插入还是删除,都需要耗费线性的时间。

反过来,基于链表实现的结构允许我们借助引用或位置对象,在常数的时间内插入或删除元素;但是为了找出居于特定次序的元素,我们不得不花费线性的时间对整个结构进行遍历查找。

能否将这两类结构的优点结合起来,并回避其不足呢?接下来将要介绍的结构,将正面回答这一问题。

线性结构(Linear structures)、非线性结构(Non-linear structures )、半线性结构(Semi-linear structures)。

“树的某一元素是另一元 素‘直接上邻’”,也可以说“某一元素是另一元素的‘直接下邻’之一”。

术语

节点(Node)的深度、树的深度depth(v)与高度、树根(Root)、父 亲(Parent)、孩子(Child)、树边(Edge)、“兄弟” (Sibling)、“度”(Degree)、“内部节点”(Internal node)、“外部节点”(External node)、“叶子”(Leaf)、路径(Path)、“祖先”(Ancestor)、“后代”(Descendent)、子树(Subtree)、“空树”(Empty tree)、共同祖先(Common ancestor)、最低共同祖先(Lowerest common ancestor)、“有 序树(Ordered tree)”、二叉树(Binary tree)、真二叉树(Proper bina ry tree )、非真二叉树 (Improper binary tree)、完全二叉树(Complete binary tree)

/*
> 节点的深度、树的深度与高度

定义.1 在树结构中,
b 每个节点的深度都是一个非负整数;
c 深度为 0 的节点有且仅有一个,称作树根(Root);
d 对于深度为 k (k≥1)的每个节点 u,都有且仅有一个深度为 k-1 的节点 v 与之对应,称作 u 的父亲(Parent)或父节点。

定义.2 若节点 v 是节点 u 的父亲,则 u 称作 v 的孩子(Child),并在二者之间建立一条树边(Edge)。

定义.3 树中所有节点的最大深度,称作树的深度或高度。

观察结论.1 树中节点的数目,总是等于边数加一。

> 度、内部节点与外部节点

定义.4 任一节点的孩子数目,称作它的“度”(Degree)。

定义.5 至少拥有一个孩子的节点称作“内部节点”(Internal node);没有任何孩子的节点则称作“外部节点”(External node)或“叶子”(Leaf)。

定义.6 由树中 k+1 节点通过树边首尾衔接而构成的序列{ (v0, v1), (v1, v2), …, (vk-1, vk) | k ≥ 0},称作树中长度为 k 的一条路径(Path)。

观察结论.2 树中任何两个节点之间都存在唯一的一条路径。

观察结论.3 若 v 是 u 的父亲,则 depth(v) + 1 = depth(u)。

推论.1 从树根通往任一节点的路径长度,恰好等于该节点的深度。

> 祖先、后代、子树和节点的高度

定义.7
0. 每个节点都是自己的“祖先”(Ancestor),也是自己的“后代”(Descendent);
1. 若 v 是 u 的父节点的祖先,则 v 也是 u 的祖先;
2. 若 u 的父节点是 v 的后代,则 u 也是 v 的后代。

定义.8 除节点本身以外的祖先(后代),称作真祖先(后代)。

观察结论.4 任一节点 v 的深度,等于其真祖先的数目。

观察结论.5 任一节点 v 的祖先,在每一深度上最多只有一个。

定义.9 树 T 中每一节点 v 的所有后代也构成一棵树,称作 T 的“以 v 为根的子树(Subtree)”。

定义.10 若子树 v 的深度(高度)为 h,则称 v 的高度为 h,记作 height(v) = h。

观察结论.6 对于叶子节点 u 的任何祖先 v,必有 depth(v) + height(v) ≥ depth(u)。

> 共同祖先及最低共同祖先

定义.11 在树 T 中,若节点 u 和 v 都是节点 a 的后代,则称节点 a 为节点 u 和 v 的共同祖先(Commonancestor)。

定义.11 在树 T 中,若节点 u 和 v 都是节点 a 的后代,则称节点 a 为节点 u 和 v 的共同祖先(Commonancestor)。

观察结论.7 每一对节点至少存在一个共同祖先。

定义.12 在一对节点 u 和 v 的所有共同祖先中,深度最大者称为它们的最低共同祖先(Lowerestcommon ancestor),记作 lca(u, v)。

观察结论.8 每一对节点的最低共同祖先必存在且唯一。

> 有序树、m 叉树

定义.13 在树 T 中,若在每个节点的所有孩子之间都可以定义某一线性次序,则称 T 为一棵“有序树(Ordered tree)”。

定义.14 每个内部节点均为 m 度的有序树,称作 m 叉树。

二叉树>

定义.15 每个节点均不超过 2 度的有序树,称作二叉树(Binary tree)。

定义.16 不含 1 度节点的二叉树,称作真二叉树(Proper bina ry tree ),否则称作非真二叉树(Improper binary tree)。

观察结论.9 在二叉树中,深度为 k 的节点不超过 2k 个。

推论.2 高度为 h 的二叉树最多包含 2h+1-1 个节点。

推论.3 由 n 个节点构成的二叉树,高度至少为⎣log2n⎦。

观察结论.10 在二叉树中,叶子总是比 2 度节点多一个。

> 满二叉树与完全二叉树

定义.17 若二叉树 T 中所有叶子的深度完全相同,则称之为满二叉树(Full binary tree)。

观察结论.11 高度为 h 的二叉树是满的,当且仅当它拥有 2h匹叶子、2h+1-1 个节点。

定义.18 若在一棵满二叉树中,从最右侧起将相邻的若干匹叶子节点摘除掉,则得到的二叉树称作完全二叉树(Complete binary tree)。

引理.1 由 n 个节点构成的完全二叉树,高度 h = ⎣log2n⎦。

推论.4 在由固定数目的节点所组成的所有二叉树中,完全二叉树的高度最低。

> 树的基本算法
getSize()⎯⎯统计(子)树的规模

观察结论四.12 一棵树的规模,等于根节点下所有子树规模之和再加一,也等于根节点的后代总数。

getHeight()⎯⎯计算节点的高度

推论四.5 c 若 u 是 v 的孩子,则 height(v) ≥ height(u) + 1;
 d height(v) = 1 + max height(u)。
                    u是v的孩子

推论四.6 若 u 是 v 的孩子,则 depth(u) = depth(v) + 1。

定理四.1 树的前序、后序及层次遍历,均可在 O(n)时间内完成,其中 n 为树本身的规模。
*/

树抽象数据类型及其实现

public interface Tree {

    /**
     * @return 当前节点中存放的对象
     */
    Object getElem();

    /**
     * 将对象obj存入当前节点,并返回此前的内容
     *
     * @param obj
     * @return
     */
    Object setElem(Object obj);

    /**
     * @return 当前节点的父节点
     */
    TreeLinkedList getParent();

    /**
     * @return 当前节点的长子
     */
    TreeLinkedList getFirstChild();

    /**
     * @return 当前节点的最大弟弟
     */
    TreeLinkedList getNextSibling();

    /**
     * @return 当前节点后代元素的数目,即以当前节点为根的子树的规模
     */
    int getSize();

    /**
     * @return 当前节点的高度
     */
    int getHeight();

    /**
     * @return 当前节点的深度
     */
    int getDepth();
}

基于链表实现树

public class TreeLinkedList implements Tree {

    /**
     * 树根节点
     */
    private Object element;
    /**
     * 父亲、长子及最大的弟弟
     */
    private TreeLinkedList parent, firstChild, nextSibling;


    /**
     * (单节点树)构造方法
     */
    public TreeLinkedList() {
        this(null, null, null, null);
    }

    /**
     * 构造方法
     * @param e
     * @param p
     * @param c
     * @param s
     */
    public TreeLinkedList(Object e, TreeLinkedList p, TreeLinkedList c, TreeLinkedList s) {
        element = e;
        parent = p;
        firstChild = c;
        nextSibling = s;
    }

    /*---------- Tree接口中各方法的实现 ----------*/

    /**
     * 返回当前节点中存放的对象
     *
     * @return
     */
    @Override
    public Object getElem() {
        return element;
    }

    //

    /**
     * 将对象obj存入当前节点,并返回此前的内容
     *
     * @param obj
     * @return
     */
    @Override
    public Object setElem(Object obj) {
        Object bak = element;
        element = obj;
        return bak;
    }

    /**
     * 返回当前节点的父节点;对于根节点,返回null
     *
     * @return
     */
    @Override
    public TreeLinkedList getParent() {
        return parent;
    }

    /**
     * 返回当前节点的长子;若没有孩子,则返回null
     *
     * @return
     */
    @Override
    public TreeLinkedList getFirstChild() {
        return firstChild;
    }

    /**
     * 返回当前节点的最大弟弟;若没有弟弟,则返回null
     *
     * @return
     */
    @Override
    public TreeLinkedList getNextSibling() {
        return nextSibling;
    }


    /**
     * 返回当前节点后代元素的数目,即以当前节点为根的子树的规模
     *
     * @return
     */
    @Override
    public int getSize() {
        /**
         * 当前节点也是自己的后代
         */
        int size = 1;
        /**
         * 从长子开始
         */
        TreeLinkedList subtree = firstChild;

        /**依次
         *
         */
        while (null != subtree) {
            /**
             * 累加
             */
            size += subtree.getSize();
            /**
             * 所有孩子的后代数目
             */
            subtree = subtree.getNextSibling();
        }
        /**
         * 即可得到当前节点的后代总数
         */
        return size;
    }

    /**
     * 返回当前节点的高度
     *
     * @return
     */
    @Override
    public int getHeight() {
        int height = -1;
        /**
         * 从长子开始
         */
        TreeLinkedList subtree = firstChild;
        /**
         * 依次
         */
        while (null != subtree) {
            /**
             * 在所有孩子中取最大高度
             */
            height = Math.max(height, subtree.getHeight());
            subtree = subtree.getNextSibling();
        }
        /**
         * 即可得到当前节点的高度
         */
        return height + 1;
    }

    /**
     * 返回当前节点的深度
     * @return
     */
    @Override
    public int getDepth() {
        int depth = 0;
        /**
         * 从父亲开始
         */
        TreeLinkedList p = parent;
        /**
         * 依次
         */
        while (null != p) {
            depth++;
            /**访问各个真祖先
             * 
             */
            p = p.getParent();
        }
        /**
         * 真祖先的数目,即为当前节点的深度
         */
        return depth;
    }
}

前序、后序遍历

所谓树的遍历(Traversal),就是按照某种次序访问树中的节点,且每个节点恰好访问一次。 也就是说,按照被访问的次序,可以得到由树中所有节点排成的一个序列。 两种最基本的树遍历算法⎯⎯前序遍历(PreorderTraversal)后序遍历(Postorder traversal)。这两种遍历算法都是递归定义的,只是其中对“次序”的定义略有 不同。

PreorderTraversal

        if (null != v) {
            for (u = v.getFirstChild(); null != u; u = u.getNextSibling())
                PreorderTraversal(u);
        }

LevelorderTraversal

        if (null != v) {
            Q.enqueue(v);
            while (!Q.isEmpty()) {
                u = Q.dequeue();
                for (w = u.getFirstChild(); null != w; w = w.nextSibling())
                    Q.enqueue(w);
            }
        }

树迭代器

public class IteratorTree implements Iterator {
    /**
     * 列表
     */
    private List list;
    /**
     * 当前(下一个)元素的位置
     */
    private Position nextPosition;


    /**
     * 默认构造方法
     */
    public IteratorTree() {
        list = null;
    }

    /**
     * 前序遍历
     *
     * @param T
     */
    public void elementsPreorderIterator(TreeLinkedList T) {
        if (null == T) {
            //递归基
            return;
        }
        //首先输出当前节点
        list.insertLast(T);
        //从当前节点的长子开始
        TreeLinkedList subtree = T.getFirstChild();
        //依次对当前节点的各个孩子
        while (null != subtree) {
            //做前序遍历
            this.elementsPreorderIterator(subtree);
            subtree = subtree.getNextSibling();
        }
    }

    /**
     * 后序遍历
     *
     * @param T
     */
    public void elementsPostorderIterator(TreeLinkedList T) {
        if (null == T) {
            //递归基
            return;
        }
        //从当前节点的长子开始
        TreeLinkedList subtree = T.getFirstChild();
        //依次对当前节点的各个孩子
        while (null != subtree) {
            //做后序遍历
            this.elementsPostorderIterator(subtree);
            subtree = subtree.getNextSibling();
        }
        //当所有后代都访问过后,最后才访问当前节点
        list.insertLast(T);
    }

    /**
     * 层次遍历
     *
     * @param T
     */
    public void levelTraversalIterator(TreeLinkedList T) {
        if (null == T) {
            return;
        }
        //空队
        QueueList Q = new QueueList();
        //根节点入队
        Q.enqueue(T);
        //在队列重新变空之前
        while (!Q.isEmpty()) {
            //取出队列首节点
            TreeLinkedList tree = (TreeLinkedList) (Q.dequeue());
            //将新出队的节点接入迭代器中
            list.insertLast(tree);
            //从tree的第一个孩子起
            TreeLinkedList subtree = tree.getFirstChild();
            //依次找出所有孩子,并
            while (null != subtree) {
                //将其加至队列中
                Q.enqueue(subtree);
                subtree = subtree.getNextSibling();
            }
        }
    }

    /**
     * 检查迭代器中是否还有剩余的元素
     *
     * @return
     */
    @Override
    public boolean hasNext() {
        return (null != nextPosition);
    }

    /**
     * 返回迭代器中的下一元素
     *
     * @return
     * @throws ExceptionNoSuchElement
     */
    @Override
    public Object getNext() throws ExceptionNoSuchElement {
        if (!hasNext()) {
            throw new ExceptionNoSuchElement("No next position");
        }
        Position currentPosition = nextPosition;
        if (currentPosition == list.last()) {//若已到达尾元素,则
            //不再有下一元素
            nextPosition = null;
        } else {//转向下一元素
            //否则
            nextPosition = list.getNext(currentPosition);
        }
        return currentPosition.getElem();
    }
} 

二叉树

二叉树类的 Java 接口

/**
 * <b>Description:</b> 二叉树接口 <br>
 */
public interface BinTree {

    /**
     * 返回树根
     *
     * @return
     */
    public BinTreePosition getRoot();

    /**
     * 判断是否树空
     *
     * @return
     */
    public boolean isEmpty();

    /**
     * 返回树的规模(即树根的后代数目)
     *
     * @return
     */
    public int getSize();

    /**
     * 返回树(根)的高度
     *
     * @return
     */
    public int getHeight();

    /**
     * 前序遍历
     *
     * @return
     */
    public Iterator elementsPreorder();

    /**
     * 中序遍历
     *
     * @return
     */
    public Iterator elementsInorder();

    /**
     * 后序遍历
     *
     * @return
     */
    public Iterator elementsPostorder();

    /**
     * 层次遍历
     *
     * @return
     */
    public Iterator elementsLevelorder();
}

二叉树节点ADT接口

为了在遵循面向对象规范的同时保证效率,这里也将使用位置的概念来描述和实现二叉树节点。

/**
 * <b>Description:</b> 二叉树节点ADT接口 <br>
 */
public interface BinTreePosition extends Position {

    /**
     * 判断是否有父亲(为使代码描述简洁)
     *
     * @return
     */
    public boolean hasParent();

    /**
     * 返回当前节点的父节点
     *
     * @return
     */
    public BinTreePosition getParent();

    /**
     * 设置当前节点的父节点
     *
     * @param p
     */
    public void setParent(BinTreePosition p);

    /**
     * 判断是否为叶子
     *
     * @return
     */
    public boolean isLeaf();

    /**
     * 判断是否为左孩子(为使代码描述简洁)
     *
     * @return
     */
    public boolean isLChild();

    /**
     * 判断是否有左孩子(为使代码描述简洁)
     *
     * @return
     */
    public boolean hasLChild();

    /**
     * 返回当前节点的左孩子
     *
     * @return
     */
    public BinTreePosition getLChild();

    /**
     * 设置当前节点的左孩子(注意:this.lChild和c.parent都不一定为空)
     *
     * @param c
     */
    public void setLChild(BinTreePosition c);

    /**
     * 判断是否为右孩子(为使代码描述简洁)
     *
     * @return
     */
    public boolean isRChild();

    /**
     * 判断是否有右孩子(为使代码描述简洁)
     *
     * @return
     */
    public boolean hasRChild();

    /**
     * 返回当前节点的右孩子
     *
     * @return
     */
    public BinTreePosition getRChild();

    /**
     * 设置当前节点的右孩子(注意:this.rChild和c.parent都不一定为空)
     *
     * @param c
     */
    public void setRChild(BinTreePosition c);

    /**
     * 返回当前节点后代元素的数目
     *
     * @return
     */
    public int getSize();

    /**
     * 在孩子发生变化后,更新当前节点及其祖先的规模
     */
    public void updateSize();

    /**
     * 返回当前节点的高度
     *
     * @return
     */
    public int getHeight();

    /**
     * 在孩子发生变化后,更新当前节点及其祖先的高度
     */
    public void updateHeight();

    /**
     * 返回当前节点的深度
     *
     * @return
     */
    public int getDepth();

    /**
     * 在父亲发生变化后,更新当前节点及其后代的深度
     */
    public void updateDepth();

    /**
     * 按照中序遍历的次序,找到当前节点的直接前驱
     *
     * @return
     */
    public BinTreePosition getPrev();

    /**
     * 按照中序遍历的次序,找到当前节点的直接后继
     *
     * @return
     */
    public BinTreePosition getSucc();

    /**
     * 断绝当前节点与其父亲的父子关系 返回当前节点
     *
     * @return
     */
    public BinTreePosition secede();

    /**
     * 将节点c作为当前节点的左孩子
     *
     * @param c
     * @return
     */
    public BinTreePosition attachL(BinTreePosition c);

    /**
     * 将节点c作为当前节点的右孩子
     *
     * @param c
     * @return
     */
    public BinTreePosition attachR(BinTreePosition c);

    /**
     * 前序遍历
     *
     * @return
     */
    public Iterator elementsPreorder();

    /**
     * 中序遍历
     *
     * @return
     */
    public Iterator elementsInorder();

    /**
     * 后序遍历
     *
     * @return
     */
    public Iterator elementsPostorder();

    /**
     * 层次遍历
     *
     * @return
     */
    public Iterator elementsLevelorder();
}

基于链表节点实现二叉树节点

/**
 * <b>Description:</b> 基于链表节点实现二叉树节点 <br>
 */
public class BinTreeNode implements BinTreePosition {
    /**
     * 该节点中存放的对象
     */
    protected Object element;
    /**
     * 父亲
     */
    protected BinTreePosition parent;
    /**
     * 左孩子
     */
    protected BinTreePosition lChild;
    /**
     * 右孩子
     */
    protected BinTreePosition rChild;
    /**
     * 后代数目
     */
    protected int size;
    /**
     * 高度
     */
    protected int height;
    /**
     * 深度
     */
    protected int depth;


    /**************************** 构造方法 ****************************/
    public BinTreeNode() {
        this(null, null, true, null, null);
    }

    /**
     * @param e        节点内容
     * @param p        父节点
     * @param asLChild 是否作为父节点的左孩子
     * @param l        左孩子
     * @param r        右孩子
     */
    public BinTreeNode(Object e, BinTreePosition p, boolean asLChild, BinTreePosition l, BinTreePosition r) {
        size = 1;
        height = depth = 0;
        //初始化
        parent = lChild = rChild = null;
        //存放的对象 
        element = e;
        // 建立与父亲的关系
        if (null != p) {
            if (asLChild) {
                p.attachL(this);
            } else {
                p.attachR(this);
            }
        }
        //建立与孩子的关系
        if (null != l) {
            attachL(l);
        }
        if (null != r) {
            attachR(r);
        }
    }

    /**************************** Position接口方法 ********************************/
    /**
     * 返回当前节点中存放的对象
     *
     * @return
     */
    @Override
    public Object getElem() {
        return element;
    }

    /**
     * 将对象obj存入当前节点,并返回此前的内容
     *
     * @param obj
     * @return
     */
    @Override
    public Object setElem(Object obj) {
        Object bak = element;
        element = obj;
        return bak;
    }

    /**************************** BinTreePosition接口方法 *************************/
    /**
     * 判断是否有父亲(为使代码描述简洁)
     *
     * @return
     */
    @Override
    public boolean hasParent() {
        //返回当前节点的父节点
        return null != parent;
    }

    @Override
    public BinTreePosition getParent() {
        //设置当前节点的父节点
        return parent;
    }

    @Override
    public void setParent(BinTreePosition p) {
        parent = p;
    }

    /**
     * 判断是否为叶子
     *
     * @return
     */
    @Override
    public boolean isLeaf() {
        //判断是否为左孩子(为使代码描述简洁)
        return !hasLChild() && !hasRChild();
    }

    /**
     * 若当前节点有父亲,而且是左孩子,则返回true;否则,返回false
     *
     * @return
     */
    @Override
    public boolean isLChild() {
        return (hasParent() && this == getParent().getLChild()) ? true : false;
    }

    /**
     * 判断是否有左孩子(为使代码描述简洁)
     *
     * @return
     */
    @Override
    public boolean hasLChild() {
        return null != lChild;
    }

    /**
     * 返回当前节点的左孩子
     *
     * @return
     */
    @Override
    public BinTreePosition getLChild() {
        return lChild;
    }

    /**
     * 设置当前节点的左孩子(注意:this.lChild和c.parent都不一定为空)
     *
     * @param c
     */
    @Override
    public void setLChild(BinTreePosition c) {
        lChild = c;
    }

    /**
     * 判断是否为右孩子(为使代码描述简洁)
     *
     * @return 若当前节点有父亲,而且是右孩子,则返回true;否则,返回false
     */
    @Override
    public boolean isRChild() {
        return (hasParent() && this == getParent().getRChild()) ? true : false;
    }

    /**
     * 判断是否有右孩子(为使代码描述简洁)
     *
     * @return
     */
    @Override
    public boolean hasRChild() {
        return null != rChild;
    }

    /**
     * 返回当前节点的右孩子
     *
     * @return
     */
    @Override
    public BinTreePosition getRChild() {
        return rChild;
    }

    /**
     * 设置当前节点的右孩子(注意:this.rChild和c.parent都不一定为空)
     *
     * @param c
     */
    @Override
    public void setRChild(BinTreePosition c) {
        rChild = c;
    }

    /**
     * 返回当前节点后代元素的数目
     *
     * @return
     */
    @Override
    public int getSize() {
        return size;
    }

    /**
     * 在孩子发生变化后,更新当前节点及其祖先的规模
     */
    @Override
    public void updateSize() {
        //当前节点
        size = 1;
        if (hasLChild()) {
            //左子树的规模
            size += getLChild().getSize();
        }
        if (hasRChild()) {
            //右子树的规模
            size += getRChild().getSize();
        }

        if (hasParent()) {
            //递归更新各个真祖先的规模记录
            getParent().updateSize();
        }
    }

    /**
     * 返回当前节点的高度
     *
     * @return
     */
    @Override
    public int getHeight() {
        return height;
    }

    /**
     * 在孩子发生变化后,更新当前节点及其祖先的高度
     */
    @Override
    public void updateHeight() {
        //先假设没有左、右孩子
        height = 0;

        if (hasLChild()) {
            //左孩子
            height = Math.max(height, 1 + getLChild().getHeight());
        }
        if (hasRChild()) {
            //右孩子
            height = Math.max(height, 1 + getRChild().getHeight());
        }
        if (hasParent()) {
            //递归更新各个真祖先的高度记录
            getParent().updateHeight();
        }
    }

    /**
     * 返回当前节点的深度
     *
     * @return
     */
    @Override
    public int getDepth() {
        return depth;
    }

    /**
     * 在父亲发生变化后,更新当前节点及其后代的深度
     */
    @Override
    public void updateDepth() {
        //当前节点
        depth = hasParent() ? 1 + getParent().getDepth() : 0;

        if (hasLChild()) {
            //沿孩子引用逐层向下,
            getLChild().updateDepth();
        }
        if (hasRChild()) {
            //递归地更新所有后代的深度记录
            getRChild().updateDepth();
        }
    }

    /**
     * 按照中序遍历的次序,找到当前节点的直接前驱
     *
     * @return
     */
    @Override
    public BinTreePosition getPrev() {
        //若左子树非空,则其中的最大者即为当前节点的直接前驱
        if (hasLChild()) {
            return findMaxDescendant(getLChild());
        }
        //至此,当前节点没有左孩子
        if (isRChild()) {
            //若当前节点是右孩子,则父亲即为其直接前驱
            return getParent();
        }
        //至此,当前节点没有左孩子,而且是左孩子
        //从当前节点出发
        BinTreePosition v = this;
        while (v.isLChild()) {
            //沿左孩子链一直上升
            v = v.getParent();
        }
        //至此,v或者没有父亲,或者是父亲的右孩子
        return v.getParent();
    }

    /**
     * 按照中序遍历的次序,找到当前节点的直接后继
     *
     * @return
     */
    @Override
    public BinTreePosition getSucc() {
        //若右子树非空,则其中的最小者即为当前节点的直接后继
        if (hasRChild()) {
            return findMinDescendant(getRChild());
        }
        //至此,当前节点没有右孩子
        if (isLChild()) {
            //若当前节点是左孩子,则父亲即为其直接后继
            return getParent();
        }
        //至此,当前节点没有右孩子,而且是右孩子
        //从当前节点出发
        BinTreePosition v = this;
        while (v.isRChild()) {
            //沿右孩子链一直上升
            v = v.getParent();
        }
        //至此,v或者没有父亲,或者是父亲的左孩子
        return v.getParent();
    }

    /**
     * 断绝当前节点与其父亲的父子关系。
     * 将以某一节点为根的子树从母树中分离出来。
     *
     * @return 返回当前节点
     */
    @Override
    public BinTreePosition secede() {
        if (null != parent) {
            if (isLChild()) {
                //切断父亲指向当前节点的引用
                parent.setLChild(null);
            } else {
                parent.setRChild(null);
            }
            //更新当前节点及其祖先的规模
            parent.updateSize();
            //更新当前节点及其祖先的高度
            parent.updateHeight();
            //切断当前节点指向原父亲的引用
            parent = null;
            //更新节点及其后代节点的深度
            updateDepth();
        }
        //返回当前节点
        return this;
    }

    /**
     * 将节点c作为当前节点的左孩子
     *
     * @param c
     * @return
     */
    @Override
    public BinTreePosition attachL(BinTreePosition c) {
        if (hasLChild()) {
            //摘除当前节点原先的左孩子
            getLChild().secede();
        }
        if (null != c) {
            //c脱离原父亲
            c.secede();
            lChild = c;
            //确立新的父子关系
            c.setParent(this);
            //更新当前节点及其祖先的规模
            updateSize();
            //更新当前节点及其祖先的高度
            updateHeight();
            //更新c及其后代节点的深度
            c.updateDepth();
        }
        return this;
    }

    /**
     * 将节点c作为当前节点的右孩子
     *
     * @param c
     * @return
     */
    @Override
    public BinTreePosition attachR(BinTreePosition c) {
        if (hasRChild()) {
            //摘除当前节点原先的右孩子
            getRChild().secede();
        }
        if (null != c) {
            //c脱离原父亲
            c.secede();
            rChild = c;
            //确立新的父子关系
            c.setParent(this);
            //更新当前节点及其祖先的规模
            updateSize();
            //更新当前节点及其祖先的高度
            updateHeight();
            //更新c及其后代节点的深度
            c.updateDepth();
        }
        return this;
    }

    /**
     * 前序遍历
     *
     * @return
     */
    @Override
    public Iterator elementsPreorder() {
        List list = new ListDLNode();
        preorder(list, this);
        return list.elements();
    }

    /**
     * 中序遍历
     *
     * @return
     */
    @Override
    public Iterator elementsInorder() {
        List list = new ListDLNode();
        inorder(list, this);
        return list.elements();
    }

    /**
     * 后序遍历
     *
     * @return
     */
    @Override
    public Iterator elementsPostorder() {
        List list = new ListDLNode();
        postorder(list, this);
        return list.elements();
    }

    /**
     * 层次遍历
     *
     * @return
     */
    @Override
    public Iterator elementsLevelorder() {
        List list = new ListDLNode();
        levelorder(list, this);
        return list.elements();
    }

    /**************************** 辅助方法 ****************************/
    /**
     * 在v的后代中,找出最小者
     *
     * @param v
     * @return
     */
    protected static BinTreePosition findMinDescendant(BinTreePosition v) {
        if (null != v) {
            while (v.hasLChild()) {
                //从v出发,沿左孩子链一直下降
                v = v.getLChild();
            }
        }
        //至此,v或者为空,或者没有左孩子
        return v;
    }

    /**
     * 在v的后代中,找出最大者
     *
     * @param v
     * @return
     */
    protected static BinTreePosition findMaxDescendant(BinTreePosition v) {
        if (null != v) {
            while (v.hasRChild()) {
                //从v出发,沿右孩子链一直下降
                v = v.getRChild();
            }
        }
        //至此,v或者为空,或者没有右孩子
        return v;
    }

    /**
     * 前序遍历以v为根节的(子)树
     *
     * @param list
     * @param v
     */
    protected static void preorder(List list, BinTreePosition v) {

        if (null == v) {
            //递归基:空树
            return;
        }
        //访问v
        list.insertLast(v);
        //遍历左子树
        preorder(list, v.getLChild());
        //遍历右子树
        preorder(list, v.getRChild());
    }

    /**
     * 中序遍历以v为根节的(子)树
     *
     * @param list
     * @param v
     */
    protected static void inorder(List list, BinTreePosition v) {
        if (null == v) {
            //递归基:空树
            return;
        }
        //遍历左子树
        inorder(list, v.getLChild());
        //访问v
        list.insertLast(v);
        //遍历右子树
        inorder(list, v.getRChild());
    }

    /**
     * 后序遍历以v为根节的(子)树
     *
     * @param list
     * @param v
     */
    protected static void postorder(List list, BinTreePosition v) {
        if (null == v) {
            //递归基:空树
            return;
        }
        //遍历左子树
        postorder(list, v.getLChild());
        //遍历右子树
        postorder(list, v.getRChild());
        //访问v
        list.insertLast(v);
    }

    /**
     * 层次遍历以v为根节的(子)树
     *
     * @param list
     * @param v
     */
    protected static void levelorder(List list, BinTreePosition v) {
        //空队
        QueueList Q = new QueueList();
        //根节点入队
        Q.enqueue(v);
        while (!Q.isEmpty()) {
            //出队
            BinTreePosition u = (BinTreePosition) Q.dequeue();
            //访问v
            list.insertLast(u);
            if (u.hasLChild()) {
                Q.enqueue(u.getLChild());
            }
            if (u.hasRChild()) {
                Q.enqueue(u.getRChild());
            }
        }
    }
}

基于链表实现二叉树

/**
 * <b>Create Date:</b> 2018/9/25<br>
 * <b>Email:</b> 289286298@qq.com<br>
 * <b>Description:</b> 基于链表实现二叉树 <br>
 *
 * @author tongson
 */
public class BinTreeLinkedList implements BinTree {
    /**
     * 根节点
     */
    protected BinTreePosition root;

    /**************************** 构造函数 ****************************/
    public BinTreeLinkedList() {
        this(null);
    }

    public BinTreeLinkedList(BinTreePosition r) {
        root = r;
    }

    /**************************** BinaryTree接口方法 ****************************/
    /**
     * 返回树根
     *
     * @return
     */
    @Override
    public BinTreePosition getRoot() {
        return root;
    }

    /**
     * 判断是否树空
     *
     * @return
     */
    @Override
    public boolean isEmpty() {
        return null == root;
    }

    /**
     * 返回树的规模(即树根的后代数目)
     *
     * @return
     */
    @Override
    public int getSize() {
        return isEmpty() ? 0 : root.getSize();
    }

    /**
     * 返回树(根)的高度
     *
     * @return
     */
    @Override
    public int getHeight() {
        return isEmpty() ? -1 : root.getHeight();
    }

    /**
     * 前序遍历
     *
     * @return
     */
    @Override
    public Iterator elementsPreorder() {
        return root.elementsPreorder();
    }

    /**
     * 中序遍历
     *
     * @return
     */
    @Override
    public Iterator elementsInorder() {
        return root.elementsInorder();
    }

    /**
     * 后序遍历
     *
     * @return
     */
    @Override
    public Iterator elementsPostorder() {
        return root.elementsPostorder();
    }

    /**
     * 层次遍历
     *
     * @return
     */
    @Override
    public Iterator elementsLevelorder() {
        return root.elementsLevelorder();
    }
} 

完全二叉树

接口

/**
 * <b>Description:</b> 完全二叉树接口 <br>
 */
public interface ComplBinTree extends BinTree {
    /**
     * 生成并返回一个存放e的外部节点,该节点成为新的末节点
     *
     * @param e
     * @return
     */
    BinTreePosition addLast(Object e);

    /**
     * 删除末节点,并返回其中存放的内容
     *
     * @return
     */
    Object delLast();

    /**
     * 返回按照层次遍历编号为i的节点的位置,0 <= i < size()
     *
     * @param i
     * @return
     */
    BinTreePosition posOfNode(int i);
}

基于秩实现的完全二叉树节点

/**
 * <b>Description:</b> 基于秩实现的完全二叉树节点 <br>
 */
public class ComplBinTreeNodeRank extends BinTreeNode implements BinTreePosition {
    /**
     * 所属的树
     */
    private Vector T;
    /**
     * 在所属树中的秩
     */
    private int rank;
    /**
     * 存放的对象
     */
    private Object element;

    /**
     * 构造函数
     *
     * @param t
     * @param obj
     */
    public ComplBinTreeNodeRank(Vector t, Object obj) {
        element = obj;
        T = t;
        rank = T.getSize();
        T.insertAtRank(rank, this);
    }

    /**
     * 返回当前节点中存放的对象
     *
     * @return
     */
    @Override
    public Object getElem() {
        return element;
    }

    /**
     * 将对象obj存入当前节点,并返回此前的内容
     *
     * @param obj
     * @return
     */
    @Override
    public Object setElem(Object obj) {
        Object bak = element;
        element = obj;
        return bak;
    }

    /**
     * 判断是否有父亲(为使代码描述简洁)
     *
     * @return
     */
    @Override
    public boolean hasParent() {
        return (0 != rank) ? true : false;
    }

    /**
     * 返回当前节点的父节点
     *
     * @return
     */
    @Override
    public BinTreePosition getParent() {
        return hasParent() ? (BinTreePosition) T.getAtRank((rank - 1) / 2) : null;
    }

    /**
     * 判断是否有左孩子(为使代码描述简洁)
     *
     * @return
     */
    @Override
    public boolean hasLChild() {
        return (1 + rank * 2 < T.getSize()) ? true : false;
    }

    /**
     * 返回当前节点的左孩子
     *
     * @return
     */
    @Override
    public BinTreePosition getLChild() {
        return hasLChild() ? (BinTreePosition) (T.getAtRank(1 + rank * 2)) : null;
    }

    /**
     * 判断是否有右孩子(为使代码描述简洁)
     *
     * @return
     */
    @Override
    public boolean hasRChild() {
        return (2 + rank * 2 < T.getSize()) ? true : false;
    }

    /**
     * 返回当前节点的右孩子
     *
     * @return
     */
    @Override
    public BinTreePosition getRChild() {
        return hasRChild() ? (BinTreePosition) (T.getAtRank(2 + rank * 2)) : null;
    }

    /**
     * 返回当前节点后代元素的数目
     *
     * @return
     */
    @Override
    public int getSize() {
        int size = 1;
        if (hasLChild()) {
            size += getLChild().getSize();
        }
        if (hasRChild()) {
            size += getRChild().getSize();
        }
        return size;
    }

    /**
     * 返回当前节点的高度
     *
     * @return
     */
    @Override
    public int getHeight() {
        int hL = hasLChild() ? getLChild().getHeight() : -1;
        int hR = hasRChild() ? getRChild().getHeight() : -1;
        return 1 + Math.max(hL, hR);
    }

    /**
     * 返回当前节点的深度
     *
     * @return
     */
    @Override
    public int getDepth() {
        return hasParent() ? 1 + getParent().getDepth() : 0;
    }
}

基于向量的实现

/**
 * <b>Description:</b>  基于向量实现的完全二叉树 <br>
 */
public class ComplBinTreeVector extends BinTreeLinkedList implements ComplBinTree {
    /**
     * 向量
     */
    private Vector T;

    /**
     * 构造方法:默认的空树
     */
    public ComplBinTreeVector() {
        T = new VectorExtArray();
        root = null;
    }

    /**
     * 构造方法:按照给定的节点序列,批量式建立完全二叉树
     *
     * @param s
     */
    public ComplBinTreeVector(Sequence s) {
        this();
        if (null != s) {
            while (!s.isEmpty()) {
                addLast(s.removeFirst());
            }
        }
    }

    /*---------- BinaryTree接口中各方法的实现 ----------*/

    /**
     * 返回树根(重写)
     *
     * @return
     */
    @Override
    public BinTreePosition getRoot() {
        return T.isEmpty() ? null : posOfNode(0);
    }

    /**
     * 判断是否树空(重写)
     *
     * @return
     */
    @Override
    public boolean isEmpty() {
        return T.isEmpty();
    }

    /**
     * 返回树的规模(重写)
     *
     * @return
     */
    @Override
    public int getSize() {
        return T.getSize();
    }

    /**
     * 返回树(根)的高度(重写)
     *
     * @return
     */
    @Override
    public int getHeight() {
        return isEmpty() ? -1 : getRoot().getHeight();
    }

    /*---------- ComplBinTree接口中各方法的实现 ----------*/

    /**
     * 生成并返回一个存放e的外部节点,该节点成为新的末节点
     *
     * @param e
     * @return
     */
    @Override
    public BinTreePosition addLast(Object e) {
        BinTreePosition node = new ComplBinTreeNodeRank(T, e);
        root = (BinTreePosition) T.getAtRank(0);
        return node;
    }

    /**
     * 删除末节点,并返回其中存放的内容
     *
     * @return
     */
    @Override
    public Object delLast() {
        if (isEmpty()) {
            //若树(堆)已空,无法删除
            return null;
        }
        if (1 == getSize()) {
            //若删除最后一个节点,则树空
            root = null;
        }
        return T.removeAtRank(T.getSize() - 1);
    }

    /**
     * 返回按照层次遍历编号为i的节点的位置,0 <= i < size()
     *
     * @param i
     * @return
     */
    @Override
    public BinTreePosition posOfNode(int i) {
        return (BinTreePosition) T.getAtRank(i);
    }
}