DS静态查找之顺序索引查找

Description

给出一个队列和要查找的数值,找出数值在队列中的位置,队列位置从1开始

要求使用顺序索引查找算法,其中索引表查找和块内查找都采用不带哨兵、从头开始的顺序查找方法。

Input

第一行输入n,表示主表有n个数据

第二行输入n个数据,都是正整数,用空格隔开

第三行输入k,表示主表划分为k个块,k也是索引表的长度

第四行输入k个数据,表示索引表中每个块的最大值

第五行输入t,表示有t个要查找的数值

第六行起,输入t个数值,输入t行

Output

每行输出一个要查找的数值在队列的位置和查找次数,数据之间用短划线隔开,如果查找不成功,输出字符串error

Sample

#0
Input

Copy

18
22 12 13 8 9 20 33 42 44 38 24 48 60 58 74 57 86 53
3
22 48 86
6
13
5
48
40
53
90
Output

Copy

3-4
error
12-8
error
18-9
error

思路:

本题给出一串序列,并将其分成几块,给出每块中的最大值,然后我们查找的时候,只要在其中一块中查找就好了
如:A块中最大值为22,B块中最大值为50,那如果查找30的时候,30>A最大值20,30<=B最大值50,所以就在B块中查找了

样例:

1.先分块

2.开始查找:

    一:简单点先看在第一块里的:

查找13,13<=22,所以在第一块里,然后在第一块中查找
然后在第一块里找到
查找次数:找在第一块里花了1次查找次数,然后在第一块里找到他从左往右找,找了三次,所以次数总共是4次

二.查找的值的大小在块里,但是那一块里面却没有这个值:

按照大小比较,5<=22,在第一块里,然后查找第一块,第一块里面没有他,所以输出error

三.查找的值存在且在别的块里:

48>22,48<=48,在第二块里(与第一块最大值比较一次是查了一次,与第二块最大值比较一次是第二次)
在第二块最后一个,查找了六次
查找次数:2+6=8

4.查找的值根本不在块里:

90>22,90>48,90>86,不在任何一块里面,所以根本没这个值,输出error


代码细节

1.分块的处理

2.分块的每一块的范围的处理

3.查找

   一:查找在第几块

二:查找在第几块中的第几个位置

tips:flag=1表示查找到了

全部代码:

#include <iostream>
using namespace std;
const int maxn = 1e3 + 10;
int shuzu[maxn];///存所有数据
struct nmax
{
    int val;///存取最大值
    int end;///存取最大值的一部分的最大下标,就是那一块的终点,这一块的起点是前一块终点+1
    ///如 1 2 5 3 4 7 8 10 9
    //分成两块,最大值分别为5 ,10
    //第一块就是 1 2 5 3 4,假设下标从1开始,那第一部分的最大下标就是5,指向4
};
nmax maxshuzu[maxn];//存取每一块的最大值
int main()
{
    int n;
    while (cin >> n)
    {
        for (int i = 1; i <= n; i++)///输出数据
        {
            cin >> shuzu[i];
        }
        int m;
        cin >> m;///输入分成m块
        for (int i = 1; i <= m; i++)
        {
            cin >> maxshuzu[i].val;///输入每一块中的最大值
        }
        maxshuzu[0].end = 0;
        shuzu[n + 1] = 0x3f3f3f;///这里在最后添加一个无穷大
        //我们确定块的范围是大于前一块的地方作为起点,第一个大于这一块的最大值的-1作为终点
        ///如 1 2 5 3 4 7 8 10 9 0x3f3f3f
        //分成两块,最大值分别为5 ,10
        //第二块的位置在7开始,7是第一个大于前一块最大值5,作为起点
        //我们第二块就不知道终点,所以在尾巴放一个无穷大的数,终点就是第一个大于第二块最大值10的位置-1,指向9
        for (int i = 1; i <= m; i++)
        {
            for (int j = 1; j <= n+1; j++)
            {
                if (shuzu[j] > maxshuzu[i].val)//找到大于这一块的最大值的第一个点
                {
                    maxshuzu[i].end = j - 1;
                    break;
                }
            }
        }

        int t;
        cin >> t;///输入查找t次
        while (t--) 
        {
            int num;
            int cnt = 0;///cnt负责统计查找次数
            int flag = 0;///flag状态变量判断是否查找到了
            cin >> num;
            ///先找在第几块里
            int i;///i表示在第几块
            for (i = 1; i <= m; i++)
            {
                cnt++;
                if (num <= maxshuzu[i].val)
                {
                    break;///找到在第i块里
                }
            }
            if (i > m)///i>m表面不在块里,那就没有这个数
            {
                cout << "error" << endl;
                continue;
            }
            int j;//j表示在第i块里第j个位置
            ///在前一块的终点+1作为起点,终点是自己的这一块的末位置
            for (j = maxshuzu[i - 1].end + 1; j <= maxshuzu[i].end; j++)
            {
                cnt++;
                if (shuzu[j] == num)
                {
                    flag = 1;
                    break;
                }
            }
            if (flag)
            {
                cout << j << "-" << cnt << endl;//j就是数据在数组里的下标
            }
            else
            {
                cout << "error" << endl;
            }
        }
    }

}

今天就到这吧!
再见再见再见!!!

  • 26
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值