跟小刀学习 数据结构二叉树的实现

  • 最近学习的有点累。导致二叉树学习的有点模糊
  • 我们之前学过数组 和链表 数组插入比较慢 链表查询比较慢。这时候我们就需要使用树这种结构。都比较快
  • 树的基本概念
  • :树最上面的节点称为根节点,一棵树只有一个根节点
  • 父节点:每一个节点都有一条边向上连接到另一个节点,这个节点就是称为下面这个节点的父节点
  • 子节点:每一个节点都有条向下连接的节点,下面的这个节点就是该节点的子节点
  • 叶子节点:没有子节点的节点也叫叶子节点.
  • 子树:每一个节点都可以作为一个子树的根。他和他的所有子节点组合在一起就是个子树
  • 查找节点:从根节点开始查找,如果查找的节点值比当前节点的值小,则继续查找左子树,否则查找右子树
  • 遍历树:遍历树是根据一个特定的顺序访问树的每一个节点,根据顺序的不同分为前序,中序,后序遍历三种。
  • 前序遍历。

    • (1)访问根节点
    • (2)前序遍历左子树
    • (3)前序遍历右子树
  • 中序遍历。

    • (1)中序遍历左子树
    • (2)访问根节点
    • (3)中序遍历右子树
  • 后序遍历。

    • (1)后序遍历左子树
    • (2)后序遍历右子树
    • (3)访问根节点

上代码:

/**
 * 二叉树的节点类
 * @author Administrator
 *
 */
public class Node {

    public int iData;

    public String sData;

    public Node leftChild;
    public Node rightChild;


    public Node(int iData,String sData) {
        this.iData = iData;
        this.sData =sData;
    }


    public Node() {
        // TODO Auto-generated constructor stub
    }


    public void dispalyNode(){
        System.out.print("{"+ iData +"}");
    }

}

二叉树的具体实现

package com.chapter5_1;

public class Tree {

    //根节点
    public Node root;

    /**
     * 二叉树的插入 s
     */
    public void insert(int d,String s){
        //新节点
        Node newNode = new Node(d,s);
        //引用当前的节点
        Node current = root;
        //引用父节点
        Node parent;

        if(current == null){
            root = newNode;
            return ;//如果root节点为空的话,直接点添加都结束了
        }  


        while(true){
            //先将当前的节点付给一个parent. 这个节点一直在变动
            parent = current;

            if(d < current.iData){
                //当前的节点变成刚才的左节点
                current = current.leftChild;
                if(current == null){
                    parent.leftChild =newNode;
                    return;
                }
            }else{//d > 

//              变成刚才的又节点
                current = current.rightChild;

                if(current == null){
                    parent.rightChild= newNode;
                    return;
                }

            }
        }
    }

    /**
     * 查找二叉树
     * @param value
     * @return
     */
    public Node find(int value){
        Node current = root;

        while(current.iData !=value){
            //如果这个值比当前的节点值小,那么找左子节点
            if(current.iData > value){
                current = current.leftChild;
            }else{
                current = current.rightChild;
            }

            if(current == null){
                return null;
            }
        }

        return  current;

    }
    public void traverse(int traverseType){
        switch (traverseType) {
        case 1://
            //前序遍历
            System.out.println("前序遍历");
            frontOrder(root);
            break;
        case 2:
            System.out.println("中序遍历");
            inOrder(root);
            break;
        case 3:
            System.out.println("后序遍历");
            postOrder(root);
            break;

        default:
            break;
        }
        System.out.println("--------------------------------");
    }

    /**
     * 前序遍历
     * @param localNode
     */
    public void frontOrder(Node localNode){

        if(localNode != null){
            //访问根节点
            System.out.println(localNode.iData +","+localNode.sData);
            //前序遍历左子树
            frontOrder(localNode.leftChild);
            //前序遍历右子树
            frontOrder(localNode.rightChild);
        }
    }
    /**
     *  中序遍历 -
     * 1.中序遍历左子树
     * 2.访问根节点
     * 3.中序遍历右子树(从小到大)
     * @param localNode
     */
    public void inOrder(Node localNode){

        if(localNode != null){

            //中序遍历左子树
            inOrder(localNode.leftChild);
            //访问根节点
            System.out.println(localNode.iData +","+localNode.sData);
            //中序遍历右子树
            inOrder(localNode.rightChild);
        }
    }
    /**
     * 后序遍历。。先遍历左子树-右子树-访问根节点
     * @param localNode
     */
    public void postOrder(Node localNode){

        if(localNode != null){

            //后序遍历左子树
            postOrder(localNode.leftChild);
            //后序遍历右子树
            postOrder(localNode.rightChild);
            //访问根节点
            System.out.println(localNode.iData +","+localNode.sData);

        }
    }

    /**
     * 删除一个节点
     * 有3种情况
     * 1.该节点是叶子节点
     * 2.该节点只有 一个节点
     * 3.该节点有俩个节点。需要找到右边节点的最小节点。(中序遍历后继。。找到)
     * @param value
     * @return
     */
    public  boolean delete(int value){

        //引用当前节点
        Node current = root;
        //引用父节点
        Node parent = root;

        //判断是否为左子节点
        boolean isLeftChild  =true;
        while(current.iData != value){
            //先赋值
            parent = current;
            //如果这个值比当前的节点值小,那么找左子节点
            if(current.iData > value){
                current = current.leftChild;
                isLeftChild  =true;
            }else{
                current = current.rightChild;
                isLeftChild  =false;
            }

            if(current == null){
                return false;
            }
        }


        //删除叶子节点,也就是该节点没有子节点
        if(current.leftChild == null && current.rightChild == null){
            if(current == root){//删除的是根。并且根么有子子节点
                root = null;
            }else if(isLeftChild){//删除的叶子节点是父节点的左子节点
                parent.leftChild = null;

            }else{
                parent.rightChild = null;
            }

    }else if(current.rightChild == null){//只有一个节点  意思就是左子节点有数据

        if(current == root){//如果是根的话。就是根节点=当前的左子节点 
            root = current.leftChild;
        }else if(isLeftChild){
            parent.leftChild = current.leftChild;
        }else{
            parent.rightChild = current.leftChild;
        }

    }else if(current.leftChild == null){//只有一个节点  意思就是右子节点有数据
        if(current == root) root = current.rightChild;
        //这里看起来比较绕。。所以删除的时候可以自己画一个图。自己想
        else if(isLeftChild){
            parent.leftChild = current.rightChild;
        }else{
            parent.rightChild = current.rightChild;
        }
    }else{//有俩个节点。。。。
        Node successor = getSuccessor(current);

        if(current ==root){
            root = successor;

        }else if(isLeftChild){
            parent.leftChild = successor;
        }else{
            parent.rightChild = successor;
        }

        successor.leftChild =current.leftChild; 
    }
        return true;
    }


    public Node getSuccessor(Node delNode){
        Node successor = delNode;
        Node successorParent = delNode;

        Node current =delNode.rightChild;

        while(current != null){
            successorParent =successor;
            successor =current;//先右边然后然后一直找左子节点
            current = current.leftChild;//一直往左子节点找
        }
        if(successor != delNode.rightChild){//这里没有看懂。
            successorParent.leftChild = successor.rightChild;
            successor.rightChild = delNode.rightChild;

        }
        return successor;

    }
}

测试代码:

package com.chapter5_1;

public class Test {

    public static void main(String[] args) {
        Tree t = new Tree();

        t.insert(10,"thinkpad");
        t.insert(20,"mac");
        t.insert(15,"del");
        t.insert(3,"leishen");
        t.insert(40,"zhangsan");
        t.insert(16,"liao");
        t.insert(4,"luyao");

//      System.out.println(t.root.rightChild.iData);
//      System.out.println(t.root.rightChild.leftChild.iData);
//      System.out.println(t.root.leftChild.iData);


//      Node node = t.find(15);
        System.out.println(node.iData +", " +  node.sData);
//      node = t.find(3);
        System.out.println(node.iData +", " +  node.sData);
        t.delete(3);
//      t.traverse(1);
        t.traverse(2);
//      t.traverse(3);

        t.delete(16);
//      t.traverse(1);
        t.traverse(2);
    }
}

至于测试结果我就不贴了。很多。在删除二叉树有俩个节点的时。我没有弄明白。我先贴代码。最近比较累。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值