经典查找算法总结(上)

查找算法们(java)

                               顺序查找
                               二分查找
                               插值查找
                               斐波那契查找
                               树表查找
                               分块查找
                               哈希查找

一、顺序查找
描述
遍历数组,依次比较,直到找到目标元素。
条件
数组可以乱序可以有序,只要是可遍历的线性结构。
平均查找次数:(n+1)/2
时间复杂度:O(n)
代码:

public int seqSearch(int[] array,int target) {
  //顺序查找
  for(int i = 0;i < array.length;i ++) {
   if(array[i] == target) {
    return i;
   }
  }
  return -1;
 }

二、二分查找(折半查找)
描述
每次将中点的元素与target做比较,若大于target,(以升序排列为 例)查找区间改为左半部分;若小于target,查找区间改为右半部分,在新的查找区间里再找中点的元素与target作比较,若不相等,再改变查找区间…直到找到目标元素(即中点元素等于target)。
条件
数组必须是有序的
平均查找次数:log2n
时间复杂度:O(logn)
代码

public static int binarySearch(int[] array,int target) {
  //二分查找(以数组升序排列为例)
  int left = 0;
  int right = array.length-1;
  while(left <= right) {
   int mid = (left + right)/2;
   if(array[mid] == target) {
    return mid;
   }else if(array[mid] > target) {
    right = mid - 1;
   }else {
    left = mid + 1;
   }
  }
  return -1;
 }

三、插值查找
描述
插值查找是二分查找的改进,二分查找是每次对数组下标的mid处查找,插值查找加入了数组中元素值的影响,每次从自适应的mid处查找。把二分法的(以数组升序排列为例)mid = (right+left)/2 = left+(right-left)/2公式,改为
mid = left+(right-left)*(target-array[left])/(array[right]-array[left])
条件
数组必须是有序的
时间复杂度:O(loglogn)
代码

public static int insertValueSearch(int[] array,int target) {
 //插值查找(以数组升序排列为例)
  int left = 0;
  int right = array.length - 1;
  if(target < array[left] || target > array[right])
   return -1;
  while(left <= right) {
   int mid = left + (right - left)*(target - array[left])/(array[right] - array[left]);
   if(array[mid] == target) {
    return mid;
   }else if(array[mid] > target) {
    right = mid - 1;
   }else {
    left = mid + 1;
   }
  }
  return -1;
 }

四、斐波那契查找
描述
斐波那契数列:fibonacci[0]=fibonacci[1]=1,
fibonacci[n]= fibonacci[n-1]+fibonacci[n-2]
n越大时fibonacci[n]/fibonacci[n-1]的值越接近黄金比例0.618,
斐波那契查找按照斐波那契函数进行分割,对于长度为fibonacci[n]的数组,进行分割时分割成fibonacci[n-1]长的前半部分和fibonacci[n-2]长的后半部分。找出最接近数组长度且大于数组长度的fibonacci函数值,多出的部分全部补充为数组最后一个元素。便于理解如图
在这里插入图片描述
条件:数组必须是有序的
时间复杂度:O(logn)
代码

//斐波那契查找
 private static int maxsize = 20;
 public static int[] getFibonacci() {
 //生成斐波那契数列
  int[] fib = new int[maxsize];
  fib[0] = 1;
  fib[1] = 1;
  for(int i = 2;i < maxsize;i ++) {
   fib[i] = fib[i-1] + fib[i-2];
  }
  return fib;
 }
 public static int fibonacciSearch(int[] array,int target) {
 //查找
  int left = 0;
  int right = array.length - 1;
  int[] fib = getFibonacci();//获取斐波那契数列
  int k = 0;//斐波那契分割数下标
  while(right > fib[k]) {
   k ++;
  }
  //构造k长度的新数组并把array里的元素拷贝过来
  int[] temp = Arrays.copyOf(array, fib[k]);
  //对新数组进行元素补充
  for(int i = right + 1;i < k;i ++) {
   temp[i] = array[right];
  }
  while(left <= right) {
   int mid = left + fib[k-1] - 1;
   if(temp[mid] > target) {
    right = mid - 1;
    //判断target在前半部分,而前半部分有fib[k-1]个元素,
    //可以再分成fib[k-1]=fib[k-2]+fib[k-3],则下次循环就是k-2即在原来(k-1)的基础上减一
    k -= 1;
   }else if(temp[mid] < target) {
    left = mid + 1;
    //判断target在后半部分,而后半部分有fib[k-2]个元素,
    //可以再分成fib[k-2]=fib[k-3]+fib[k-4],则下次循环就是k-3即在原来(k-1)的基础上减二
    k -= 2;
   }else {
    //target=array[mid]的情况,此时要判断结果是否在补充的元素中,若在的话就返回原数组的最后一位
    if(mid <= array.length-1) {
     return mid;
    }else {
     return array.length-1;
    }
   }
  }
  return -1;
 }

五、树表查找
描述:只介绍一种最简单的树表查找:二叉搜索树
二叉搜索树(又称二叉排序树),是一种对查找和排序都很有用的特殊二叉树。
二叉搜索树可以是空树,也可以是满足如下性质的二叉树:
(1)若其左子树非空,则左子树上所有节点的值均小于根节点的值;
(2)若其右子树非空,则右子树上所有节点的值均大于等于根节点的值;
即二叉搜索树中序遍历后会得到一个关键字递增的有序序列。
查找时先用数组构建一个二叉搜索树(尽量构建成一个平衡二叉树),然后对该二叉搜索树进行查找,
查找时,如果target等于根节点,则返回根节点地址,
如果target大于根节点,则继续查找右子树,
如果target小于 根节点,则继续查找左子树。
时间复杂度:二叉树有n个节点
如果二叉搜索树是平衡的,则其深度为log2n +1,时间复杂度为O(logn)
若果二叉搜索树完全不平衡,则其深度可能达到n,查找效率退化为O(n).
所以,一般二叉搜索树的查找时间复杂度在O(logn)和O(n)之间。
代码

//简单树表查找(二叉搜索树)
 public static TreeNode sortArrayTOtree(int[] array) {
 //把待查找数组构建成一个二叉搜索树
  int end = array.length;
  if(end <= 0) 
   return null;
  return buildTree(array,0,end-1);
 }
 public static TreeNode buildTree(int[] array,int start,int end) {
 //构建二叉搜索树
  if(start <= end) {
   int mid = (start + end)/2;
   //把数组中间的元素设置为二叉树根节点的数值
   TreeNode root = new TreeNode(array[mid]);
   root.left = buildTree(array, start, mid-1);
   root.right = buildTree(array, mid+1, end);
   return root;
  }else {
   return null;
  }
 }
 public static TreeNode binaryTreeSearch(int[] array,int target) {
  TreeNode root = sortArrayTOtree(array);
  if(root == null) 
   return null;
  TreeNode temp = root;
  while(temp != null) {
   //若根节点大于目标元素,则目标元素在其左子树上
   if(temp.data > target) {
    temp = temp.left;
    //若左子树为空,则目标元素不在该二叉树上,返回空
    if(temp == null) {
     return null;
    }
   }
   //若根节点小于目标元素,则目标元素在其右子树上
   if(temp.data < target) {
    temp = temp.right;
    //若右子树为空,则目标元素不在该二叉树上,返回空
    if(temp == null) {
     return null;
    }
   }
   if(temp.data == target) {
    return temp;
   }
  }
  return null; 
  
 }

二叉树的基本数据类型:

public class TreeNode {
 int data;//存放当前节点的数据
 TreeNode left;//当前节点的左子树
 TreeNode right;//当前节点的右子树
 TreeNode root;//根节点
 
 //实现各个变量的get,set方法
 public int getData() {
  return data;
 }
 public void setData(int data) {
  this.data = data;
 }
 
 public TreeNode getLeft(TreeNode left) {
  return left;
 }
 public void setLeft(TreeNode left) {
  this.left = left;
 }
 
 public TreeNode getRight(TreeNode right) {
  return right;
 }
 public void setRight(TreeNode right) {
  this.right = right;
 }
 
 public TreeNode getRoot(TreeNode root) {
  return root;
 }
 public void setRoot(TreeNode root) {
  this.left = root;
 }
 
 
 public TreeNode(int data) {
  this.data = data;
 }
 public TreeNode() {
  
 }
}

分块查找和哈希查找待更

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值