二叉树基础操作和遍历

package tree;

import java.util.ArrayDeque;

import java.util.Deque;


public class BinaryTree {

private BinaryTreeNodemRoot;

    public BinaryTree() {

}

public BinaryTree(BinaryTreeNode root) {

mRoot = root;

    }

public BinaryTreeNodegetRoot() {

return mRoot;

    }

public void setRoot(BinaryTreeNode root) {

mRoot = root;

    }

public void insertAsLeftChild(BinaryTreeNode child) {

checkTreeEmpty();

        mRoot.setLeftNode(child);

    }

public void insertAsRightChild(BinaryTreeNode child) {

checkTreeEmpty();

        mRoot.setRightNode(child);

    }

private void checkTreeEmpty() {

if (mRoot ==null) {

throw new IllegalStateException("Can't insert to a null tree! Did you forget set value for root?");

        }

}

/**

    * 删除某个节点的二叉树

    *

    * @param node

    */

    public void deleteNode(BinaryTreeNode node) {

checkTreeEmpty();

        if (node ==null) {

return;

        }

deleteNode(node.getLeftNode());

        deleteNode(node.getRightNode());

        node =null;

    }

/**

    * 清空二叉树

    */

    public void clear() {

if (mRoot !=null) {

deleteNode(mRoot);

        }

}

/**

    * 获取二叉树高度

    */

    public int getTreeHeight() {

return getHeight(mRoot);

    }

private int getHeight(BinaryTreeNode node) {

if (node ==null) {

return 0;

        }

int leftHeight = getHeight(node.getLeftNode());

        int rightHeight = getHeight(node.getRightNode());

        int max = Math.max(leftHeight, rightHeight);

        // 加上自己的根节点

        return max +1;

    }

/**

    * 二叉树长度

    *

    * @return

    */

    public int size() {

return getSize(mRoot);

    }

private int getSize(BinaryTreeNode node) {

if (node ==null) {

return 0;

        }

int leftSize = getSize(node.getLeftNode());

        int rightSize = getSize(node.getRightNode());

        // 根节点的数量

        return leftSize + rightSize +1;

    }

/**

    * 获取当前节点的父节点

    * 遍历所有节点,判断该节点的左右节点是否与该节点相同

    *

    * @param node

    * @return

    */

    public BinaryTreeNodegetParentNode(BinaryTreeNode node) {

if (mRoot ==null || node.equals(mRoot)) {

return null;

        }else {

return getParent(mRoot, node);

        }

}

private BinaryTreeNodegetParent(BinaryTreeNode subTree, BinaryTreeNode node) {

if (subTree ==null) {

return null;

        }

if (subTree.getLeftNode().equals(node) || subTree.getRightNode().equals(node)) {

return subTree;

        }else {

BinaryTreeNode parent = getParent(subTree.getLeftNode(), node);

            if (parent !=null) {

return parent;

            }else {

return getParent(subTree.getRightNode(), node);

            }

}

}

/**

    * 二叉树遍历

    */

/**

    * 先序遍历, 优先遍历根节点,然后左节点 + 右节点

    * 中序遍历, 优先遍历左节点,然后根节点 + 右节点

    * 后序遍历, 优先遍历左节点,然后右节点 + 根节点

    *

    * @param node

    */

    public void interateFirstOrder(BinaryTreeNode node) {

if (node ==null) {

return;

        }

print(node);

        insertAsLeftChild(node.getLeftNode());

        insertAsLeftChild(node.getRightNode());

    }

/**

    * 输出节点值

    *

    * @param node

    */

    private void print(BinaryTreeNode node) {

if (node ==null) {

return;

        }

System.out.println(node.getData());

    }

/**

    * 创建一棵二叉树

    *

    * @return 根节点

    * @author bin.zhang

*/

    public static BinaryTreeNodecreateBinTree() {

BinaryTreeNode R3 =new BinaryTreeNode<>("F", null, null);

        BinaryTreeNode L2 =new BinaryTreeNode<>("D", null, null);

        BinaryTreeNode R2 =new BinaryTreeNode<>("E", null, R3);

        BinaryTreeNode L1 =new BinaryTreeNode<>("B", L2, R2);

        BinaryTreeNode R1 =new BinaryTreeNode<>("C", null, null);

        BinaryTreeNode T =new BinaryTreeNode<>("A", L1, R1);

        return T;

    }

/**

    * 先序遍历

    * 利用栈的特性

    */

    public static void preOrder(){

BinaryTreeNode p =createBinTree();

        // 初始化栈

        Deque stack =new ArrayDeque<>();

        while (p !=null || !stack.isEmpty()) {

// 如果当前节点不为空,则输出节点的值,因为当前节点都被当作了左节点

            if (p !=null) {

System.out.print(p.getData());

                // 为啥需要添加到栈中?

                stack.push(p);

                p = p.getLeftNode();

            }

// 如果当前节点为空,则意味着左节点遍历完成,需要将之前塞入栈中的节点拿出,遍历其右边节点

            // 将右边节点当作根节点继续遍历

            else {

p = stack.pop();

                p = p.getRightNode();

            }

}

System.out.println();

    }

/**

    * 中序遍历

    */

    public static void mediaOrder(){

BinaryTreeNode p =createBinTree();

        // 初始化栈

        Deque stack =new ArrayDeque<>();

        while (p !=null || !stack.isEmpty()) {

// 先遍历到最后一个左节点,将之前的节点存入栈中

            if (p !=null){

stack.push(p);

                p = p.getLeftNode();

            }else{

// 遍历到null以后,将栈中第一个节点输出,即为左子树中最后一个左节点也是根节点

                // 再以同样的方式遍历右节点

                p = stack.pop();

                System.out.print(p.getData());

                p = p.getRightNode();

            }

}

System.out.println();

    }

/**

    * 后序遍历

    * 通过循环入栈,出栈;相当于利用了递归的思想

    *  第一个栈 入栈时按照 根 左/右 的方式,将所有元素按照排序方式入栈

    *  第二个栈 入栈时按照 根 右/左 的方式

    *  第二个栈 出栈时即为 左/右/根 ,即为最终的结果

    */

    public static void posOrderUnRecur1(){

BinaryTreeNode p =createBinTree();

        System.out.print("PosOrder:");

        if(p !=null){

Deque s1 =new ArrayDeque<>();

            Deque s2 =new ArrayDeque<>();

            s1.push(p);

            while(!s1.isEmpty()){

p = s1.pop();

                s2.push(p);

                if(p.getLeftNode() !=null){

s1.push(p.getLeftNode());

                }

if(p.getRightNode() !=null){

s1.push(p.getRightNode());

                }

}

while(!s2.isEmpty()){

System.out.print(s2.pop().getData() +" ");

            }

}

System.out.println();

    }

public static void posOrderUnRecur2() {

BinaryTreeNode p =createBinTree();

        System.out.print("PosOrder:");

        if (p !=null) {

Deque stack =new ArrayDeque<>();

            stack.push(p);

            // 已输出的节点,判断该节点的父节点是

            BinaryTreeNode crrNode = p;

            while (!stack.isEmpty()){

BinaryTreeNode node = stack.peek();

                // 判断该节点的下的值是否被输出过,如果都没有,则塞入栈中待处理

                // 处理左节点,则需要确认上一个输出的节点是否为其左右节点

                // 如果是右节点,则证明已经处理过左节点;如果是左节点,则说明已经处理过,当前节点可以输出了

                if (node.getLeftNode() !=null && crrNode != node.getLeftNode() && crrNode != node.getRightNode()){

stack.push(node.getLeftNode());

                // 处理右节点,只需要证明上次处理的是否为当前节点

                }else if (node.getRightNode() !=null && crrNode != node.getRightNode()){

stack.push(node.getRightNode());

                }else{

BinaryTreeNode pop = stack.pop();

                    System.out.print(pop.getData());

                    crrNode = pop;

                }

}

}

System.out.println();

    }

public static void main(String[] args) {

preOrder();

        mediaOrder();

        posOrderUnRecur1();

        posOrderUnRecur2();

    }

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 1.HashMap是一个数组+链表/红黑树的结构,数组的下标在HashMap中称为Bucket值,每个数组项对应的...
    谁在烽烟彼岸阅读 1,007评论 2 2
  • 实验三 二叉树遍历(递归算法和非递归算法) 一.实验目的 1.掌握二叉树的存储结构与基本操作 2.掌握二叉树的遍历...
    落幕12阅读 966评论 0 1
  • 二叉树:每个节点最多有两个孩子,是一种动态数据结构,具有递归结构。 其中空树和只有根节点的树都是二叉树。 满二叉树...
    代夫阿普曼阅读 350评论 0 4
  • 自由 文/冰百合 最初每天早上 在病房的窗外 鸣叫的那只小鸟 忽然就没有了影踪 秋天往纵深处扩展 是不是这里...
    冰百合阅读 255评论 0 0
  • 从美食导入,聊到牙齿,大家都喜欢洁白整齐的牙齿。 出示牙齿,你想到什么? 拔牙 牙龈 补牙 乳牙 老师说假牙的故事...
    tongzi915阅读 124评论 0 0