查找、AVL树、散列表
插值查找是二分查找的改进,斐波那契查找是插值查找的改进。
二分查找:mid=(low+high)/ 2
插值查找:mid=(key-a[low])*(high-low)/ (a[high]-a[low])
斐波那契查找主要思想是只要长度符合斐波那契数列,则该段数字可以用两个子段来分割,F(k)-1=(F[k-1]-1)+(F[k-2]-1),即mid=low+F(k-1)-1
FibonacciSearch查找的实现:
package Fibonacci_Search; //fibonacci数列查找
public class FibonacciSearch { //fibonacci数列
public static int fib(int n)
{
if(n==0)
return 0;
if(n==1)
return 1;
return fib(n-1)+fib(n-2);
} //查找
public static int fibonacci_search(int[] arr,int n,int key)
{
int low=1; //记录从1开始
int high=n; //high不用等于fib(k)-1,效果相同
int mid; int k=0;
while(n>fib(k)-1) //获取k值
k++;
int[] temp = new int[fib(k)]; //因为无法直接对原数组arr[]增加长度,所以定义一个新的数组
System.arraycopy(arr, 0, temp, 0, arr.length); //采用System.arraycopy()进行数组间的赋值
for(int i=n+1;i<=fib(k)-1;i++) //对数组中新增的位置进行赋值
temp[i]=temp[n]; while(low<=high) {
mid=low+fib(k-1)-1;
if(temp[mid]>key) {
high=mid-1;
k=k-1; //对应上图中的左段,长度F[k-1]-1
}else if(temp[mid]<key) {
low=mid+1;
k=k-2; //对应上图中的右端,长度F[k-2]-1
}else {
if(mid<=n)
return mid;
else
return n; //当mid位于新增的数组中时,返回n
}
}
return 0;
} public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = {0,1,16,24,35,47,59,62,73,88,99};
int n=10;
int key=59;
System.out.println(fibonacci_search(arr, n, key)); //输出结果为:6
} }
测试结果:6
排序二叉树,排序二叉树是一种动态查找表,方便插入和删除数据。利用中序遍历二叉排序树可以得到有序数列
排序二叉树的删除操作有4种可能。
1)没有左子树的结点,直接将右子树连接到前驱上。
2)没有右子树的结点,直接将左子树连接到前驱上。
3)叶子节点,直接删除
4)有左子树和右子树,可以选取左子树的中序遍历前驱结点或者后继结点替代该结点。
仔细观察,第四种情况中,前驱结点和后继结点肯定属于1,2,3两种情况中的一种,直接将要删除的结点替换成该结点的值并将该结点删除即可。
排序二叉树的实现:
package Binary_Sort_Tree; //二叉排序树
public class BinarySortTree { /**
* 根结点
*/
private TreeNode rootNode; /**
* 获取rootNode
* @return
*/
public TreeNode getRootNode() {
return this.rootNode;
} /**
* 创建二叉排序树 的第一种方法(通过insertBST创建)
* @param array
* @return
*/
public void createBinarySortTree1(int[] array) { for (int i = 0; i <array.length; i++) {
if (!insertBST(array[i])) {
System.out.println("已存在" + array[i] + ",不再插入二叉排序树");
}
} } /**
* 创建二叉排序树 的第二种方法
* @param array
* @return
*/
public void createBinarySortTree2(int[] array) { for (int i = 0; i < array.length; i++) {
if (i == 0) {
rootNode = new TreeNode(array[i]);
continue;
} TreeNode node = rootNode;
while (true) {
if (array[i] < node.getData()) { if (node.getLchild() == null) {
node.setLchild(new TreeNode(array[i]));
break;
} else {
node = node.getLchild();
} } else if (array[i] == node.getData()) {
System.out.println("已存在" + array[i] + ",不再插入二叉排序树");
break;
} else { if (node.getRchild() == null) {
node.setRchild(new TreeNode(array[i]));
break;
} else {
node = node.getRchild();
} }
}
} } /**
* 中序遍历
* @param node
*/
public void inOrderTraverse(TreeNode node) {
if (node != null) {
inOrderTraverse(node.getLchild());
System.out.print(node.getData() + " ");
inOrderTraverse(node.getRchild());
}
} /**
* 二叉排序树的查找 (递归实现)
*
* 查找可以有两种实现方法,一种是递归,一种是while 循环。
* 在插入和删除操作中也首先需要查询操作,这时使用while 循环比较好,可以知道要查询结点的双亲结点
* @param node
* @param key
* @return 返回
*/
public boolean searchBST(TreeNode node, int key) {
if (node == null) {
return false;
} else if (key == node.getData()) {
return true;
} else if (key < node.getData()) {
return searchBST(node.getLchild(), key);
} else {
return searchBST(node.getRchild(), key);
}
} //非递归查找
public boolean iterativeSearch(TreeNode node,int key)
{
TreeNode tempNode=node;
while(tempNode!=null)
{
if(tempNode.getData()>key)
{
tempNode=tempNode.getLchild();
}
else if(tempNode.getData()<key)
{
tempNode=tempNode.getRchild();
}
else
{
return true;
}
}
return false;
} /**
* 二叉排序树的插入
* @param node
* @param key
*/
public boolean insertBST(int key) { //相当于 search 用非递归实现 -----begin
TreeNode node = rootNode;
//查找 最后访问的 node
TreeNode searchLastNode = null; while (node != null) {
searchLastNode = node;
if (key < node.getData()) {
node = node.getLchild();
} else if (key > node.getData()) {
node = node.getRchild();
} else {
return false;
}
}
// search ----end TreeNode newNode = new TreeNode(key); if (rootNode == null) {
rootNode = newNode;
} else if (key < searchLastNode.getData()) {
searchLastNode.setLchild(newNode);
} else {
searchLastNode.setRchild(newNode);
} return true;
} public boolean deleteBST(int key) {
//相当于 search 用非递归实现 -----begin
TreeNode node = rootNode;
//存储 其双亲结点,如果是根节点,则双亲结点为null
TreeNode parentNode = null; while (node != null) {
if (key < node.getData()) {
parentNode = node;
node = node.getLchild();
} else if (key > node.getData()) {
parentNode = node;
node = node.getRchild();
} else {
//相等时已找到
break ;
}
} // search ----end //没有找到要删除的node
if (node == null) {
return false;
} // 右子树为空 ,重接左子树
if (node.getRchild() == null) {
if (parentNode != null) {
if (parentNode.getLchild() == node)
parentNode.setLchild(node.getLchild());
else
parentNode.setRchild(node.getLchild());
} else {
rootNode = node.getLchild();
}
// 左子树为空,重接右子树
} else if (node.getLchild() == null) {
if (parentNode != null) {
if (parentNode.getLchild() == node)
parentNode.setLchild(node.getRchild());
else
parentNode.setRchild(node.getRchild());
} else {
rootNode = node.getRchild();
}
// 左右子树都不为空 ,可以将 要删除结点 按中序遍历的前驱或后继 替代 要删除结点的位置,此处取前驱
} else { //取前驱结点 ,先转左,然后一直到最右
TreeNode replaceNode = node.getLchild();
TreeNode replaceParentNode = node; if (replaceNode.getRchild() != null) {
replaceParentNode = replaceNode;
replaceNode = replaceNode.getRchild();
}
//获取到前驱结点极其双亲结点 //如果前驱结点的双亲结点是 要删除的结点
if (replaceParentNode == node)
replaceParentNode.setLchild(replaceNode.getLchild());
else
replaceParentNode.setRchild(replaceNode.getLchild()); node.setData(replaceNode.getData());
} return true;
} public static void main(String[] args) {
// int[] array = new int[15];
// System.out.print("随机数:");
// for (int i = 0; i < 15; i++) {
// array[i] = (int) (Math.random() * 100);
// System.out.print(array[i] + " ");
// } int[] array = {4, 10, 1, 13, 3, 15, 9, 11, 8, 5, 14, 2, 6, 7, 12}; BinarySortTree binarySortTree = new BinarySortTree();
//创建二叉排序树
binarySortTree.createBinarySortTree1(array); //中序遍历 即是 从小到大的排序
System.out.print("\n中序遍历结果:");
binarySortTree.inOrderTraverse(binarySortTree.getRootNode()); //二叉排序树的查找
boolean searchResult = binarySortTree.iterativeSearch(binarySortTree.getRootNode(), 10);
if (searchResult)
System.out.println("\n查到");
else
System.out.println("\n查不到"); // 二叉排序树的删除
binarySortTree.deleteBST(13);
binarySortTree.inOrderTraverse(binarySortTree.getRootNode());
}
} class TreeNode {
private int data; private TreeNode lchild; private TreeNode rchild; public TreeNode(int data) {
this.data = data;
} public int getData() {
return data;
} public void setData(int data) {
this.data = data;
} public TreeNode getLchild() {
return lchild;
} public void setLchild(TreeNode lchild) {
this.lchild = lchild;
} public TreeNode getRchild() {
return rchild;
} public void setRchild(TreeNode rchild) {
this.rchild = rchild;
} @Override
public String toString() {
return "TreeNode [data=" + data + ", lchild=" + lchild + ", rchild=" + rchild + "]";
}
}
结果:
中序遍历结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
查到
1 2 3 4 5 6 7 8 9 10 11 12 14 15
平衡二叉树
有空再写
https://www.cnblogs.com/skywang12345/p/3577479.html
查找、AVL树、散列表的更多相关文章
- 数据结构(四十二)散列表查找(Hash Table)
一.散列表查找的基础知识 1.散列表查找的定义 散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key).查找时,根据这个确定的对应关系找到 ...
- 数据结构---散列表查找(哈希表)概述和简单实现(Java)
散列表查找定义 散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,是的每个关键字key对应一个存储位置f(key).查找时,根据这个确定的对应关系找到给定值的key的对应f(key) ...
- 数据结构之AVL树
AVL树是高度平衡的而二叉树.它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. 旋转 如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡.这种失去平衡的可以概括为4种姿态:LL ...
- AVL树(三)之 Java的实现
概要 前面分别介绍了AVL树"C语言版本"和"C++版本",本章介绍AVL树的Java实现版本,它的算法与C语言和C++版本一样.内容包括:1. AVL树的介绍 ...
- AVL树(一)之 图文解析 和 C语言的实现
概要 本章介绍AVL树.和前面介绍"二叉查找树"的流程一样,本章先对AVL树的理论知识进行简单介绍,然后给出C语言的实现.本篇实现的二叉查找树是C语言版的,后面章节再分别给出C++ ...
- AVL树(二)之 C++的实现
概要 上一章通过C语言实现了AVL树,本章将介绍AVL树的C++版本,算法与C语言版本的一样. 目录 1. AVL树的介绍2. AVL树的C++实现3. AVL树的C++测试程序 转载请注明出处:ht ...
- AVL树----java
AVL树----java AVL ...
- AVL树的实现——c++
一.概念 AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的.它是最先发明的自平衡二叉查找树,也被称为高度平衡树.相比于"二叉查找树",它 ...
- 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作
AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1). 也就是说,AVL树,本质上 ...
- 06-看图理解数据结构与算法系列(AVL树)
AVL树 AVL树,也称平衡二叉搜索树,AVL是其发明者姓名简写.AVL树属于树的一种,而且它也是一棵二叉搜索树,不同的是他通过一定机制能保证二叉搜索树的平衡,平衡的二叉搜索树的查询效率更高. AVL ...
随机推荐
- 数据结构 -- Trie字典树
简介 字典树:又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种. 优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高. 性质: 1. 根节 ...
- Windows注册表中修改UAC(用户账号控制)及批处理脚本
注册表路径: HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System 键说明: ConsentProm ...
- 【C++札记】标准模板库string
介绍 c++中字符串string对象属于一个类,内置了很多实用的成员函数,操作简单,方便更直观. 命名空间为std,所属头文件<string> 注意:不是<string.h>. ...
- 20190705-Python数据驱动之DDT
DDT ddt 是第三方模块,需安装, pip install ddt DDT包含的装饰器 包含一个类装饰器@ddt和两个方法装饰器@data和@file_data 通常情况下,@data中的数据按照 ...
- web.xml 转 学习!http://www.cnblogs.com/wkrbky/p/5929943.html
1.spring 框架解决字符串编码问题:过滤器 CharacterEncodingFilter(filter-name) 2.在web.xml配置监听器ContextLoaderListener(l ...
- java封装数据类型——Integer
今天来学习整型 int 的封装数据类型,Integer. 1. 定义 首先来看看定义.可以看到,Integer 继承 Number 抽象类,实现了 Comparable 接口.Number 类是常用数 ...
- 微信小程序tabBar与redirectTo 或navigateTo冲突
微信小程序tabBar与redirectTo 或navigateTo冲突 tabBar设置的pagePath无法再次被redirectTo或navigateTo引用 导致跳转失败,更改为swithTa ...
- ant design pro超详细入门教程
1.Ant Design Pro 初了解 说到ant design pro,得先了解一下ant design是个什么东西?ant design蚂蚁金服基于react打造的一个服务于企业级产品的UI框架 ...
- Axure流程图
什么是流程图 一个流程图可用于展示各种各样的处理流程,包括用例流程.商业流程.页面流程等.在Axure中,流程图常用于提供一个高保真的.能通过所设计的页面来完成的任务视图.一张简明的流程图,能促进和其 ...
- rabbit MQ 的环境及命令使用(一)
RabbitMQ依赖erlang,所以先安装erlang,然后再安装RabbitMQ; 先安装erlang,双击erlang的安装文件即可,然后配置环境变量: ERLANG_HOME=D:\Progr ...