二叉树与二叉查找树(附java代码实现)

Java实现二叉树(一):二叉查找树的实现 Java实现二叉树(一):二叉查找树的实现    数据结构+算法=程序,这是共识,是真理,还是学生时代卷子中的考点。但大多数程序员往往缺乏数据结构和算法的知识,或是根本没有学过,或是学过,但在工作时频繁地与业务逻辑打交道,也就逐渐忘记了有这么一回事。    话不多说,直接开始吧,本文将介绍二叉树的基本概念,以及平衡二叉树增删改查节点的实现,由于网上关于数据结构的资料,C++相对居多,而本身作为一个... 阅读详情

查阅了不少资料,拾人牙慧,做个便于自己查阅的简单归纳。


树这种结构具备天然的高效性可以巧妙的避开我们不关心的东西,只需要根据我们的线索快速去定位我们的目标。所以说树代表着一种高效。在了解二分搜索树之前,我们不得不了解一下二叉树,因为二叉树是实现二分搜索树的基础。就像我们后面会详细讲解和实现AVL(平衡二叉树),红黑树等树结构,你不得不在此之前学习二分搜索树一样,他们都是互为基础的。


二叉树(Binary Tree)

1. 二叉树是一种特殊的树类型,最上方的唯一节点称为根节点。

2. 每个节点最多只能有两个子节点,分别叫左孩子或者右孩子。

3. 没有孩子的节点称为叶子节点,有孩子的节点则称为内节点

4. 每个子树也是一个二叉树

二叉树的类型可分为:

满二叉树:官方定义,一棵深度为 h,且有 2^h - 1 个节点称之为满二叉树。

说人话就是,从根节点到每一个叶子节点所经过的节点数都是相同的。看图一目了然

完全二叉树:官方定义,深度为 h,有 n 个节点的二叉树,当且仅当其每一个节点都与深度为 h 的满二叉树中,序号为 1 至 n 的节点对应时,称之为完全二叉树。

说人话,完全二叉树除去最后一层叶子节点,就是一颗满二叉树,并且最后一层的节点只能集中在左侧。从另一个角度来说就是将满二叉树的叶子节点从右往左删除若干个后就变成了一棵完全二叉树,也就是说,满二叉树一定是一棵完全二叉树,反之不成立。

平衡二叉树:平衡二叉树又被称为AVL树,它是一棵二叉树,又是一棵二分搜索树,平衡二叉树的任意一个节点的左右两个子树的高度差的绝对值不超过1,即左右两个子树都是一棵平衡二叉树。后面会详细介绍该树。


二叉树与数组的对比

数组:在java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组是一种线性序列,这使得元素访问非常快速。但是为了这种快速所付出的代价是数组对象的大小被固定,并且是在其整个生命周期中不可被改变,简单的来说可以理解为数组一旦被初始化,则其长度不可被改变。数组长度定义后,会在堆内存中开辟指定长度的连续内存空间,并且JVM会自动根据数据类型分配数组元素的初始值。

总结就是,优点:随机访问。数组的查找时间是线性 O(n),但定位时间却是常量 O(1),效率极高。缺点:长度固定。一旦初始化完成,数组的大小被固定。灵活性不足。

二叉树:二叉树不是采用连续的内存存放。实际上,通常 BinaryTree 类的实例仅包含根节点实例的引用,而根节点实例又分别指向它的左右孩子节点实例,以此类推。所以关键的不同之处在于,组成二叉树的节点对象实例可以分散到堆中的任何位置,它们没必要像数组元素那样连续的存放。

如果要访问二叉树中的某一个节点,通常需要逐个遍历二叉树中的节点,来定位那个节点。它不象数组那样能对指定的节点进行直接的访问。所以查找二叉树的渐进时间是线性的 O(n),在最坏的情况下需要查找树中所有的节点。也就是说,随着二叉树节点数量增加时,查找任一节点的步骤数量也将相应地增加。

普通的二叉树确实不能提供比数组更好的性能,甚至于当二叉树全部偏向于一侧时,就成了链表结构。但是按照一定的规则来组织排列二叉树中的元素时,就可以很大程度地改善查询时间和定位时间。


二分搜索树(Binary Search Tree)

又称为二叉查找树,是一种特殊的二叉树,改善了二叉树节点查找的效率。有以下性质:

对于任意一个节点 n,

  • 其左子树(left subtree)下的每个后代节点(descendant node)的值都小于节点 n 的值;
  • 其右子树(right subtree)下的每个后代节点的值都大于节点 n 的值。

从二叉查找树的性质可知,BST 各节点存储的数据必须能够与其他的节点进行比较。给定任意两个节点,BST 必须能够判断这两个节点的值是小于、大于还是等于。

通过 BST 查找节点,理想情况(二叉树均衡分布,如完全二叉树)下我们需要检查的节点数可以减半,此时的查找时间复杂度为O(lg n)。而糟糕情况下(二叉树完全偏向一侧成链表结构),此时的时间复杂度为O(n),也就与在数组中查找基本类似了。

因此,BST 算法查找时间依赖于树的拓扑结构。最佳情况是 O(log­2n),而最坏情况是 O(n)。

我们不仅需要了解如何在二叉查找树中查找一个节点,还需要知道如何在二叉查找树中插入和删除一个节点。


插入节点:

当向树中插入一个新的节点时,该节点将总是作为叶子节点。所以,最困难的地方就是如何找到该节点的父节点。类似于查找算法中的描述,我们将这个新的节点称为节点 n,而遍历的当前节点称为节点 c。开始时,节点 c 为 BST 的根节点。则定位节点 n 父节点的步骤如下:

  1. 如果节点 c 为空,则节点 c 的父节点将作为节点 n 的父节点。如果节点 n 的值小于该父节点的值,则节点 n 将作为该父节点的左孩子;否则节点 n 将作为该父节点的右孩子。
  2. 比较节点 c 与节点 n 的值。
  3. 如果节点 c 的值与节点 n 的值相等,则说明用户在试图插入一个重复的节点。解决办法可以是直接丢弃节点 n,或者可以抛出异常。
  4. 如果节点 n 的值小于节点 c 的值,则说明节点 n 一定是在节点 c 的左子树中。则将父节点设置为节点 c,并将节点 c 设置为节点 c 的左孩子,然后返回至第 1 步。
  5. 如果节点 n 的值大于节点 c 的值,则说明节点 n 一定是在节点 c 的右子树中。则将父节点设置为节点 c,并将节点 c 设置为节点 c 的右孩子,然后返回至第 1 步。

当合适的节点找到时,算法结束。从而使新节点被放入 BST 中成为某一父节点合适的孩子节点。

BST 的插入算法的复杂度与查找算法的复杂度是一样的:最佳情况是 O(log­2n),而最坏情况是 O(n)。因为它们对节点的查找定位策略是相同的。


删除节点:

删除节点首先要查找要删除的节点,找到后执行删除操作。

删除节点的节点有如下几种情况:

  1. 删除的节点有两个子节点
  2. 删除的节点有一个子节点
  3. 删除的节点没有子节点

Case 1:节点有两个子节点情况下,涉及到节点的“位置变换”,用右子树中的最小节点替换当前节点。从右子树一直 left 到 NULL。最后会被转换为 Case 2 或 Case 3 的情况。所以对于删除有两个孩子的节点,删除的是其右子树的最小节点,最小节点的内容会替换要删除节点的内容。

Case 2:有一个子节点的情况下,将其父节点指向其子节点,然后删除该节点。

Case 3:在没有子节点的情况,其父节点指向空,然后删除该节点。


遍历:

对于线性的连续的数组来说,遍历数组采用的是单向的迭代法。从第一个元素开始,依次向后迭代每个元素。而 BST 则有三种常用的遍历方式:

  • 前序遍历(Perorder traversal)
  • 中序遍历(Inorder traversal)
  • 后序遍历(Postorder traversal)

当然,这三种遍历方式的工作原理是类似的。它们都是从根节点开始,然后访问其子节点。区别在于遍历时,访问节点本身和其子节点的顺序不同。

前序遍历从当前节点(节点 c)开始访问,然后访问其左孩子,再访问右孩子。

中序遍历是从当前节点(节点 c)的左孩子开始访问,再访问当前节点,最后是其右节点。

后序遍历首先从当前节点(节点 c)的左孩子开始访问,然后是右孩子,最后才是当前节点本身。


贴上二叉树的java代码实现:

package tree;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;

/**
 * 二叉查找树(非递归版)
 */
public class Tree<V extends Comparable<? super V>> {

    private Node root;
    private int size;

    class Node {
        public Node right;
        public Node left;
        public Node parent;
        public V value;

        Node(V v, Node parent) {
            this.value = v;
            this.parent = parent;
        }

        @Override
        public String toString() {
            return "Node{" +
                    "value=" + value +
                    '}';
        }
    }


    /**
     * 插入
     *
     * @param v
     * @return 返回插入后的新节点
     */
    public Node insert(V v) {
        Node tmp = this.root;
        if (tmp == null) {
            this.root = new Node(v, null);
            size++;
            return root;
        }
        int cmp;
        Node parent;
        do {
            parent = tmp;
            cmp = tmp.value.compareTo(v);
            if (cmp > 0) {
                tmp = tmp.left;
            } else if (cmp < 0) {
                tmp = tmp.right;
            } else {
                return null;  // doNothing
            }
        } while (tmp != null);

        Node node = new Node(v, parent);
        if (cmp > 0) {
            parent.left = node;
        } else if (cmp < 0) {
            parent.right = node;
        }
        size++;
        return node;
    }

    /**
     * 查找
     *
     * @param v
     * @return
     */
    public Node getNode(V v) {
        Node tmp = this.root;
        do {
            int cmp = tmp.value.compareTo(v);
            if (cmp > 0) {
                tmp = tmp.left;
            } else if (cmp < 0) {
                tmp = tmp.right;
            } else {
                return tmp;
            }
        } while (tmp != null);
        return null;
    }

    /**
     * 移除
     *
     * @param v
     * @return 实际发生高度变化的子树根节点
     */
    public Node remove(V v) {
        Node first = getNode(v);
        if (first == null) return null;
        /**
         * Case 1:该节点有两个子节点
         * 该种情况下,涉及到节点的“位置变换”,用右子树中的最小节点替换当前节点。从右子树一直 left 到 NULL。
         * 最后会被转换为 Case 2 或 Case 3 的情况。
         */
        if (first.left != null && first.right != null) {
            Node s = first.right;
            while (s.left != null) {
                s = s.left;
            }
            // 修改first的value,完成替换,此时value为v的节点已被移除
            first.value = s.value;
            // first指向右子树的最小节点,此时后续问题转换为,删除此最小节点,即Case 2场景
            first = s;
        }
        Node second = first.left != null ? first.left : first.right;
        // Case 2:该节点有一个子节点,将其父节点指向其子节点,然后删除该节点。
        if (second != null) {
            second.parent = first.parent;
            if (first.parent == null) {
                root = second;
            } else if (first == first.parent.left) {
                first.parent.left = second;
            } else {
                first.parent.right = second;
            }
        } else {
            // Case 3:该节点无子节点,其父节点的子节点指向空
            if (first == first.parent.left) {
                first.parent.left = null;
            } else {
                first.parent.right = null;
            }
        }
        size--;
        return first;
    }

    /**
     * 前序遍历 (按遍历得到的顺序重新构建树,能得到相同的树)
     *
     * @param root
     * @return
     */
    public List<V> preOrder(Node root) {
        List<V> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        ArrayDeque<Node> stack = new ArrayDeque<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            Node node = stack.pop();
            list.add(node.value);
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        return list;
    }

    /**
     * 中序遍历 (所有元素从小到大排列)
     *
     * @param root
     * @return
     */
    public List<V> midOrder(Node root) {
        List<V> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        ArrayDeque<Node> stack = new ArrayDeque<>();
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            if (!stack.isEmpty()) {
                Node node = stack.pop();
                list.add(node.value);
                root = node.right;
            }
        }
        return list;
    }

    /**
     * 后序遍历
     *
     * @param root
     * @return
     */
    public List<V> backOrder(Node root) {
        List<V> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        ArrayDeque<Node> stackA = new ArrayDeque<>();
        ArrayDeque<Node> stackB = new ArrayDeque<>();
        stackA.push(root);
        while (!stackA.isEmpty()) {
            Node node = stackA.pop();
            stackB.push(node);
            if (node.left != null) {
                stackA.push(node.left);
            }
            if (node.right != null) {
                stackA.push(node.right);
            }
        }
        while (!stackB.isEmpty()) {
            Node node = stackB.pop();
            list.add(node.value);
        }
        return list;
    }

    /**
     * 层次遍历 (按遍历得到的顺序重新构建树,能得到相同的树)
     *
     * @param root
     * @return
     */
    public List<V> levelOrder(Node root) {
        List<V> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        ArrayDeque<Node> queue = new ArrayDeque<>();
        ArrayDeque<Node> queue2 = new ArrayDeque<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            root = queue.poll();
            queue2.add(root);
            if (root.left != null) {
                queue.add(root.left);
            }
            if (root.right != null) {
                queue.add(root.right);
            }
        }
        while (!queue2.isEmpty()) {
            Node node = queue2.poll();
            list.add(node.value);
        }
        return list;
    }

    /**
     * 高度
     *
     * @param root
     * @return
     */
    public int height(Node root) {
        if (root == null) {
            return 0;
        }
        int res = 0;
        ArrayDeque<Node> queue = new ArrayDeque<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            ++res;
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                root = queue.poll();
                if (root.left != null) {
                    queue.add(root.left);
                }
                if (root.right != null) {
                    queue.add(root.right);
                }
            }
        }
        return res;
    }

    /**
     * 右旋
     *
     * @param root
     */
    public void rightRotate(Node root) {
        Node left = root.left;
        // 1.1 处理root节点:将root的左节点从重新指向原左节点left的右节点
        root.left = left.right;
        // 2. 处理左节点的右节点: 假如left的右节点不为null,则其右节点的父亲指向root
        if (left.right != null) {
            left.right.parent = root;
        }
        // 3.处理root节点的父节点:父节点的子节点重新指向
        if (root.parent != null) {
            if (root == root.parent.left) {
                //如果为左节点
                root.parent.left = left;
            } else {
                //x为右节点
                root.parent.right = left;
            }
        }
        // 4. 处理左节点
        left.parent = root.parent;
        if (root.parent == null) {
            this.root = left;
        }
        left.right = root;
        // 1.2 处理root的左节点,因为root.parent的原值会在上面步骤上用到,所以放到后面处理,重新将parent指向root的原left节点
        root.parent = left;
    }

    /**
     * 左旋
     *
     * @param root
     */
    public void leftRotate(Node root) {
        Node right = root.right;
        //1.1 将root的右节点指向原右节点的左节点
        root.right = right.left;
        //2. 如果原右节点的左节点不为空 把此节点的父节点指向root
        if (right.left != null) {
            right.left.parent = root;
        }
        // 3.处理root节点的父节点:父节点的子节点重新指向原节点的右节点
        if (root.parent != null) {
            if (root == root.parent.left) {
                //如果为左节点
                root.parent.left = right;
            } else {
                //x为右节点
                root.parent.right = right;
            }
        }
        // 4. 处理右节点
        right.parent = root.parent;
        if (root.parent == null) {
            this.root = right;
        }
        right.left = root;
        // 1.2 处理root的右节点,因为root.parent的原值会在上面步骤上用到,所以放到后面处理,重新将parent指向root的原left节点
        root.parent = right;
    }



   /*
    public List<List<V>> levelOrder2(Node root) {
        List<List<V>> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        ArrayDeque<Node> queue = new ArrayDeque<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            List<V> line = new ArrayList<>();
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                root = queue.poll();
                line.add(root.value);
                if (root.left != null) {
                    queue.add(root.left);
                }
                if (root.right != null) {
                    queue.add(root.right);
                }
            }
            list.add(line);
        }
        return list;
    }*/


    public Node getRoot() {
        return root;
    }

    public int getSize() {
        return size;
    }
}

参考文章

https://www.cnblogs.com/gaochundong/p/binary_search_tree.html

https://www.cnblogs.com/newobjectcc/p/11293689.html

超级详细树讲解一 —— 二叉树、二叉查找树、完全二叉树图解+代码 超级详细树讲解 ——图解+代码 首先很高兴你看到了这篇文章,这篇文章可能会花费你很长很长的时间去看,但是这篇文章包括的内容绝对足够你对树的一个系统性的学习。为什么要写这篇文字呢?因为自己在学习树的时候,有些博客只有图解,有些博客只有代码,在这里我将树的图解和代码都整理在了一起。在每个树都有着对应的图解和代码。相信这篇文字会花费你大量的时间,但是绝对值得。 代码的github地址:代码传送门 pdf的github地址:pdf传送 文章目录超级详细树讲解 ——图解+代码树的基本概念二叉树二叉树的定义二叉树首相数 阅读详情

相关推荐

【NAS for PVE _04】安装TrueNAS

前篇说到如何调试 Proxmox VE 8.2 为安装虚拟机做准备,本篇主要讲述如何在 Proxmox VE 上安装 TrueNAS 系统,并开启NFS供其他系统挂载使用官网下载好TrueNAS系统镜像。

村口王师傅。 6144

二叉树查找 java_Java实现二叉树(一):二叉查找树的实现

Java实现二叉树(一):二叉查找树的实现数据结构+算法=程序,这是共识,是真理,还是学生时代卷子中的考点。但大多数程序员往往缺乏数据结构和算法的知识,或是根本没有学过,或是学过,但在工作时频繁地与业务逻辑打交道,也就逐渐忘记了有这么一回事。话不多说,直接开始吧,本文将介绍二叉树的基本概念,以及平衡二叉树增删改查节点的实现,由于网上关于数据结构的资料,C++相对居多,而本身作为一个Javaer,将...

weixin_32129195的博客 602

Unity2018连接MySQL数据库

当前在做的一个Unity项目需要连接到MySQL数据库,弄了一整天,排了很多错,终于在Unity上成功连接到MySQL数据库了,所以分享一下,避免有这个需求的朋友不用花那么多时间。 我使用的软件是 Unity20184.0f1 + mysql-8.0.24 导入 MySql.Data.dll 首先需要把 MySql.Data.dll 导入到Assets/Plugins 这个dll需要安装Connector/NET,在安装目录\Assemblies\v4.0中拿到,最好不要下载版本太高的,版本太高导入的时候

ZLX的博客 9451

java 自平衡二叉搜索树的实现以及前序、中序、后续遍历实现

上一篇文章讲了java 二叉搜索树的实现以及前序、中序、后续遍历实现,本文将讲述使用java实现自平衡二叉搜索树,以及自平衡二叉搜索树二叉搜索树的前序、中序、后续遍历实现。既然有了二叉搜索树,为什么又出现个 自平衡二叉搜索树呢?试着把 1、2、3、4、5、6、7、8、9、10 这几个数字依次加入到二叉搜索树中你会发现,它是这样的这样的树也是二叉搜索树,只不过它是一个链型,是一个不平衡的二叉搜索树,假如要获取10这个节点需要耗费的时间很长。

西凉的悲伤博客 971

【v4l2】在Android SDK中交叉编译v4l2-ctl

为调试Android设备中camera的相关功能,需要引入v4l2-ctl工具。由于厂商提供的Android SDK源码中未集成v4l2-utils(包含v4l2-ctl以及其它组件的工具包),故需要下载v4l2-utils源码,并在Android SDK中交叉编译生成v4l2-ctl可执行文件。本文讲述其过程步骤。

rentong123的博客 1326

省三医院新门诊大楼网络安全建设项目实施方案

为了响应国家建设数字医疗,构建医联网、医共体的号召,新门诊大楼现有计算机网络,实现各门诊室、药房、医学影像科室及后勤科室的终端数据互通。在互联网出口以三层模式部署两台防火墙,作为连接公网的出口设备;出于等保合规和自身业务安全的考虑,现需要该网络上通过网络安全设备实现安全建设。公网出口防火墙,配置攻击防御策略,防御互联网上的病毒进入内网。公网出口防火墙配置攻击防御策略,防御外网对内网的入侵行为。服务器取得边界防火墙,配置攻击防御策略,入侵防御策略。公网出口防火墙配置入侵防御策略,防御外网对内网发起的D。

m0_63645854的博客 2015

平衡查找二叉树(AVL树)的讲解与实现(JAVA版本)

平衡查找二叉树的讲解与实现前言原理二叉查找树平衡查找二叉树(AVL树)实现AVLTreeDemo后记AVL树的不足 前言 如果让我们在一堆带有标识的数据中,去高效查询一个特定标识的数据,我们有几种方法?通常我们都会知道二分查找法,二分查找法确实是一种比较高效的查找算法,但是也有弊端就是使用二分查找的数据必须要先经过排序而且针对链表,树这种数据结构并不能像数组一样根据坐标去直接访问。 原理 二叉查找...

hellopeng1的博客 1007

【LabVIEW懒人系列教程-视觉入门】2.6LabVIEW模板匹配之创建模板

上期2.5在Labview软件框架中实现了模板匹配功能的运用,然而我们的模板图像是通过视觉助手创建出来的,在实际项目中这样做 ,难免有些不妥。所以,今天就给大家讲解一下,如何编写创建模板功能,模板图像的创建与加载需要注意一些什么。 模板图片的创建,大家可以理解为将图像中的一个特征区域扣下来,通过Labview函数进行信息学习,然后保存成带有图像信息的模板图。 具体做法,下面为大家演示一下 百度网盘视频链接:https://pan.baidu.com/s/1-zxcJBxPgk4t1Ej..

视觉龙哥 2168

(Java)leetcode-100 Same Tree(相同的树)

中规中矩的遍历+比较两棵树,三行代码搞定。

不思量 247

基于Simulink的雷达跟踪系统仿真(附源码)

此示例包含对雷达系统的基本特征进行建模的子系统。该模型是用于目标位置和速度检测的雷达系统的典型模型。该示例包括雷达脉冲发生器、射频发射器子系统、移动目标的 Simulink 表示、射频接收器和接收模块(Rx 模块)。

珞瑜的博客 3516

北斗导航 | SPP、RTK、RTD、PPP-RTK、PPP算法原理,公式及完整matlab代码

开发参考:SPP适合入门学习GNSS定位原理和最小二乘。RTK是工程高精度定位主流方案,但依赖基站。PPP适合无基站区域的广域高精度应用。PPP-RTK是融合两者优点的新一代技术,但系统复杂度最高。· 代码资源:raPPPid(VieVS PPP)是功能完整的MATLAB开源PPP工具箱,支持多系统PPP-AR。MATLAB GPS Toolbox 提供从SPP到PPP的完整功能实现。· 实际应用:农业自动驾驶、无人机航测通常使用网络RTK;大地测量、地壳形变监测常采用PPP事后处理;

尘世冰封的专栏 829

java二叉树镜像_Java编程求二叉树的镜像两种方法介绍

给出一棵二叉树,求它的镜像,如下图:右边是二叉树是左边二叉树的镜像。仔细分析这两棵树的特点,看看能不能总结出求镜像的步骤。这两棵树的根节点相同,但他们的左右两个子节点交换了位置。因此我们不妨先在树中交换根节点的两个子节点,就得到了下面一幅图中的第二颗树解法1(递归)思路1:如果当前节点为空,返回,否则交换该节点的左右节点,递归的对其左右节点进行交换处理。/*class TreeNode{int v...

weixin_39956350的博客 265

MIKE水动力笔记13_数字化海图2之克里金插值

在进行MIKE水动力建模之初,需要准备好水深数据,本专题系列博文主要讲解如何将扫描版JPG格式海图数据在ArcGIS中进行数字化并制作成xyz水深地形数据,用的克里金插值方法,仅供参考。

晏长街的博客 2881

java基础复习——二叉树以及代码实现

说到二叉树,那都是很久以前学的了。。。 最近听到之前的一个同事说,有人说他基础很好,可以写出二叉树等数据结构的实现,这。。。虽然在很多人看来并没有什么,但是。。。我TM对二叉树完全没印象了,突然觉得自己好菜啊~~~ 所以痛下决心,需要复习一下基础知识了~~~ 那么就先从这个二叉树开始吧。 所谓的二叉树,它是一种数据结构,同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快

树懒的博客 3070

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

二叉查找树与平衡二叉树的区别

二叉查找树 二叉查找树又名二叉排序树,亦称二叉搜索树。是每个结点最多有两个子树的树结构。通常子树被称作“左子树”和“右子树”。 定义 若左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若右子树不空,则右子树上所有节点的值均大于它的根节点的值; 左、右子树也分别为二叉排序树; 没有键值相等的节点。 示例图 看起来二叉树的结构是很均匀的排列的,别急,当依次插入13,14数据后,如下图:...

qq_42610605的博客 9596

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

二叉树与二叉查找树的基本方法java实现

转载自:https://www.cnblogs.com/eudiwffe/p/6207196.html https://blog.youkuaiyun.com/weixin_38629529/article/details/81171245 目录 1.二叉树(Binary Tree) 2.完全二叉树: 3.满二叉树: 4.二叉查找树 5.二叉查找树基本方法 1)二叉查找树表示 2)查找一个...

阿休要努力 618

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

java实现简单二叉树

二叉树全面讲解

公号:一条coding 7万+

二叉树的性质及二叉查找树的实现

二叉树的性质 树中的结点数等于数的边数加1,也等于所有的度数之和加1(此性质适合所有的树) 在二叉树的第i层上最多有2i2^i2i个结点,其中i从第0层开始 高度为h的二叉树至多有2h+1−12^{h+1}-12h+1−1个结点 对于任意一棵二叉树T,如果其终端节点数为n0,度为2的结点数为n2,则n0 = n2 + 1 (可以使用性质1来推导,n = n0 + n2 + n1 , n = ...

全村最靓的仔 516

Java实现最优二叉查找树

1 问题描述 在了解最优二叉查找树之前,我们必须先了解何为二叉查找树? 引用自百度百科一段讲解: 二叉排序树(Binary ...

5756

Java实现二叉树的遍历、添加、删除

定义 二叉树在图论中是这样定义的:二叉树是一个连通的无环图,并且每一个顶点的度不大于3。有根二叉树还要满足根结点的度不大于2。有了根结点之后,每个顶点定义了唯一的父结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。如果不考虑连通性,允许图中有多个连通分量,这样的结构叫做森林。 为什么需要使用二叉树 二叉树,本质上,是对链表和数组的一个折中。 比如,我有一个任务,需要输入

顽皮的左腿的博客 1649

Java数据结构--二叉树(二叉查找树)

二叉树是几个有限无素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点。如图即为一个二叉树(可根据图片理解):注:该树并不为一棵二叉搜索树对于二叉树的遍历,可进一步分为三种:①前序遍历(根左右):对于每一棵子树,先访问该节点,然后是左子树,最后是右子树②中序遍历(左根右):对于每一棵子树,先访问左子树,然后是该节点,最后是右子树。

m0_74808313的博客 1439

数据结构:二叉查找树的api设计及其java代码实现

关于二叉树的一些基本概念 二叉树: 二叉树就是度不超过2的树(每个结点最多有两个子结点) 满二叉树: 一个二叉树,如果每一层的结点数都达到最大值,则这个二叉树就是满二叉树 完全二叉树: 叶结点只能出现在最下层和此下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树,即如果树不满则要求左满右不满,是为完全二叉树 我们分析了二叉树结点的特性后,不难设计出二叉树的结点类 。 private class Node { private K key;//键 .

jasnet_u的博客 651

java基础-二叉树之Java实现

二叉树之Java实现 1 二叉树概念 二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加。但是他也有自己的缺点:删除操作复杂。 二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树、二叉排序...

染小柒的博客 723

【AVL平衡二叉树】JAVA代码实现

【AVL平衡二叉树】JAVA代码实现实现思路二叉查找树二叉查找树实现平衡二叉树实现如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 实现思路 AVL平衡二叉树,是在二叉查找树基础上加上了平衡功能,即依照平衡二叉树的规则插入数据之后,依旧要保证任意一个节点的左右子树深度相差不

weixin_42270132的博客 945

4叉树java语言实现_java语言实现二叉树

java语言实现二叉树java语言实现二叉树一、概念对于大量的输入数据,链表的线性访问时间太慢,不宜使用。树这种结构极大的缩短了数据的访问时间。什么是树呢?它是怎么做到提高访问效率的呢?树可以用几种方式定义,定义树的一种自然方式是递归方式,一棵树是一些节点的集合,这些集合可以是空集;若不是空集,则树由根(root)节点以及n(n>=0)个子(child)节点组成,这些子节点每一个都有来自根节...

weixin_29189003的博客 329
上一篇: java位运算符
下一篇: 平衡二叉树AVL及其旋转
MrMoving
博客等级 码龄10年 54粉丝 145原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值