当前位置: 首页 > article >正文

【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】

目录😋

任务描述

相关知识

一、根据键盘输入的一组有序数据建立顺序表

二、顺序表的输出

三、二分查找算法

测试说明

通关代码

测试结果


任务描述

本关任务:实现二分查找的算法。

相关知识

为了完成本关任务,你需要掌握:

  1. 根据键盘输入的一组有序数据建立顺序表
  2. 顺序表的输出
  3. 二分查找算法

一、根据键盘输入的一组有序数据建立顺序表

  1. 顺序表的概念
    顺序表是线性表的一种存储方式,它用一组地址连续的存储单元依次存储线性表中的数据元素,使得逻辑上相邻的元素在物理存储位置上也相邻。在 C/C++ 等编程语言中,可以使用数组来实现顺序表的底层存储结构。

  2. 建立顺序表的步骤(以 C++ 为例)

  • 定义顺序表结构体
    首先需要定义一个结构体来表示顺序表,结构体中通常包含存储数据的数组、当前顺序表的长度等信息。以下是一个简单的示例代码:
#define MAX_SIZE 100  // 定义顺序表的最大容量

template <typename T>
struct SeqList {
    T data[MAX_SIZE];  // 存储数据的数组
    int length;        // 顺序表当前长度
    SeqList() : length(0) {}  // 构造函数初始化长度为 0
};
  • 从键盘输入数据并构建顺序表
    可以通过cin等输入流来获取用户从键盘输入的数据,然后将这些有序数据依次存入顺序表中,同时更新顺序表的长度。以下是一个简单的代码示例,假设输入的是整数类型的数据且以特定结束标志(比如输入 -1 表示结束输入):
#include <iostream>
using namespace std;

template <typename T>
void createSeqList(SeqList<T>& list) {
    T num;
    cout << "请输入有序数据(输入 -1 结束输入):" << endl;
    while (cin >> num && num!= -1) {
        if (list.length < MAX_SIZE) {
            list.data[list.length++] = num;
        } else {
            cout << "顺序表已满,无法继续添加元素。" << endl;
            break;
        }
    }
}

二、顺序表的输出

输出顺序表就是将顺序表中存储的元素依次展示出来。同样以 C++ 为例,通过遍历顺序表结构体中的数组,按照顺序输出每个元素,示例代码如下:

template <typename T>
void printSeqList(const SeqList<T>& list) {
    cout << "顺序表中的元素为:";
    for (int i = 0; i < list.length; i++) {
        cout << list.data[i] << " ";
    }
    cout << endl;
}

main函数中,可以这样调用上述创建和输出顺序表的函数:

int main() {
    SeqList<int> myList;
    createSeqList(myList);
    printSeqList(myList);
    return 0;
}

三、二分查找算法

  1. 算法原理
    二分查找(也叫折半查找)是一种用于在有序数组(或者说顺序表这种存储有序数据的结构)中查找特定元素的高效算法。它的基本思想是:每次比较中间元素与目标元素的大小,如果中间元素等于目标元素,则查找成功;如果中间元素大于目标元素,则在数组的左半部分继续查找;如果中间元素小于目标元素,则在数组的右半部分继续查找。不断重复这个过程,直到找到目标元素或者确定目标元素不存在为止。

  2. 算法实现步骤(以在上述顺序表中查找为例)
    以下是使用 C++ 实现二分查找算法的代码示例:可以在main函数中调用二分查找函数来查找特定元素,示例如下:

    template <typename T>
    int binarySearch(const SeqList<T>& list, T target) {
        int left = 0;  // 左边界
        int right = list.length - 1;  // 右边界
        while (left <= right) {
            int mid = left + (right - left) / 2;  // 计算中间位置,防止溢出
            if (list.data[mid] == target) {
                return mid;  // 找到目标元素,返回其下标
            } else if (list.data[mid] > target) {
                right = mid - 1;  // 在左半部分继续查找
            } else {
                left = mid + 1;  // 在右半部分继续查找
            }
        }
        return -1;  // 未找到目标元素,返回 -1
    }
    

    可以在main函数中调用二分查找函数来查找特定元素,示例如下:

  3. 算法复杂度分析

  • 时间复杂度:在最好情况下,一次比较就能找到目标元素,时间复杂度为O(1);在最坏情况下,需要不断地对半划分区间,直到区间缩小为 1,此时时间复杂度为 O(logn),其中  是顺序表中元素的个数。平均时间复杂度也是 O(logn),所以二分查找算法在有序数据查找场景下效率较高。

  • 空间复杂度:由于算法在查找过程中只需要使用几个额外的变量(如左右边界、中间位置指针等)来辅助查找,不随数据规模增长而大量占用额外空间,所以空间复杂度为O(1)

测试说明

平台会对你编写的代码进行测试:

测试输入示例:(第一行是输入的一组原始关键字数据,第二行是要查找的关键字)

1 2 3 4 5 6 7 8 9 10 
9

预期输出:

请输入一组数据 : 关键字序列:1 2 3 4 5 6 7 8 9 10
请输入要查找的关键字 :9
查找9的比较过程如下:
第1次比较:在[0,9]中比较元素R[4]:5
 第2次比较:在[5,9]中比较元素R[7]:8
 第3次比较:在[8,9]中比较元素R[8]:9
元素9的位置是9

提示:二分查找算法中要依次输出每次查找的区间,及与k所比较的关键字,用空格分隔开。假设顺序表的关键字序列: 2 3 10 15 20 25 28 29 30 35 40,

如果要查找的关键字k=20,则函数输出如下,并返回值5.
第1次比较: 查找范围R[0...10],比较元素R[5]:25
第2次比较: 查找范围R[0...4],比较元素R[2]:10
第3次比较: 查找范围R[3...4],比较元素R[3]:15
第4次比较: 查找范围R[4...4],比较元素R[4]:20

如果要查找的关键字k=26,则函数要输出如下,并返回值0.
第1次比较: 查找范围R[0...10],比较元素R[5]:25
第2次比较: 查找范围R[6...10],比较元素R[8]:30
第3次比较: 查找范围R[6...7],比较元素R[6]:28

开始你的任务吧,祝你成功!


通关代码

#include <iostream>
#include <vector>
using namespace std;
// 定义查找元素的结构体类型,包含关键字和其他数据(这里暂未详细使用其他数据部分)
struct RecType {
  int key;
  // 可以按需添加其他数据成员及对应操作,此处简化只关注关键字key
};

// 创建顺序表,将输入的关键字数据存入顺序表中
void CreateList(vector<RecType> &R, const vector<int> &keys) {
  for (size_t i = 0; i < keys.size(); ++i) {
    RecType temp;
    temp.key = keys[i];
    R.push_back(temp);
  }
}

// 输出顺序表的函数,遍历顺序表并输出每个元素的关键字
void DispList(const vector<RecType> &R) {
  for (size_t i = 0; i < R.size(); ++i) {
    cout << R[i].key << " ";
  }
  cout << endl;
}

// 二分查找算法实现,按照要求输出每次查找的区间及比较的关键字
int BinSearch(const vector<RecType> &R, int k) {
  int low = 0;
  int high = R.size() - 1;
  int count = 1;
  while (low <= high) {
    int mid = low + (high - low) / 2;
    cout << "  第" << count << "次比较:在[" << low << "," << high
         << "]中比较元素R[" << mid << "]:" << R[mid].key << endl;
    if (R[mid].key == k) {
      return mid + 1; // 返回位置,这里的位置是从1开始计数,所以下标加1
    } else if (R[mid].key > k) {
      high = mid - 1;
    } else {
      low = mid + 1;
    }
    count++;
  }
  return 0; // 如果没找到,返回0表示元素不在表中
}

int main() {
  vector<RecType> R;
  vector<int> keys;
  int n =
      10; // 根据测试示例,这里默认输入数据个数为10,也可以改成让用户输入个数
  cout << "请输入一组数据 :" << endl;
  for (int i = 0; i < n; ++i) {
    int num;
    cin >> num;
    keys.push_back(num);
  }
  CreateList(R, keys);
  cout << "关键字序列:";
  DispList(R);
  int k;
  cin >> k;
  cout << "请输入要查找的关键字 :" << k << endl;
  cout << "查找" << k << "的比较过程如下:" << endl;
  int result = BinSearch(R, k);
  if (result != 0) {
    cout << "元素" << k << "的位置是" << result << endl;
  } else {
    cout << "元素" << k << "不在表中" << endl;
  }
  return 0;
}

测试结果

在这里插入图片描述


http://www.kler.cn/a/470532.html

相关文章:

  • NOVA:AutoRegressive Video Generation Without Vector Quantization——自回归视频生成无需向量量化
  • patchwork++地面分割学习笔记
  • 《鸿蒙微内核与人工智能算法协同,开启智能系统新时代》
  • 51单片机——共阴数码管实验
  • 缓存-Redis-缓存更新策略-主动更新策略-Cache Aside Pattern(全面 易理解)
  • Flutter Web 选取并上传图片
  • 【渗透测试术语总结】
  • Zero to JupyterHub with Kubernetes 下篇 - Jupyterhub on k8s
  • 人工智能的发展领域之GPU加速计算的应用概述、架构介绍与教学过程
  • 【H3CNE邓方鸣】路由协议概述+2025.1.5
  • SQLite 的未来发展与展望
  • 【vue3封装element-plus的反馈组件el-drawer、el-dialog】
  • 解决 IntelliJ IDEA 中 Tomcat 日志乱码问题的详细指南
  • STLG_01_14_程序设计C语言 - 函数与程序结构
  • 基于ROS先验地图的机器人自主定位与导航SLAM
  • 基于单片机的直流稳压电源的设计(论文+源码)
  • 【AIGC-ChatGPT进阶提示词指令】AI美食助手的设计与实现:Lisp风格系统提示词分析
  • jenkins入门9--参数化构建
  • Vue3国际化多语言的切换
  • Linux 浅析sysfs文件系统
  • F#语言的网络编程
  • 水库水位监测系统的自动化功能:减少人工干预,可实现实时监控
  • GraphRAG:LLM之Graphrag接入milvus
  • 【博主推荐】 Microi吾码开源低代码平台,快速建站,提高开发效率
  • Infineon PSoC 4 CapSense ModusToolbox IDE - 系统生态篇
  • 从Linux本地软件存储库安装MySQL