7.2 有序表查找

Posted xlzfdddd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
?>

最后的实现结果:

技术分享图片

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

以上是关于7.2 有序表查找的主要内容,如果未能解决你的问题,请参考以下文章

折半查找的概念及实现代码

线性结构--二分查找

顺序表 | 根据两个有序表查找合并后的中位数

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

插值查找-有序表查找_20230411

[Algorithm]二分插值斐波那契查找算法 Java 代码实现