C数据结构与算法——顺序查找和二分查找算法 应用

news2024/12/25 9:31:06

实验任务

(1) 掌握顺序查找算法的实现;
(2) 掌握二分查找算法的实现;
(3) 掌握两种查找算法的时间复杂度与适用场合。

实验内容

(1) 基于顺序查找表实现顺序查找和二分查找算法;
(2) 使用两个不同大小的查找表进行两次理论和实际性能对比;
(3) 根据实验环境调整两次查找表的大小,使得:
      i.第1次查找表的长度 = ⌊ 第2次查找表长度 / 10 ⌋;
      ii.第2次顺序查找的时间介于 [ 9000, 9999 ] ms之间。
(4) 输出实验结果,结果应与如下图1所示尽可能相似。

实验源码

注意:由于编译器优化或电脑编程环境缓存等因素,实际运行和理论值可能有差距

//
// Created by Lenovo on 2022-05-27-上午 9:14.
// 作者:小象
// 版本:1.0
//

#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include <pthread_time.h>
#include <profileapi.h>

#define MAXSIZE 2147483 // int型0~21亿 顺序表可能达到的最大长度10位
#define OK 1
#define ERROR 0

// 数据元素类型定义
typedef struct {
    int key; // 关键字域
    int otherInfo; // 其他域
} ElemType;

// 顺序表定义
typedef struct {
    ElemType *elem; // 存储空间的基地址
    int length; // 当前长度
} SqSTable;

int InitTable(SqSTable *table); // 顺序表的初始化
int CreateTable(SqSTable *table, int length); // 顺序表的创建
double SearchSeq(SqSTable table, int key); // 顺序查找
double SearchSeq_Times(SqSTable table); // 顺序查找完 key 个关键字耗时
double SearchBin(SqSTable table, int key); // 二分查找
double SearchBin_Times(SqSTable table); // 二分查找完 key 个关键字耗时
void PrintResult(int data, double sequentialTimes, double binaryTimes); // 打印最终结果

/**
 * <h2>二分查找 和 顺序查找算法 实验一</h2>
 * <h3>实验要求:</h3>
 * i.第1次查找表的长度 = 第2次查找表长度 / 10; <br>
 * ii.第2次顺序查找的时间介于 [ 9000, 9999 ] ms之间。 <br>
 * @return 0
 */
int main() {

    SqSTable table;
    if (!(InitTable(&table))) {
        printf("空间申请失败!!!");
    }
    // 两种查找方式的所查找的数据量
    int test_01_data = 9666;
    int test_02_data = test_01_data * 10;
    /*
     * 第一次测试
     */
    printf("=========== 第1次测试,数据量:%6d个 ===========\n", test_01_data);
    // 创建顺序表
    CreateTable(&table, test_01_data);
    // 顺序查找
    double sequentialTimes_01 = SearchSeq_Times(table);
    // 二分查找
    double binaryTimes_01 = SearchBin_Times(table);
    // 查找结果
    PrintResult(test_01_data, sequentialTimes_01, binaryTimes_01);


    /*
     * 第二次测试
     */
    printf("=========== 第2次测试,数据量:%6d个 ===========\n", test_02_data);
    // 创建顺序表
    CreateTable(&table, test_02_data);
    // 顺序查找
    double sequentialTimes_02 = SearchSeq_Times(table);
    // 二分查找
    double binaryTimes_02 = SearchBin_Times(table);
    // 查找结果
    PrintResult(test_02_data, sequentialTimes_02, binaryTimes_02);

    // 测试环境
    printf("===== 测试环境:Windows 11,i7-9750HF@4.12Ghz =====");

    getchar();
}

// 构造一个空的顺序表
int InitTable(SqSTable *table) {
    table->elem = (ElemType *) malloc(sizeof(SqSTable) * MAXSIZE); // 动态方式需要先分配内存,而且
    // 需要用到malloc函数申请,有可能申请不到,申请到后malloc()函数会把申请到的连续数据空间首地址返回
    // 注意:这里申请到返回的地址是十六进制的地址,而elem只能存十进制的地址,所以需要强转为十进制地址后赋值
    if (table->elem == NULL) { // 如果没有申请到地址,退出
        return ERROR;
    }
    table->length = 0; // 空表长度为 0
    return OK; // 初始化成功
}

// 顺序表的创建
int CreateTable(SqSTable *table, int length) {
    for (int i = 1; i <= length; i++) { // 第一个数默认不使用
        table->elem[i].key = i;
        table->length++; // 表长加 1
    }
    return OK;
}

// 顺序查找
double SearchSeq(SqSTable table, int key) {
    int i;
    table.elem[0].key = key; // 第一个数的作用来了 -> 设置 “哨兵”
    for (i = table.length; table.elem[i].key != key; i--); // 从后往前找
}

// 顺序查找测时
double SearchSeq_Times(SqSTable table) {
    /*
     * 时间测试方式二:
     *      所用精度:纳秒级
     */
    struct timespec start;
    struct timespec end;
    // 开始时间
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);

    for (int i = 1; i <= table.length; i++) { // 所有数都查找一遍
        SearchSeq(table, i);
    }

    // 结束时间
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
    // 总耗时
    // 转化为 ms 为单位(但是精度可以直接到 ns 级别)
    double start_ms = start.tv_sec * 1000.0 + start.tv_nsec / 1000000.0;
    double end_ms = end.tv_sec * 1000.0 + end.tv_nsec / 1000000.0;
    return end_ms - start_ms;
}

// 在有序表table中折半查找其关键字等于key的数据元素。若找到,则函数值为该元素在表中的位置,否则为0
double SearchBin(SqSTable table, int key) {
    // 置 查找区间 初值
    int leftIndex = 1; // 第一个数默认不使用
    int rightIndex = table.length;
    while (leftIndex <= rightIndex) { // 循环限制条件:查找过程中如果没有找到的情况,会造成栈溢出
        int minIndex = (leftIndex + rightIndex) / 2; // 二分查找的精髓:先找到中间那个数
        if (key == table.elem[minIndex].key) {
            // 如果需要查找的数等于中间那个数,则直接输出中间那个数(即需要查找的数的)下标
            return minIndex; // 找到待查元素
        } else if (key < table.elem[minIndex].key) {
            // 如果需要查找的数小于中间那个数,说明需要从中间那个数的左边第一个数继续进行二分查找,其他不变
            rightIndex = minIndex - 1;
        } else {
            // 如果需要查找的数大于中间那个数,说明需要从中间那个数的右边第一个数继续进行二分查找,其他不变
            leftIndex = minIndex + 1;
        }
    }
    return -1; // 如果没有找到返回-1
}

// 二分查找测时
double SearchBin_Times(SqSTable table) {
    /*
     * 时间测试方式二:
     *      所用精度:微秒级
     */
    union _LARGE_INTEGER time_start; // 开始时间
    union _LARGE_INTEGER time_over; // 结束时间
    LARGE_INTEGER f; // 计时器频率
    QueryPerformanceFrequency(&f);
    double dqFreq = (double) f.QuadPart; // 计时器频率
    QueryPerformanceCounter(&time_start); // 计时开始

    for (int i = 1; i <= table.length; i++) { // 所有数都查找一遍
        SearchBin(table, i);
    }

    QueryPerformanceCounter(&time_over); // 计时结束
    // 乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒
    double run_time = 1000000.0 * (time_over.QuadPart - time_start.QuadPart) / dqFreq;
    return run_time / 1000.0;
}

void PrintResult(int data, double sequentialTimes, double binaryTimes) {

    // 理论ASL
    double sequentialASL = (data + 1) / 2.0;
    double binaryASL = log2(data + 1) - 1;

    printf(".--------.\n");
    printf("|理论性能'----------------------------------------.\n");
    printf("|ALS成功 : 顺序查找 = %-7.1f   二分查找 = %-4.1f |\n", sequentialASL, binaryASL);
    printf("|次数之比:   顺序查找  :  二分查找  = %7.2f : 1 |\n", sequentialASL / binaryASL);
    printf("'-------------------------------------------------'\n");

    printf(".--------.\n");
    printf("|实际性能'----------------------------------------.\n");
    printf("|ALS成功 : 顺序查找 %-7.2f ms  二分查找%-4.2f ms |\n", sequentialTimes, binaryTimes);
    printf("|次数之比:   顺序查找  :  二分查找  = %7.2f : 1 |\n", sequentialTimes / binaryTimes);
    printf("'-------------------------------------------------'\n");

}

实验结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/800779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用STM32为主控以LORA为通讯模块,通过中继器链接MQTT服务器的物联网信息采集处理的信息系统方案

项目的详细方案如下&#xff1a; 硬件组成&#xff1a; STM32主控板&#xff1a;作为项目的主控单元&#xff0c;负责采集终端点位的温湿度信息&#xff0c;并通过LORA通讯模块发送数据到中继器。 LORA通讯模块&#xff1a;作为STM32与中继器之间的无线通信模块&#xff0c;负…

【NLP】语音识别 — GMM, HMM

一、说明 在语音识别的深度学习&#xff08;DL&#xff09;时代之前&#xff0c;HMM和GMM是语音识别的两项必学技术。现在&#xff0c;有将HMM与深度学习相结合的混合系统&#xff0c;并且有些系统是免费的HMM。我们现在有更多的设计选择。然而&#xff0c;对于许多生成模型来说…

浅谈集成式电力电容器无功补偿装置的技术特点及应用状况

安科瑞 华楠 摘要&#xff1a;阐述了集成式电力电容器无功补偿装置的组成与应用状况&#xff0e;在与常规电力电容器对比的基础上&#xff0c;分析了集成式电力电容器无功补偿装置的技术特点。通过对集成式无功补偿装置原理结构的分析&#xff0c;探讨了对集成式无功补偿装置的…

Spring Batch教程(四)tasklet使用示例:spring batch的定时任务使用

Spring batch 系列文章 Spring Batch教程&#xff08;一&#xff09; 简单的介绍以及通过springbatch将xml文件转成txt文件 Spring Batch教程&#xff08;二&#xff09;示例&#xff1a;将txt文件转成xml文件以及读取xml文件内容存储到数据库mysql Spring Batch教程&#xff…

TPU-MLIR编译部署算法

注意&#xff1a; 由于SOPHGO SE5微服务器的CPU是基于ARM架构&#xff0c;以下步骤将在基于x86架构CPU的开发环境中完成 初始化开发环境(基于x86架构CPU的开发环境中完成)模型转换 (基于x86架构CPU的开发环境中完成) 处理后的PP-OCR项目文件将被拷贝至 SE5微服务器 上进行推理…

el-table-column 合并列,切换表格显示,数据错乱问题

由于同一个页面需要通过lable进行切换显示不同的表格结果在切换的时候发现表格列错乱了 正常是这样的 切换错乱的是这样的 序号没有了&#xff0c;已接单协同总数列也不见了 切换回来发现第一个表格 原先的两列被后面的挤压了 代码也没啥毛病&#xff0c;最主要的原因是因为同…

【从零开始学习JAVA | 第三十二篇】 异常(下)新手必学!

目录 前言&#xff1a; Exceptions&#xff08;异常&#xff09;&#xff1a; 异常的两大作用&#xff1a; 异常的处理方式&#xff1a; 1.JVM默认处理 2.自己捕获异常 3.抛出处理 自定义异常&#xff1a; 异常的优点&#xff1a; 总结&#xff1a; 前言&#xff1a; 前…

LUMEN技术要点总结

LUMEN总结 主题是动态全局光照和Lumen Lumen更像是一个各种GI算法的集大成者。 1. 如何理解lumen及全局光照的实现机制 渲染方程 至今为止所有的实时光照都是按照Render Equation来进行渲染的&#xff0c;我们做得到只是在无限的逼近它。 我们把只进行一次反弹叫做SingleBou…

uni-app 经验分享,从入门到离职(一)——初始 uni-app,快速上手(文末送书福利1.0)

文章目录 &#x1f4cb;前言&#x1f3af;什么是 uni-app&#x1f3af;创建第一个 uni-app 项目&#x1f9e9;前期工作&#x1f9e9;创建项目&#xff08;熟悉默认项目、结构&#xff09;&#x1f9e9;运行项目 &#x1f4dd;最后&#x1f3af;文末送书&#x1f525;参与方式 &…

客户方数据库服务器CPU负载高优化案例

客户方数据库服务器CPU负载高优化案例 背景 上周线上服务出现一个问题&#xff0c;打开某个页面&#xff0c;会导致其它接口请求响应超时&#xff0c;排查后发现数据库响应超400s&#xff0c;之前1s就可查到数据。 具体原因是有个大屏统计页面&#xff0c;会实时查看各业务服…

echarts坐标轴名称换行

一、期望效果&#xff1a; 期望超过6个字换行&#xff0c;最多可显示十个字 如图&#xff1a; 二、踩坑&#xff1a; echarts的width和overflow设置后换行无效。&#xff08;如果其他人有设置有效的 还请说明下&#xff09; 三、解决方案&#xff1a; 用\n换行&#xf…

Django + Xadmin 数据列表复选框显示为空,怎么修复这个问题?

问题描述&#xff1a; 解决方法&#xff1a; 后续发现的报错&#xff1a; 解决方案&#xff1a; 先根据报错信息定位到源代码&#xff1a; 在该文件顶部写入&#xff1a; from django.core import exceptions然后把&#xff1a; except models.FieldDoesNotExist修改为&…

qt6.5 download for kali/ubuntu ,windows (以及配置选项选择)

download and sign in qt官网 sign in onlion Install 1 2 3 4 5

SpringBoot整合WebService

SpringBoot整合WebService WebService是一个比较旧的远程调用通信框架&#xff0c;现在企业项目中用的比较少&#xff0c;因为它逐步被SpringCloud所取代&#xff0c;它的优势就是能够跨语言平台通信&#xff0c;所以还有点价值&#xff0c;下面来看看如何在SpringBoot项目中使…

Neo4j图数据基本操作

Neo4j 文章目录 Neo4jCQL结点和关系增删改查匹配语句 根据标签匹配节点根据标签和属性匹配节点删除导入数据目前的问题菜谱解决的问题 命令行窗口 neo4j.bat console 导入rdf格式的文件 :GET /rdf/ping CALL n10s.graphconfig.init(); //初始化 call n10s.rdf.import.fetch(&q…

每日一题——两个链表的第一个公共结点

题目 输入两个无环的单向链表&#xff0c;找出它们的第一个公共结点&#xff0c;如果没有公共节点则返回空。&#xff08;注意因为传入数据是链表&#xff0c;所以错误测试数据的提示是用其他方式显示的&#xff0c;保证传入数据是正确的&#xff09; 数据范围&#xff1a; n≤…

LeetCode 75 第十一题(392)判断子序列

题目: 示例: 分析: 给两个字符串s和t,问s是不是t的子序列.即判断t中能不能提取出s(s有的元素,t都要有.并且字符的相对顺序不能变,如果字符的相对顺序能变的话就不能用双指针来做,而是要用哈希表了,可以参考力扣383赎金信这题). 这题虽然简单,但是是练习双指针的一个很好的题目…

【QT】Day3

1. 完成闹钟的实现&#xff1a; widgt.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QTimerEvent> //定时器事件处理函数 #include <QTime> //时间类 #include <QTextToSpeech> //文本转语音类头…

ARP协议(地址解析协议)详解

ARP协议&#xff08;地址解析协议&#xff09;详解 ARP协议的作用映射方式静态映射动态映射 ARP原理及流程ARP请求ARP响应 ARP协议报文首部 ARP协议的作用 ARP协议是“Address Resolution Protocol”&#xff08;地址解析协议&#xff09;的缩写。其作用是在以太网环境中&…

DataEase开源BI工具安装_数据全量_增量同步_大屏拖拽自动生成_多数据源支持_数据血缘分析---大数据工作笔记0183

我这里用的是Centos7.9安装的 可以通过uname -p来查看一下我们的电脑架构,可以看到是x86_64架构的 我们下第一个,这个是x86架构的,第二个arm架构的 然后解压到/opt/module中 然后再去重命名一下文件夹. 推荐200G 本地模式的功能比较多 推荐100G