算法与数据结构 (三) 二叉树的简单应用 二叉查找树,二叉堆排序

一  二叉查找树

二叉查找树又叫二叉排序树,是为了解决查找的效率问题。正常情况下查找一个元素,需要O(n)的代价,但是如果查找元素有顺序,有序数组:可以用二分查找降低到 lgn 代价,但是有序链表的代价还是O(n) 因为,链表不支持随机访问,定位不到中间元素,从而不可以一次就排除掉一半元素。此时二叉查找树的出现,完美解决了这个问题,左边的全比根小,右边的全比根大。所以理想状态下也是一次淘汰一半元素(当然不理想,所以出现了红黑树和平衡二叉排序树),一次淘汰一半(实际淘汰不了)和二分查找思路不谋而合。树的简单实现(包括查找,插入,删除算法):

package tree.one;import tree.MyTree;import java.util.ArrayDeque;
import java.util.Queue;public class FindTree {private FindTree left;private FindTree right;private int val;FindTree() {}FindTree(int val) {this.val = val;}//插入一个节点public static void insert(FindTree tree, int n) {if (tree.left == null && n < tree.val) {tree.left = new FindTree(n);return;}if (tree.right == null && n > tree.val) {tree.right = new FindTree(n);return;}if (n < tree.val) {insert(tree.left, n);} else {insert(tree.right, n);}}//查找节点public static  boolean findNode(FindTree tree,int n){if(tree.val==n)return true;while(tree!=null){if(tree.val<n)tree = tree.right;else if(tree.val>n)tree = tree.left;elsereturn true;}return false;}//中序遍历public static void showTree(FindTree tree) {if (tree == null)return;showTree(tree.left);System.out.print(tree.val + " ");showTree(tree.right);}//   层次遍历public static void showTree1(FindTree tree){if (tree == null)return;Queue<FindTree> queue = new ArrayDeque<>();FindTree now = null;queue.offer(tree);while (!queue.isEmpty()) {now = queue.poll();System.out.print(now.val + " ");if (now.left != null)queue.offer(now.left);if (now.right != null)queue.offer(now.right);}}//删除节点public static void deleteNode(FindTree tree ,int n){if(!findNode(tree, n)){System.out.println("删除的元素不存在");return;}FindTree now = null;while(true){if(tree.left!=null) {if (tree.left.val == n) {tree.left = nextNode(tree.left);break;}}if(tree.right!=null) {if (tree.right.val == n) {tree.right = nextNode(tree.right);break;}}if(tree.val<n)tree = tree.left;elsetree = tree.right;}}
//找到删除之后的备胎private static FindTree nextNode(FindTree tree){if(tree.left==null&&tree.right==null)return null; //第一种情况 删除的节点左右孩子都是空else if(tree.left==null)return tree.right; // 第二种情况左孩子空else if(tree.right==null) return tree.left; //第三种情况右孩子空else { //第四种情况FindTree now = tree.right;if(now.left==null){now.left = tree.left;return now;}else{while(now.left.left!=null)now = now.left;FindTree temp = now.left;now.left = null;temp.left = tree.left;temp.right = tree.right;return temp;}}} }

  查找和增加的算法都很常规,删除稍微复杂点:

删除的思路是:找到删除的那个节点,保存它的父节点。让父节点指向新的删除完的子树

删除的节点情况分为:

删除的节点左右孩子都是空的,直接让父节点指向null

删除的节点左孩子为空,右不空,让父节点指向右子树

删除的节点左孩子不为空,右空,让父节点指向左子树

删除的节点左右都不为空,这时候应当找到右子树的最小节点,来“继承“被删除的节点

    所以 又有如下两种情况 :一是子树没有左边分支,也就是下图中40就是最小的  二是有左边的分叉,这时38就是最小的

 

 

 

另外 由于整个类的定义问题,删除根节点的操作没法实现,因为我这里把根节点作为参数了,java又是值传递,所以我另写了一个方法实现

起始 就是调用找备胎节点的方法就行了

public static FindTree deleteRoot(FindTree tree){return nextNode(tree);
}

 测试如下:

public class TreeTest {public static void main(String[] args) {FindTree findTree = new FindTree(18);FindTree.insert(findTree, 32);FindTree.insert(findTree, 26);FindTree.insert(findTree, 25);FindTree.insert(findTree, 30);FindTree.insert(findTree, 40);FindTree.insert(findTree, 44);FindTree.showTree(findTree);System.out.println();FindTree.showTree1(findTree);FindTree.deleteNode(findTree, 32);System.out.println();FindTree.showTree(findTree);System.out.println();FindTree.showTree1(findTree);}
}

  

 

 

 

 

二  、二叉堆(大根堆、小根堆)

二叉堆逻辑上是一颗树,满足根节点是最值,根节点是整颗树最小(大)的,左节点是整颗左子树最(小)的。 
二叉堆逻辑上是一颗完全二叉树,一般用数组就可以实现。二叉树的一个应用堆排序,主要最核心的两个操作是:首先增加一个元素,一般到添加到尾部,此时要对数组进行上浮操作;其次是删除一个元素,这里只实现删除最值元素,
也就是最值元素,此时把最后一个元素调到第一次,执行下坠操作。这部分漫画算法里讲的很好,下面是代码实现的一个二叉堆的结构
public class MyHeap {private int arr[];int size;MyHeap() {this(20);}   //不指定堆的大小,就自定义为20MyHeap(int n) {arr = new int[n];}public boolean isEmpty(){return size == 0;}  //当前堆是不是空的public void push(int n) {if(size==arr.length){throw new RuntimeException("堆满了");}arr[size] = n;int child = size;int par = (child - 1) / 2;int temp = arr[child];while (child > 0 && temp < arr[par]) {arr[child] = arr[par];child = par;par = (child - 1) / 2;}arr[child] = temp;size++;}//弹出arr[0]的元素 并把尾部的元素调到arr[0] 执行下坠操作public   int  pop(){int now = arr[0];int temp = arr[size-1];int left = 1;int par = 0;while(left<size-1){if(left==size-2){if(temp<arr[left])break;}else{if(temp<arr[left]&&temp<arr[left+1])break;}if(left!=size-2&&arr[left]>arr[left+1]){left++;}arr[par] = arr[left];par = left;left = 2 * par + 1;}arr[par] = temp;size--;return now;}}

  

public class TreeTest {public static void main(String[] args) {
//        FindTree findTree = new FindTree(18);
//        FindTree.insert(findTree, 32);
//        FindTree.insert(findTree, 26);
//        FindTree.insert(findTree, 25);
//        FindTree.insert(findTree, 30);
//        FindTree.insert(findTree, 40);
//        FindTree.insert(findTree, 44);
//
//        FindTree.showTree(findTree);
//        System.out.println();
//        FindTree.showTree1(findTree);
//        FindTree.deleteNode(findTree, 32);
//        System.out.println();
//        FindTree.showTree(findTree);
//        System.out.println();
//        FindTree.showTree1(findTree);MyHeap heap = new MyHeap(20);heap.push(2);heap.push(10);heap.push(1);heap.push(20);heap.push(-5);heap.push(-5);while(!heap.isEmpty()){System.out.println(heap.downAdjust());}}
}

  

测试结果如下:

 

转载于:https://www.cnblogs.com/caijiwdq/p/11032220.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/411124.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java操作Excel的poi 遍历一个工作簿

遍历一个工作簿 package com.java.poi;import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.…

git 回滚 add 操作_炫技!git 优雅回滚一次错误的合并操作!

点击蓝色小字关注!关注一下你就不会有bug&#xff01;合并操作相对于常规的 commit&#xff0c;当使用 git merge 合并两个分支的时候&#xff0c;你会得到一个新的 merge commit。当我们 git show 的时候会出现类似信息&#xff1a;1commit 6dd0e2b9398ca8cd12bfd1faa1531d86d…

PS教程第十八课:放大缩小

导航器进行放大缩小操作

[Gamma阶段]展示博客

水哥牛X团队[Gamma阶段]展示博客 微信小程序搜索“小小易校园”即可体验 项目愿景 想参加竞赛&#xff0c;锻炼自己&#xff0c;却找不到合适的队友想进行实习&#xff0c;体验工作&#xff0c;每天不得不翻遍吐槽版的几百条信息却一无所获发布在吐槽版的“求组队”被聊天淹没&…

删除sessionstorage_localStorage 和 sessionStorage 介绍

一、 简述sessionStorage 和 sessionStorage 是 HTML5 新增的两个特性&#xff0c;这两个特性主要是用来作为会话存储和本地存储来使用的&#xff0c;解决了 cookie 存储空间不足的问题&#xff1b;sessionStorage 属性允许你访问一个 session Storage 对象&#xff0c;用于存储…

redis springmvc mysql_redis和mysql怎么一起在springmvc里面

展开全部一、mysql集成到springMVC中的方法&#xff1a;1、在SRC目录下创建一个32313133353236313431303231363533e4b893e5b19e31333361323538db-config.properties文件来存放我们的数据源配置信息&#xff1a;db.url jdbc:mysql:///springmvcdb?useUnicodetrue&character…

mysql安装了libaio还是报错_ubuntu安装mysql遇到的坑----解决Mysql报错缺少libaio.so.1

rootmaster:/usr/local/mysql# /usr/local/mysql/bin/mysqld --initialize --usermysql --datadir/usr/local/mysql/data --basedir/usr/local/mysql弹出一个错:/usr/local/mysql/bin/mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object f…

Notepad++连接VMWare中Linux只能看到/root目录

如下图&#xff0c;使用SFTP协议连接&#xff0c;用root用户登录后&#xff0c;我一开始只能看到root下的文件。稍作修改&#xff0c;把下面的“Initial remote directory”设置成“/”就可以看到根目录了。 转载于:https://www.cnblogs.com/bigbigbigo/p/11054876.html

创建没有Document的MFC MDI应用程序

程序源代码 效果&#xff0c;如图&#xff1a;1)创建一个MFC MDI应用程序&#xff0c;Wizard设置如图&#xff0c;然后点Finish2)CMyTreeView 在CMyTreeView中新增三个函数&#xff0c;显示些示例数据virtual BOOL PreCreateWindow(CREATESTRUCT& cs);//本例没有使用该函…

glassfish mysql 配置文件_最新glassfish配置mysql

在百度搜了一个下午&#xff0c;都没有搞定glassfish配置mysql&#xff0c;特别是百度文库中的GlassFish中MySQL连接池配置这篇文章&#xff0c;我不知道它是不是过时了&#xff0c;配一个jdbcConnPool就要写一个mysql.xml,那我要再配一个&#xff0c;岂不是再写一个mysql2.xml…

Apollo 无人驾驶平台中多传感器标定

传感器标定是无人车最基础也是最核心的模块之一。作为软件层提供的第一项服务&#xff0c;标定质量和准确度极大地影响着感知、定位地图、PNC 等模块。在 Apollo 开源自动驾驶平台中&#xff0c;我们提供了丰富的多传感器标定服务&#xff0c;如激光雷达、惯导、摄像头、多普勒…

mysql数据库的数据类型转换_MySQL 和Server 2000 数据库中数据类型的转换

问题阐述在某些特殊的时候&#xff0c;可能要将MySQL 数据库转换为SQL Server 2000 数据库&#xff0c;这时问题也就随之而来。例如&#xff0c;在MySQL 数据库中&#xff0c;创建的字段使用varchar 类型&#xff0c;该类型的数据可以进行聚合运算&#xff0c;其返回的值是stri…

【Silverlight】Bing Maps开发应用与技巧二:自定义图钉标注控件和动态ToolPanel

在Bing Maps Silverlight Control中以及为我们提供了地图图钉控件Pushpin&#xff0c;我曾经在《使用图钉层&#xff08;Pushpin layer&#xff09;及地图图层&#xff08;MapLayer&#xff09;》一文中介绍过他的使用方法&#xff0c;本篇主要介绍如何自定义图钉标注控件以及对…

java 创建线程的三种方法_java 创建线程的几种方式

说道线程&#xff0c;肯定会想到使用 java.lang.Thread.java这个类那么创建线程也主要有2种方式第一种方式&#xff1a;public class MyThread extends Thread {public void run() {System.out.println("这是MyThread线程");}}然后在调用处&#xff0c;执行start方法…

【iOS】从实际出发理解多线程(二)--NSThread基础操作

简介 NSthread是苹果官方提供面向对象操作线程的技术&#xff0c;简单方便&#xff0c;可以直接操作线程对象&#xff0c;不过需要自己控制线程的生命周期。在平时使用较少&#xff0c;常用的就是下面的方法来获取当前线程。 [NSThread currentThread] 使用 1.实例初始化、属性…