数据结构与算法java篇--二叉树

内容有点多,建议先收藏

目录

一.树的介绍

二.java代码实现树

1.Node类

2.Tree类

3.查找节点

4.插入节点  

5.遍历树

        5.1 中序遍历

        5.2 前序遍历和后序遍历

6.查找最大值和最小值

7.删除节点

        7.1 删除没有子节点的节点

        7.2 删除有一个子节点的结点

        7.3 删除有两个节点的节点 

8. 完整的二叉树java代码


一.树的介绍

树由边连接的节点而组成,在图中用圆表示节点,实现表示边

 路径:顺着节点从一个节点到另一个节点的顺序叫做路径

:树顶端的节点叫根

父节点:连接下层节点的上层节点称为父节点,例如B是C,D的父节点

子节点:和父节点相连接的节点

叶节点:没有子节点的节点


二.java代码实现树

1.Node类

Node类是节点对象的类,包含了对象的数据

Node类的实现:

class Node{
    int iData;    //节点的键
    double fData;   //数据
    Node leftChild;   //左节点
    Node rightChild;  //右节点
}

Node类对象还可以指向一个代表数据类型的对象,而不是把数据项直接放在节点中:

class Node{
   person p1;
    Node leftChild;
    Node rightChild;
}
class person{
    int iData;
    double fData;
}

2.Tree类

Tree类是一个数本身的类,Tree类中有查询,删除,插入以及遍历和显示的方法

 Tree类的骨架:

class Tree{
    private Node root;  //根节点
    public void insert(int id,double dd){
        
    }
    public void find(int key){
        
    }
    public void delete(int id){
        
    }
    //.......
}

3.查找节点

规定父节点的左节点小于父节点,右节点小于父节点,在查找是,最先和父节点比较,如果查找的对象小父节点就在父节点的左节点查找,反之在右节点查找,如此类推,直到找到

查找代码:

 public Node find(int key){
        Node current=root;
        while(current.iData!=key){
            if(key<current.iData)    //如果小于
                current=current.leftChild;
            else       //如果大于
                current=current.rightChild;
            if (current==null)
                return null;
        }
        return current;
    }

4.插入节点  

插入节点,先查找到插入节点的父节点,如果插入的值大于父节点就插入到右节点,反之插入左节点

 插入操作代码:

 public void insert(int id,double dd){
        Node newNode=new Node();
        newNode.iData=id;
        newNode.dData=dd;
        if (root==null)
            root=newNode;
        else {
            Node current=root;
            Node parent;
            while (true){
                parent=current;
                if(id<current.iData){
                    current=current.leftChild;
                    if (current==null){
                        parent.leftChild=newNode;
                        return;
                    }
                    else {
                        current=current.rightChild;
                        if (current==null){
                            parent.leftChild=newNode;
                            return;
                        }
                    }
                }
            }
        }
    }
    

5.遍历树

遍历树就是按顺序访问树的每一个节点,遍历有分为中序遍历,前序遍历和后序遍历

5.1 中序遍历

图解中序遍历:

 从节点开始沿左边画路径线,当路径线结果节点正下方时该结点被遍历,如图遍历结果:20,30,40,50,60

中序遍历代码:

 public void inOrder(Node localRoot){
        if (localRoot!=null){
            inOrder(localRoot.leftChild);
            System.out.print(localRoot.iData+" ");
            inOrder(localRoot.rightChild);
        }
    }

5.2 前序遍历和后序遍历

前序遍历和后序遍历的方法类似于中序遍历


6.查找最大值和最小值

二叉树查找最小值只要遍历左子树,遍历的最后一个就是最小的,反之,遍历右子树,最后一个就是最大的

 如·图是查找最小值,查找最小值代码:

public Node minmum(){
        Node current,last;
        current=root;
        while (current!=null){
            last=current;
            current=current.leftChild;
        }
        return last;
}

查找最大值:

public Node minmum(){
        Node current,last;
        current=root;
        while (current!=null){
            last=current;
            current=current.rightChild;
        }
        return last;
}

7.删除节点

删除节点只要让该节点为null就可以了,虽然该节点依然存在,但java的垃圾回收处理会清除该节点,实现删除节点,删除操作要考虑三种情况:

1.该节点是叶节点

2.该节点有一个子节点

3.该节点有两个子节点


7.1 删除没有子节点的节点

删除没有叶节点,只要改变其父节点对应的子节点的值即可

代码:

public boolean delete(int key){
        Node current=root;
        Node parent=root;
        boolean isLeftChild=true;
        while (current.iData!=key){
            parent=current;
            if(key<current.iData){
                isLeftChild=true;
                current=current.leftChild;
            }
            else {
                isLeftChild=false;
                current=current.rightChild;
            }
            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;
        }
        return true;
}

7.2 删除有一个子节点的结点

  删除有一个子节点时,只要将该节点的子节点和其父节点连接即可

 部分代码:

      else if(current.rightChild==null)
            if (current==root)
                root=current.leftChild;
        else if(isLeftChild)
            parent.leftChild=current.rightChild;
        else if(current.leftChild==null)
            if(current==root)
                root=current.rightChild;
            else if(isLeftChild)
                parent.leftChild=current.rightChild;
            else 
                parent.rightChild=current.rightChild;
        

7.3 删除有两个节点的节点 

 删除有两个节点的节点,要找到一个结点和父节点连接,同时该连接的结点要满足大于删除节点的左节点,小于删除节点的右节点,我们称该点为后继点

 查找后继点的代码:

public Node getSuccessor(Node delNode){
        Node successorParent=delNode;
        Node successor=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;
}

8. 完整的二叉树java代码

public class Mains {
    public static void main(String[] args){
        Tree tree=new Tree();
        tree.insert(3,23);
        tree.insert(2,56);
        tree.insert(1,43);
        tree.insert(7,58);
        tree.insert(9,49);
        tree.insert(12,62);
        tree.insert(4,93);
        tree.insert(5,24);
        tree.displayTree();
         Node node=tree.find(5);
         System.out.println("第五个是:"+node.dData);
         System.out.println("1.前序遍历,2.中序遍历,3.后序遍历");
         tree.traverse(1);
        tree.traverse(2);
        tree.traverse(3);
         tree.delete(7);
         System.out.println("删除第7个后:");
         tree.displayTree();
    }
}

class Node{   //节点
    public int iData;
    public double dData;
    public Node leftChild;
    public Node rightChild;
    public void display(){
        System.out.print("{");
        System.out.print(iData);
        System.out.print(",");
        System.out.print("}");
    }
}

class Tree{    //树结构
    private Node root;
    public Tree(){
        root=null;
    }
    public Node find(int key){   //查找操作
        Node current=root;
        while (current.iData!=key){
            if(key<current.iData)   //如果小于,在左子树查找
                current=current.leftChild;
            else                    //如果大于,在右子树查找
                current=current.rightChild;
            if(current==null)  //如果没有找到
                return null;
        }
        return current;   //如果找到,返回current
    }
            //插入操作
    public void insert(int id,double dd){
        Node newNode=new Node();
        newNode.iData=id;
        newNode.dData=dd;
        if(root==null)  //如果根节点为空
            root=newNode;
        else {
            Node current=root; //遍历开始位置
            Node parent;
            while (true){
                parent=current;
                if(id<current.iData){  //小于当前二叉树键,在左子树插入
                    current=current.leftChild;
                    if (current==null){  //插入左子树最后一个
                        parent.leftChild=newNode;
                        return;
                    }
                }else {   //目标键大于时,在右子树插入
                    current=current.rightChild;
                    if (current==null){   //插入到右子树最后一个
                        parent.rightChild=newNode;
                        return;
                    }
                }
            }
        }
    }
    //删除操作
    public boolean delete(int key){
        Node current=root;
        Node parent=root;
        boolean isleftChild=true;
        while (current.iData!=key) {
            parent = current;    //设置父节点
            if (key < current.iData) { //左边操作
                isleftChild = true;   //表示删除的节点在左节点上
                current = current.leftChild;
            } else {    //右边查找
                isleftChild = false;
                current = current.rightChild;
            }
            if (current == null)  //如果没有找到要删除的key
                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);  //调用getSuccessor寻找后继点
                if (current == root)
                    root = successor;
                else if (isleftChild)  //后继点是左节点
                    parent.leftChild = successor;
                else
                    parent.rightChild = successor;
                successor.leftChild = current.leftChild;   //没有后继点
            }
        return true;
    }
    //后继节点查找操作
    private Node getSuccessor(Node delNode){
        Node successorParent=delNode;
        Node successor=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;
    }
  //选择遍历方式操作
  public void traverse(int travesType){
        switch (travesType){
            case 1:System.out.print("前序遍历:");
                    preOrder(root);
                    break;
            case 2:System.out.print("中序遍历:");
                    inOrder(root);
                    break;
            case 3:System.out.print("后序遍历:");
                    postOrder(root);
                    break;
        }
        System.out.println(" ");
    }
    //前序遍历
    private void preOrder(Node locaRoot){
        if(locaRoot!=null){
            System.out.print(locaRoot.iData+" ");
            preOrder(locaRoot.leftChild);
            preOrder(locaRoot.rightChild);
        }
    }
    //中序遍历
    private void inOrder(Node locaRoot){
        if (locaRoot!=null){
            inOrder(locaRoot.rightChild);
            System.out.print(locaRoot.iData+" ");
            inOrder(locaRoot.leftChild);
        }
    }
    //后序遍历
    private void postOrder(Node locaRoot){
        if (locaRoot!=null){
          postOrder(locaRoot.leftChild);
          postOrder(locaRoot.rightChild);
          System.out.print(locaRoot.iData+" ");
        }
    }
    //显示操作
    public void displayTree(){
        Stack globalStack=new Stack();
        globalStack.push(root);
        int nBlank=32;
        boolean isRowEmpty=false;
        System.out.println("---------------------------------------");
        while (isRowEmpty==false){
            Stack localStack=new Stack();
            isRowEmpty=true;
            for (int j=0;j<nBlank;j++)
                System.out.print(" ");
            while (globalStack.isEmpty()==false){
                Node temp=(Node)globalStack.pop();
                if(temp!=null){
                    System.out.print(temp.iData);
                    localStack.push(temp.leftChild);
                    localStack.push(temp.rightChild);
                    if (temp.leftChild!=null || temp.rightChild!=null)
                        isRowEmpty=false;
                }else {
                    System.out.print("--");
                    localStack.push(null);
                    localStack.push(null);
                }
                for (int i=0;i<nBlank*2-2;i++)
                    System.out.print(" ");
            }
            System.out.println( );
            nBlank/=2;
            while (localStack.isEmpty()==false)
                globalStack.push(localStack.pop());
        }
        System.out.println("-------------------------------");
    }
}

运行:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
数据结构与算法是计算机科学非常重要的概念。在Java,有许多常见的数据结构和算法的实现。其,数据结构包括数组、链表、栈、队列、跳表、散列表、二叉树、堆、图和Trie树。而算法包括递归、排序、二分查找、哈希算法和字符串匹配算法。\[1\] 在Java,我们可以使用散列表(哈希表)来实现数据结构。而在字符串匹配算法,有四种常见的算法:暴力匹配算法(BF算法)、RK算法、BM算法和KMP算法。这些算法都有各自的特和适用场景。\[2\] 另外,在Java开发,排序是一种常见的需求。我们可以使用一些常见的排序算法来对数据元素进行排序,比如按照日期对订单进行排序,按照价格对商品进行排序等等。在Java开发工具包(JDK),已经提供了许多数据结构和算法的实现,比如List、Set、Map和Math等。我们可以借鉴JDK的方式,将算法封装到某个类,并进行API的设计和实现。\[3\] 综上所述,数据结构与算法Java有着广泛的应用,通过学习和使用这些概念和实现,我们可以更好地解决问题和优化程序。 #### 引用[.reference_title] - *1* *2* [Java数据结构和算法学习笔记](https://blog.csdn.net/zth13015409853/article/details/121946203)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [数据结构与算法Java)笔记--Comparable接口](https://blog.csdn.net/csh1807266489/article/details/126782378)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前段被迫创业

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值