7.2 有序表查找

先对线性表进行有序排列,之后进行查找

主要有折半查找,插值查找和斐波那契查找

它们的时间复杂度均是O(logn),显然远远好于顺序查找的O(n)。但就平均性能来说,斐波那契查找要优于折半查找。可惜如果是最坏的情况,key=1,那么始终都处于左侧长半区在查找,则查找效率要低于折半查找。

还有比较关键的一点,折半查找是进行加法与除法运算,插值查找进行复杂的四则运算,而斐波那契查找只是进行最简单的加法运算,这种细微差别会影响最终的查找效率。

下面我们就用php来描述这三种算法

<?php
header("content-type:text/html;charset=utf-8");
/**
 *有序表查找操作
 *
 *包括
 * 1.初始化 __contruct()
 * 2.二分查找 binary_search()
 * 3.插值查找 insert_search()
 * 4.斐波那契查找 fibinacci_search()

 */
class Order_search{
    private $a;
    private $length;

    //初始化
    public function __construct($a = array())
    {
        $this->length = count($a);
        for ($i = 1;$i<=$this->length;$i++){
            $this->a[$i] = $a[$i-1];
        }

    }

    //二分查找
    public function binary_search($key){

        $low = 1;                         //定义最低下标为记录首位
        $high = $this->length;           //定义最高下标为记录末位
        while ($low<=$high){
            $mid = intval(($low+$high)/2);//折半

            if($key<$this->a[$mid]){     //若查找值比中值小
                $high = $mid - 1;        //最高下标调整到中值下标小一位
            }
            elseif ($key>$this->a[$mid]){//若查找值比中值大
                $low = $mid + 1;          //最高下标调整到中值下标大一位
            }
            else
                return $mid;            //若相等则说明mid即为查找到的位置
        }
        return 0;
    }

    //插值查找

    public function insert_search($key){

        $low = 1;
        $high = $this->length;
        while ($low<=$high){
            $mid = intval($low + ($high-$low) * ($key - $this->a[$low]) / ($this->a[$high] - $this->a[$low]));

            if($key<$this->a[$mid]){
                $high = $mid - 1;
            }
            elseif ($key>$this->a[$mid]){
                $low = $mid + 1;
            }
            else
                return $mid;
        }
        return 0;
    }

    //斐波那契查找
    //为了实现斐波那契查找算法,我们首先要准备一个斐波那契数列

    function Fbi($i){
        if($i < 2){
            return ($i == 0 ? 0 : 1);
        }
        return $this->Fbi($i - 1) + $this->Fbi($i - 2);
    }

    function fibinacci_search($key){
        $low = 1;                                               //定义最低下标为记录首位
        $high = $this->length;                                 //定义最高下标为记录末位
        $k = 0;
        while ($this->length>$this->Fbi($k)-1){               //计算n位于斐波那契数列的位置
            $k++;
        }
        for ($i = $this->length;$i<$this->Fbi($k)-1;$i++){    //将不满的数值补全
            $this->a[$i] = $this->a[$this->length];
        }
        while ($low<=$high){
            $mid = $low + $this->Fbi($k-1)-1;                  //计算当前分隔的下标
            if($key<$this->a[$mid]){                          //若查找记录小于当前分隔记录
                $high = $mid - 1;                             //最高下标调整到分隔下标mid-1处
                $k = $k -1;                                   //斐波那契下标减一位
            }
            elseif ($key > $this->a[$mid]){                 //若查找记录大于当前分隔记录
                $low = $mid + 1;                             //最高下标调整到分隔下标mid+1处
                $k = $k -2;                                  //斐波那契下标减2位
            }
            else{
                if($mid <= $this->length)
                    return $mid;                           //若相等则说明mid即为查找到的位置
                else
                    return $this->length;                 //若mid>数组长度说明是补全数值,返回长度
            }
        }
        return 0 ;
    }

}
?>

实现上述函数:

<?php
header("content-type:text/html;charset=utf-8");
include "order_search.class.php";

$a = array(0,1,16,24,35,47,59,62,73,88,99);
echo "初始化数组:";
echo "</br>";
$order_search = new Order_search($a);
print_r($order_search);
echo "</br>";
echo "</br>";

echo "二分查找显示62在数组中的位置:";
echo "</br>";
$key = $order_search->binary_search(62);
echo $key;
echo "</br>";
echo "</br>";

echo "插值查找显示73在数组中的位置:";
echo "</br>";
$key = $order_search->insert_search(73);
echo $key;
echo "</br>";
echo "</br>";

echo "斐波那契查找显示35在数组中的位置:";
echo "</br>";
$key = $order_search->fibinacci_search(35);
echo $key;
?>

最后的实现结果:

三种查找算法本质上是分割点的选择不同,各有优劣。

原文地址:https://www.cnblogs.com/xlzfdddd/p/9893143.html

时间: 2024-08-03 03:43:17

7.2 有序表查找的相关文章

顺序表查找和有序表查找

查找里面顺比表查找和有序表查找(包括二分查找,插值查找,斐波那契查找)比较简单,直接贴代码,代码里面有详细注释. 1 #include <iostream> 2 using namespace std; 3 4 //顺序表查找(线性查找.静态表查找) 时间复杂度为O(n) 5 int Seq_Search(int *s,int n,int key) 6 { 7 s[0] = key; //设置了一个哨兵,避免了每次比较一次过后都要判断查找位置是否越界 8 int i = n; 9 while

15.有序表查找与线索索引查找

转载请表明出处:http://blog.csdn.net/u012637501 一.有序表查找 1.折半查找/二分查找算法 (1)基本思想:在顺序存储的有序表中,取中间纪录(a[mid]=key)作为比较对象,若给定值与中间纪录的关键字相等,则查找成功:若给定值小于中间纪录的关键字,则在中间纪录的左半区继续查找:若给定值大于中间纪录的关键字,则在中间纪录的右半边.不断重复上述过程,直到查找成功,或所有查找区域无记录,查找失败为止. (2)使用条件:线性表中的纪录是关键码有序的(通常是从小到大有序

算法学习之查找算法:静态查找表(2)有序表查找

如果静态查找表是一个有序表,则可以使用折半查找. 折半查找的过程是:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止.折半查找过程是以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等于给定值或者查找区间的大小小于零时(表明查找不成功)为止. 关键字key与表中某一元素array[i]比较,有3种情况: 1.key==array[i],查找成功 2.key > array[i],待查找元素可能的范围是a

(java)有序表查找——折半查找,插值查找,斐波那契查找

有序表查找 /* 主函数 */ public class OrderTableSearch { public static void main(String[] args) { int [] a= {0,1,16,24,35,47,59,62,73,88,99}; System.out.println(FibonacciSearch(a, 10, 88)); System.out.println(InsertKeySearch(a, 10, 88)); System.out.println(Bi

有序表查找算法(折半,插值,斐波那契)

今天总结了有序表查找常用的三种算法与大家分享. 1.折半查找折半查找又称二分查找,它的基本思想是:在有序表中,取中间记录作为比较对象,若相等则查找成功:若给定值小于中间记录的关键字,则在中间记录左半区继续查找,若给定值大于中间值,则在又半区寻找,不断重复以上过程. 算法代码(java版) int binarySearch(int[] a,int key){ int low,high,mid; low = 0; high = a.length-1; while(low<=high){ mid =

数据结构(六)查找---有序表查找(三种查找方式:折半,插值,斐波拉契查找)

前提 有序表查找要求我们的数据是有序的,是排序好的,我们只需要进行查找即可 我们下面将介绍折半查找(二分查找),插值查找,斐波那契查找 一:折半查找 (一)定义 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. (二)查找过程 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功:否则利用中间位置记录将表分成前.后两个子表,如果中间位置记录的关

java数据结构之有序表查找

这篇文章是关于有序表的查找,主要包括了顺序查找的优化用法.折半查找.插值查找.斐波那契查找: 顺序优化查找:效率极为底下,但是算法简单,适用于小型数据查找: 折半查找:又称为二分查找,它是从查找表的中间开始查找.查找结果只需要找其中一半的数据记录即可.效率较顺序查找提高不少.比较适用与静态表,一次排序后不在变化: 插值查找:与折半查找比较相似,只是把中间之mid的公式进行了变换将mid = (low+high)/2;换成了mid = low + (high - low) * (key - sum

[从今天开始修炼数据结构]有序表查找

一.折半查找 1,折半查找也没啥好说的,就跟大家翻微信通讯录一样,你想找个姓杨的,你随手往下一划,划到了个姓李的,那这时候你肯定要从李往下划,李之上的区域直接被你排除了. 所以我们要两个引用,一个指向首,一个指向尾,再要另外一个指针指向中间,你拿目标value跟midValue比较一下,就知道目标再mid之前还是之后了.假如说在mid之前,这时候你让指向尾部的引用,改为指向mid-1的位置,mid指向此时的首尾之间,继续比较,直到找到目标. 2,代码实现 package Search.Order

查找 - 有序表查找

#include<cstdio> #include<cstdlib> #include<cstring> //折半查找 int Binary_Search(int *a,int n,int key){ int cnt = 0; int low,high,mid; low = 1; high = n; while(low <= high){ cnt++; mid = (low + high) >> 1; // 算术位运算 if(key < a[mi