一  二叉查找树

二叉查找树又叫二叉排序树,是为了解决查找的效率问题。正常情况下查找一个元素,需要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

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

  1. 算法与数据结构(三) 二叉树的遍历及其线索化(Swift版)

    前面两篇博客介绍了线性表的顺序存储与链式存储以及对应的操作,并且还聊了栈与队列的相关内容.本篇博客我们就继续聊数据结构的相关东西,并且所涉及的相关Demo依然使用面向对象语言Swift来表示.本篇博客 ...

  2. 数据结构与算法--力扣109题将有序双向链表转换为二叉搜索树

    将有序数组转换为二叉搜索树 近一年都比较关注算法相关的知识,也刷了不少题,之前的文章中大多也是算法相关的文章,但是感觉每次遇到树相关的题型都不能应对自如,因此还是有必要在相关知识上下功夫,因此有此次总 ...

  3. 数据结构与算法--力扣108题将有序数组转换为二叉搜索树

    力扣108提将有序数组转换为二叉搜索树 近一年都比较关注算法相关的知识,也刷了不少题,之前的文章中大多也是算法相关的文章,但是感觉每次遇到树相关的题型都不能应对自如,因此还是有必要在相关知识上下功夫, ...

  4. 数据结构---判断一棵树是否是二叉搜索树

    数据结构-判断一棵树是否是二叉搜索树 代码: #pragma once #define N 100 #define elemType BTree* #include<stdlib.h> t ...

  5. 由任意二叉树的前序遍历序列和中序遍历序列求二叉树的思想方法_算法与数据结构基础 - 二叉树(Binary Tree)...

    二叉树基础 满足这样性质的树称为二叉树:空树或节点最多有两个子树,称为左子树.右子树, 左右子树节点同样最多有两个子树. 二叉树是递归定义的,因而常用递归/DFS的思想处理二叉树相关问题,例如Leet ...

  6. 【数据结构与算法】之深入解析“将有序数组转换为二叉搜索树”的求解思路与算法示例

    一.题目要求 给你一个整数数组 nums ,其中元素已经按升序排列,请你将其转换为一棵高度平衡 二叉搜索树. 高度平衡二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树. ...

  7. 【数据结构和算法笔记】用c和c++分别实现二叉搜索树

    目录 二叉排序树(二叉搜索树)定义: 二叉排序树的性质: 二叉排序树的操作: c语言实现二叉排序树: C++实现二叉排序树: 二叉排序树(二叉搜索树)定义:    二叉排序树的性质: (1)二叉排序树 ...

  8. 算法基础知识科普:8大搜索算法之二叉搜索树(下)

    由于微信发代码以及数学符号很吃力,所以我们做知识科普只能利用图片来做,本算法代码较多,所以分为三个部分来介绍.本篇把剩余的部分补齐.当然二叉搜索树也有自己的缺陷,即构造的二叉树跟数据的初始状态以及删除 ...

  9. 树、二叉树、二叉搜索树_检查二叉树是否为BST(二叉搜索树)

    树.二叉树.二叉搜索树 Description: 描述: This article describes how to check whether a given tree is BST or not? ...

最新文章

  1. fguillot json rpc_使用Hyperf框架搭建jsonrpc服务
  2. android 修改包名
  3. CodeForces - 1198A MP3(尺取)
  4. lagrange插值(完成)
  5. spring条件注解有哪些_Spring4有条件
  6. C/S架构和B/S架构
  7. [WM][转]PPC中如何判断网络已经连接或者断开
  8. 20190906:(leetcode习题)Shuffle an Array
  9. 数据结构与算法(Python)第三天
  10. python曼·惠特尼U检验(Mann-Whitney U Test)
  11. vivado修改下载器下载速率
  12. java助教_2018-2019第一学期Java助教心得
  13. Table ‘xxx‘ is specified twice, both as a target for ‘UPDATE‘ and as a separate source for data
  14. codeforces 407C Curious Array 数学
  15. java 蓝桥杯 分机号
  16. 数据库增量同步/ETL工具
  17. Invalid format specifier的解决方法
  18. python七段数码管绘制实验报告_python实现七段数码管和倒计时效果
  19. CTP程序化交易入门系列之一:准备
  20. 转-CNN模型的压缩与加速算法综述

热门文章

  1. 如何让body背景图自适应浏览器窗口大小
  2. Linux 设备驱动开发 —— Tasklets 机制浅析
  3. MyBatis Generator配置文件翻译
  4. 在vue项目中操作元素ref案例;
  5. [react] 展示组件和容器组件有什么区别?
  6. javascript学习系列(23):数组中的解构方法
  7. React开发(103):详细路径 不然找不到
  8. 前端学习(2979):vue-element-admin结构always:true始终显示
  9. 前端学习(2926):vue改变样式2
  10. [html] 什么是空元素?常用的空元素有哪些?