走进数据结构和算法(c++版)(14)——查找

本文详细介绍了查找算法的基础概念及各类查找技术,包括顺序查找、折半查找、插值查找和斐波那契查找,并提供了每种查找方法的具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

查找

  在生活中,我们经常需要进行查找操作,例如从一本字典中查找一个单词,从图书馆的书架上找到我们需要的书。在数据结构中我们把由同一类型的数据元素(或记录)构成的集合叫做查找表( Search Table)关键字(Key) 是数据元素中某个数据项的值,又称为键值。查找( Searchìng )就是根据给定的某个值, 在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
  查找表按照操作方式来分有两大种:静态查找表动态查找表。静态查找表只作查找操作的查找表。动态查找表在查找过程中同时插入查找表中不存在的数据元素, 或者从查找表中删除已经存在的某个数据元素。

1.顺序表查找

  顺序查找又叫线性查找,是最基本的查找技术, 它的查找过程是:从表中第一个(或最后一个)记录开始, 逐个进行记亲的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功, 找到所查的记录;如果直到最后一个(或第一个)记录,其关键字和给定值比较都不等时,则表中没有所查的记录,查找不成功。代码如下:

#include<iostream>
#include<vector>
using namespace std;
int Sequential_Search(vector<int> &a, int key);
int main()
{
    vector<int> a;
    int n,val;
    cout << "输入数组元素个数:";
    cin >> n;
    cout << "输入数组元素:" << endl;
    for (int i = 0; i < n; i++)
    {
        cin >> val;
        a.push_back(val);
    }
    cout << "输入需查询的值:";
    cin >> val;
    val = Sequential_Search(a, val);
    if (-1==val)
        cout << "查找失败:"<<endl;
    else
    {
        cout << "在数组中的位置下标:" << val<<endl;
    }
    system("pause");
    return 0;
}
int Sequential_Search(vector<int> &a,int key)//顺序查找
{
    int n = a.size();
    for (int i = 0; i < n; i++)
    {
        if (a[i] == key)return i;
    }
    return -1;
}

  在VS上运行结果如下:
1

顺序表查找优化

  在查找方向的尽头放置”哨兵”免去了在查找过程中每一次比较后都要判断查找位置是否越界。代码如下:

#include<iostream>
#include<vector>
using namespace std;
int Sequential_Search2(vector<int> a, int key);
int main()
{
    vector<int> a;
    int n,val;
    cout << "输入数组元素个数:";
    cin >> n;
    cout << "输入数组元素:" << endl;
    for (int i = 0; i < n; i++)
    {
        cin >> val;
        a.push_back(val);
    }
    cout << "输入需查询的值:";
    cin >> val;
    val = Sequential_Search2(a, val);
    if (-1==val)
        cout << "查找失败:"<<endl;
    else
    {
        cout << "在数组中的位置下标:" << val<<endl;
    }
    system("pause");
    return 0;
}
int Sequential_Search2(vector<int> a, int key)//有哨兵的顺序查找
{
    int n = a.size(), i = 0;
    a.push_back(key);//添加哨兵
    while (a[i] != key)i++;
    return i==n?-1:i;
}

  在VS上运行结果如下:
2

2.有序表查找

折半查找

  折半查找( Binary Search ) 技术,又称为二分查找。它的前提是线性表中的记录必须是关键码有序(通常从小到大有序) ,线性表必须采用顺序存储。折半查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所有查找区域无记录,查找失败为止。

#include<iostream>
#include<vector>
using namespace std;
int Binaxy_Search(vector<int> a, int key);//折半查找
int main()
{
    vector<int> a;
    int n,val;
    cout << "输入数组元素个数:";
    cin >> n;
    cout << "从小到大输入数组元素:" << endl;
    for (int i = 0; i < n; i++)
    {
        cin >> val;
        a.push_back(val);
    }
    cout << "输入需查询的值:";
    cin >> val;
    val = Binaxy_Search(a, val);
    if (-1==val)
        cout << "查找失败:"<<endl;
    else
    {
        cout << "在数组中的位置下标:" << val<<endl;
    }
    system("pause");
    return 0;
}
int Binaxy_Search(vector<int> a, int key)//折半查找
{
    int low, high, mid;
    low = 0;
    high = a.size() - 1;
    while (low <= high)
    {
        mid = (low + high) / 2;
        if (key<a[mid])
            high = mid - 1;
        else if (key>a[mid])
            low = mid + 1;
        else
            return mid;

    }
    return -1;
}

  在VS上运行结果如下:
3

插值查找

  插值查找(Interpolation Search)是根据要查找的关键字key 与查找表中最大最小记录的关键字比较后的查找方法。就是令折半查找中的mid=low+(highlow)(keya[low])/(a[high]a[low])mid=low+(high−low)∗(key−a[low])/(a[high]−a[low])。代码如下:

#include<iostream>
#include<vector>
using namespace std;

int Interpolation_Search(vector<int> a, int key);//插值查找
int main()
{
    vector<int> a;
    int n,val;
    cout << "输入数组元素个数:";
    cin >> n;
    cout << "从小到大输入数组元素:" << endl;
    for (int i = 0; i < n; i++)
    {
        cin >> val;
        a.push_back(val);
    }
    cout << "输入需查询的值:";
    cin >> val;
    val = Interpolation_Search(a, val);
    if (-1==val)
        cout << "查找失败:"<<endl;
    else
    {
        cout << "在数组中的位置下标:" << val<<endl;
    }
    system("pause");
    return 0;
}
int Interpolation_Search(vector<int> a, int key)//插值查找
{
    int low, high, mid;
    low = 0;
    high = a.size() - 1;
    while (low <= high)
    {
        mid = low+(high-low)*(key-a[low])/(a[high]-a[low]);
        if (key<a[mid])
            high = mid - 1;
        else if (key>a[mid])
            low = mid + 1;
        else
            return mid;

    }
    return -1;
}

  在VS上运行结果如下:
4

斐波那契查找

  斐波那契查找(Fibonacci Seach)时,它是利用了黄金分割原理来实现。即插值查找中的比例为黄金分割比例。因为斐波那契数列F(i)/F(i+1)i=0,1,2,...F(i)/F(i+1)(i=0,1,2,...)结构近似黄金分割比例。代码如下:

#include<iostream>
#include<vector>
using namespace std;

int F(int i);//斐波那契数列
int Fibonacci_Seach(vector<int> a, int key);//斐波那契查找
int main()
{
    vector<int> a;
    int n,val;
    cout << "输入数组元素个数:";
    cin >> n;
    cout << "从小到大输入数组元素:" << endl;
    for (int i = 0; i < n; i++)
    {
        cin >> val;
        a.push_back(val);
    }
    cout << "输入需查询的值:";
    cin >> val;
    val = Fibonacci_Seach(a, val);
    if (-1==val)
        cout << "查找失败:"<<endl;
    else
    {
        cout << "在数组中的位置下标:" << val<<endl;
    }
    system("pause");
    return 0;
}
int Fibonacci_Seach(vector<int> a, int key)//斐波那契查找
{
    int low, high, mid,i,k;
    low = 0;
    int n = a.size();
    high = n-1;
    k = 0;
    while (a.size() > F(k))k++;
    for (int i = 0; i < (F(k) - high - 1); i++)
        a.push_back(a[high]);
    while (high >= low)
    {
        mid = low + F(k - 1);
        if (key < a[mid])
        {
            high = mid - 1;
            k = k - 1;
        }
        else if (key > a[mid])
        {
            low = mid + 1;
            k = k - 2;
        }
        else
        {
            if (mid <= n)
                return mid;
            else
                return n;
        }
    }
    return -1;
}
int F(int i)//斐波那契数列
{
    if (i ==0)return 0;
    if (i == 1)return 1;
    return F(i - 2) + F(i - 1);
}

  在VS上运行结果如下:
5

内含资源如下: 1.基本数据结构 1.1.Array ........... 动态数组 1.2.LinkedList ... 链表 1.3.BST .............. 二分搜索树 1.4.MapBST ..... 二分搜索树(用于实现映射) 1.5.AVLTree ...... AVL树 2.接口 2.1.Queue ........... 队列接口 2.2.Stack .............. 栈接口 2.3.Set .................. 集合接口 2.4.Map ............... 映射接口 2.5.Merger .......... 自定义函数接口 2.6.UnionFind ..... 并查集接口 3.高级数据结构 3.1.ArrayQueue .......................... 队列_基于动态数组实现 3.2.LinkedListQueue .................. 队列__基于链表实现 3.3.LoopQueue ........................... 循环队列_基于动态数组实现 3.4.PriorityQueue ....................... 优先队列_基于最大二叉堆实现 3.5.ArrayPriorityQueue ............. 优先队列_基于动态数组实现 3.6.LinkedListPriorityQueue ..... 优先队列_基于链表实现 3.7.ArrayStack ............................. 栈_基于动态数组实现 3.8.LinkedListStack ..................... 栈_基于链表实现 3.9.BSTSet ..................................... 集合_基于二分搜索树实现 3.10.LinkedListSet ....................... 集合_基于链表实现 3.11.BSTMap ................................ 映射_基于二分搜索树实现 3.12.AVLTreeMap ....................... 映射_ 基于AVL树实现 3.13.LinkedListMap .................... 映射_基于链表实现 3.14.MaxHeap ............................. 最大二叉堆 3.15.SegmentTree ...................... 线段树 3.16.Trie ......................................... 字典树 3.17.QuickFind ............................ 并查集_基于数组实现 3.18.QuickUnion ......................... 并查集_基于树思想实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不放弃的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值