头歌(C语言)-数据结构与算法-查找-第1关:实现折半查找


任务描述

本关要求通过补全函数BSL_FindKey来实现在已排序的顺序表中查找关键码值为key的结点并返回该结点的编号。

相关知识

折半查找通常是针对顺序存储的线性表,线性表的结点按关键码从小到大排序,后面称之为折半查找的顺序表。为了简化讨论,假设折半查找的顺序表中每个结点只含一个关键码,关键码为整数。图 1 给出了一个存储了 4 个关键码的折半查找的顺序表的存储结构图。

下面描述了线性表顺序存储的一种实现方案。该实现方案的示意图为:

指针pkey是存储关键码的连续空间的起始地址,顺序表中当前的关键码的个数由len给出,该顺序表中最多可存储max个关键码。

pkeylenmax组织成一个结构,该结构定义为:

 
  1. struct BSeqList{
  2. int* pkey; // 指向关键码数组的指针
  3. int len; // 当前元素个数
  4. int max; // 线性表的最大元素数
  5. };

只要给定指向该结构的一指针blist,就可对线性表进行操作。

对折半查找的顺序表定义如下操作,各个操作函数的功能详见下面给出的代码文件 BSlist.cpp 的代码框架:

 
  1. BSeqList* BSL_Create(int size);
  2. void BSL_Free(BSeqList* blist);
  3. int BSL_InsKey(BSeqList* blist, int key);
  4. int BSL_FindKey(BSeqList* blist, int key);
  5. int BSL_DelKey(BSeqList* blist, int key);
  6. void BSL_Print(BSeqList* blist);

编程要求

本关的编程任务是补全 step1/BSlist.cpp 文件中的BSL_FindKey函数,以实现在已排序的顺序表中查找关键码值为key的结点并返回该结点的编号。当返回值大于等于 0 时则表示找到值为key的结点的编号,若为 -1 则表示没有找到。

  • 具体请参见后续测试样例。

本关涉及的代码文件 BSlist.cpp 的代码框架如下:

 
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "bsList.h"
  4. BSeqList* BSL_Create(int size)
  5. //创建一个顺序表
  6. //与BSL_Free()配对
  7. {
  8. BSeqList* blist=(BSeqList*)malloc(sizeof(BSeqList));
  9. blist->pkey = (int*)malloc(sizeof(int)*size);
  10. blist->max=size;
  11. blist->len=0;
  12. return blist;
  13. }
  14. void BSL_Free(BSeqList* blist)
  15. //释放/删除顺序表
  16. //与BSL_Create()配对
  17. {
  18. free(blist->pkey);
  19. free(blist);
  20. }
  21. int BSL_FindKey(BSeqList* blist, int key)
  22. //在排序的顺序表中查找关键码值为key的结点,返回结点的编号
  23. //返回值大于等于0时表示找到值为key的结点的编号,-1表示没有找到
  24. {
  25. // 请在此添加代码,补全函数BSL_FindKey
  26. /********** Begin *********/
  27. /********** End **********/
  28. }
  29. int BSL_InsKey(BSeqList* blist, int key)
  30. //在排序的顺序表中插入一个值为key的结点
  31. //返回值大于等于0表示插入的位置, -1表示表满(无法插入)
  32. {
  33. if (blist->len>=blist->max) return -1;
  34. int k, r, m;
  35. k=0; r=blist->len-1;
  36. //寻找插入位置
  37. while (k<=r) {
  38. m=(k+r)>>1; //m=(k+r)/2
  39. if (key == blist->pkey[m]) return -2;若不允许插入已存在的值,则需要此行
  40. if (key<blist->pkey[m]) r=m-1;
  41. else k=m+1;
  42. }
  43. //插入位置为k, 腾出k号位置
  44. for (r=blist->len; r>k; r--)
  45. blist->pkey[r]=blist->pkey[r-1];
  46. //key放入k号位置
  47. blist->pkey[k]=key;
  48. blist->len++;
  49. return k;
  50. }
  51. int BSL_DelKey(BSeqList* blist, int key)
  52. //在排序的顺序表中删除值为key的结点,
  53. //存在值为x的结点则返回结点编号, 未找到返回-1
  54. {
  55. int k=BSL_FindKey(blist, key);
  56. if (k<0) return -1;
  57. int i=k;
  58. while(i < blist->len-1) {
  59. blist->pkey[i] = blist->pkey[i+1];
  60. i++;
  61. }
  62. blist->len --;
  63. return k;
  64. }
  65. void BSL_Print(BSeqList* blist)
  66. //打印整个顺序表
  67. {
  68. if (blist->len==0) {
  69. printf("The list is empty.\n");
  70. return;
  71. }
  72. printf("The list contains: ");
  73. for (int i=0; i<blist->len; i++) {
  74. printf("%d ", blist->pkey[i]);
  75. }
  76. printf("\n");
  77. }

测试说明

本关的测试文件是 step1/Main.cpp ,测试过程如下:

  1. 平台编译 step1/Main.cpp ,然后链接相关程序库并生成 exe 可执行文件;

  2. 平台运行该 exe 可执行文件,并以标准输入方式提供测试输入;

  3. 平台获取该 exe 可执行文件的输出,然后将其与预期输出对比,如果一致则测试通过;否则测试失败。

输入输出格式说明

输入格式: 首先输入一个正整数max,创建一个最多可存储max个元素的表。 然后输入多个操作:如果输入 “insert” ,则后面跟一个数x,表示将x插入;如果输入 “delete” ,则后面跟一个数x,表示将x删除;如果输入 “end” ,表示输入结束。

输出格式: 输出表的长度,然后从表头到表尾依次输出各元素。

以下是平台对 step1/Main.cpp 的样例测试集:

样例输入: 9 insert 9 insert 8 insert 89 insert 11 insert 22 insert 13 delete 11 delete 5 end

样例输出: list length: 5 The list contains: 8 9 13 22 89

代码: 

//折半查找的顺序表 实现文件
//每个结点的数据是关键码
//
#include <stdio.h>
#include <stdlib.h>
#include "BSlist.h"

BSeqList* BSL_Create(int size)
//创建一个顺序表
//与BSL_Free()配对
{
    BSeqList* blist=(BSeqList*)malloc(sizeof(BSeqList));
    blist->pkey = (int*)malloc(sizeof(int)*size);
    blist->max=size;
    blist->len=0;
    return blist;
}

void BSL_Free(BSeqList* blist)
//释放/删除顺序表
//与BSL_Create()配对
{
    free(blist->pkey);
    free(blist);
}

int BSL_FindKey(BSeqList* blist, int key)
//在排序的顺序表中查找关键码值为key的结点,返回结点的编号
//返回值大于等于0时表示找到值为key的结点的编号,-1表示没有找到
{
    /*请在BEGIN和END之间实现你的代码*/
    /*****BEGIN*****/
    int l=0,r = blist->len-1,mid = (l+r)/2;
    while(l<=r)
    {
        if(blist->pkey[mid]==key) return mid;
        else if(blist->pkey[mid]<key)
        {
            l = mid+1;
            mid = (l+r)/2;
        }
        else
        {
            r = mid-1;
            mid = (l+r)/2;
        }
    }
    return -1;
    /******END******/
    /*请不要修改[BEGIN,END]区域外的代码*/
}

int BSL_InsKey(BSeqList* blist, int key)
//在排序的顺序表中插入一个值为key的结点
//返回值大于等于0时表示插入的位置, -1表示表满(无法插入)
{

    if (blist->len>=blist->max) return -1;

    int k, r, m;
    k=0; r=blist->len-1;

    //寻找插入位置
    while (k<=r) {
        m=(k+r)>>1; //m=(k+r)/2
        if (key == blist->pkey[m]) return -2;若不允许插入已存在的值,则需要此行
        if (key<blist->pkey[m])  r=m-1;
        else k=m+1;
    }

    //插入位置为k, 腾出k号位置
    for (r=blist->len; r>k; r--) 
        blist->pkey[r]=blist->pkey[r-1];
    //key放入k号位置
    blist->pkey[k]=key;
    blist->len++;
    return k;
}

int BSL_DelKey(BSeqList* blist, int key)
//在排序的顺序表中删除值为key的结点, 
//存在值为x的结点则返回结点编号, 未找到返回-1
{
    int k=BSL_FindKey(blist, key);
    if (k<0) return -1;
    int i=k;
    while(i < blist->len-1) {
        blist->pkey[i] = blist->pkey[i+1];
        i++;
    }
    blist->len --;
    return k;
}

void BSL_Print(BSeqList* blist)
//打印整个顺序表
{
    if (blist->len==0) {
        printf("The list is empty.\n");
        return;
    }
    printf("The list contains: ");
    for (int i=0; i<blist->len; i++) {
        printf("%d  ", blist->pkey[i]);
    }
    printf("\n");
}

以上内容仅供参考哟,大家还需独立完成,巩固知识点^-^

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
折半查找算法(Binary Search),也称为二分查找,是一种在有序数组中查找特定元素的搜索算法。其基本思想是将数组按照一定的规则分成两部分,判断待查找元素与数组中间元素的大小系,从而确定待查找元素在哪一部分,然后继续在该部分中进行查找,直到找到目标元素或查找失败为止。 以下是一个使用C语言实现折半查找算法的示例代码: ```c #include <stdio.h> int binarySearch(int arr[], int low, int high, int target) { while (low <= high) { int mid = low + (high - low) / 2; if (arr[mid] == target) { return mid; } else if (arr[mid] < target) { low = mid + 1; } else { high = mid - 1; } } return -1; } int main() { int arr[] = {2, 4, 6, 8, 10, 12, 14, 16}; int n = sizeof(arr) / sizeof(arr[0]); int target = 10; int index = binarySearch(arr, 0, n - 1, target); if (index != -1) { printf("Target found at index %d\n", index); } else { printf("Target not found in the array\n"); } return 0; } ``` 在上面的代码中,`binarySearch` 函数接受一个有序数组 `arr`、数组的下界 `low`、上界 `high` 和待查找的目标元素 `target`,返回目标元素在数组中的下标,如果目标元素不存在则返回 `-1`。在 `binarySearch` 函数中,首先计算出中间元素的下标 `mid`,然后判断中间元素和目标元素的大小系,如果相等则返回中间元素的下标,如果中间元素小于目标元素,则在右半部分继续查找,否则在左半部分继续查找,直到找到目标元素或查找失败为止。 在 `main` 函数中,我们定义了一个有序数组 `arr`,并调用 `binarySearch` 函数在数组中查找目标元素 `10`,并输出查找结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值