数据结构-查找(顺序查找与二分查找的讲解与代码实现)

news2024/11/20 11:38:52

顺序查找概念:从表的另一端开始,一次将记录的关键字和给定值进行比较,若某个记录的关键字和给定的值相等,则查找成功,反之则查找失败。

ASL:平均查找长度

pi查找概率,ci查找次数

eg:序列1,2,3

查找1的次数为1概率为1/3,2为两次概率1/3,3的次数为3概率1/3 

将123的查找率*查找次数的结果累加得到 平均查找次数

 

顺序查找的代码实现:(这里我么用的顺序表查找) 

//顺序查找
typedef struct List
{
	int* data;//数据元素
	int* length;//数据长度
	int size;//有效数据个数
}List;

List* initList(int length)
{
	List* list = (List*)malloc(sizeof(List));
	list->length = length;
	list->data = (int*)malloc(sizeof(int) * length);
	list->size = 1;//size等于1的时候说明带有哨兵,后面的数据从第二个位置开始存元素。
	return list;
}

void listAdd(List* list,int data)
{
	if (list->size == list->length)//所存储的有效数据已经等于空间大小(空间已经满了)
{//这里我们重新定义一个newlength,防止开始length为0时,length*2=0;
	int newlength = list->length == 0 ? 4 : list->length * 2;
	int* tmp = (List*)realloc(list->data, newlength * sizeof(int));
	if (tmp == NULL)
	{
		printf("空间开辟失败\n");
		exit(-1);
	}
	else
	{
		list->data[list->size] = data;
		list->size++;
	}
	}
	else
	{
		list->data[list->size] = data;
		list->size++;
	}
}

void printlist(List* list)
{

	for ( int i = 0;  i <list->size ; i++)
	{
		printf("%d ->", list->data[i]);
	}
	printf("NULL\n");
}

int search(List* list, int key)
{
	int i=0;
	list->data[0] = key;
 //for循环后面没有语句只有分号时,当不满足for循环的条件后循环结束不再进行,直接进行下一语句。
	for (i = (list->size) - 1; list->data[i] != key; i--);//for循环后面没有语句的执行的时候需要添加分号,防止后面的语句直接进入for循环中。
	return i;//如果返回的为0则认为没有查找到,因为我们把要查找的元素放在了头节点当中。
}

int main()
{
	List* list = initList(5);
	listAdd(list, 1);
	listAdd(list, 2);
	listAdd(list, 3);
	listAdd(list, 4);
	listAdd(list, 5);
	printlist(list);
	printf("%d\n", search(list, 3));
	return 0;
}

顺序查找的ASL:第一个节点需要1次,第n个节点则需要n次

则总该查找的次数为Sn=n*(n+1)/2(等差数列求和公式)

每次查找的概率为1/n

所以顺序查找的ASL为:n*(n+1)/2*(1/n)=(n+1)/2 

所以时间复杂度为O(n)。

二分查找L(折半查找):

前提条件是有序序列,即每次从序列的中间开始于所要查找的元素比较,如果中间元素小于key(要查找的元素)则从中间元素的右边查找(以中间元素+1为首元素,尾元素不变,再去求mid于key相比)。同理若key<mid则要从mid的左边寻找(以中间元素-1为尾元素,首元素素不变,在去求mid于key比较),若key等于mid则返回。

代码实现:利用循环查找

//循环查找
int binarysearch(int key,List* list)
{
	int start = 0;
	int end = list->size - 1;
	int mid = 0;
	while (start<=end)/如果我们的首元素下标大于尾元素下标则说明我们已经遍历完整个序列不存在要找的元素
	{
		mid = (start + end) / 2;
		if (list->data[mid] < key)
		{
			start = mid + 1;
		}
		else if (list->data[mid]>key)
		{
			end = mid - 1;
		}
		else
		{
			return mid;
		}
	}
	return -1;//-1表示不存在
}

递归实现二分查找:

//递归查找   1.分半2查找(左查/右查)。
int binarysearchRecursion(int key, List* list, int start, int end)
{
	//出口
	if (start == end)//每个递归都有一个终止条件相当于我们while中的start<=end,当两个下标相等时进行判断如果等于key则返回任意一个下标,如果不相等则说明没有找到
	{
		if (list->data[start]==key)
		{
			return start;
		}
		else
		{
			return -1;
		}
	}
	int mid = (start + end) / 2;
//每次查找不到进行递归,看key于mid的比较来判断如果缩小范围	
if (list->data[mid] < key)
	{
	return	binarysearchRecursion(key, list, mid+1, end);
	}
	else if (list->data[mid]>key)
	{
	return	binarysearchRecursion(key, list, start, mid - 1);
	}
	else
	{
		return mid;
	}
}

 二分查找的时间复杂度:(两个二分查找的世家复杂度相同所以我们只讲解一个即可)

我们可以把线性表堪称一颗树(因为线性表是有序的比key小的都在其坐标,比它大的都在其右边)

eg:

 树的查找:节点在第几层需要查找几次,h层需要查找h次(所有的算法都符合此条件)

假设有n个节点,h层==》由树的公式得到n=2^(h-1)   一棵满二叉树。

满二叉树:每一层有2^(h-1)个节点

每一层查找次数:节点个数*层数==2^(h-1)*h

每层的ASL:查找次数 *概率=1/n*2^(h-1)*h

分解求2^(h-1)*h如何用n来代替

观察得此为等差*等比数列,求法(错位相减Sn-hSn)

3,4式联立: 

 

 

 

再去×1/n得到整个顺序的ASL 

 再利用我们数学极限n趋向足够大的时候前面的分式可以约掉,所以结果

约等于:两个都可

 

顺序查找于二分查找以简略的讲完,一些图片资料与代码都借鉴于b站upTyrantLucifer

 

 

 

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

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

相关文章

kubelet源码分析 status_manager状态管理器篇

kubelet源码分析 status_manager状态管理器篇 右上方的statusManager就是本篇要介绍的内容。上一篇kubelet的sync同步函数也介绍过&#xff0c;这篇内容详细介绍状态管理器的作用。 一、简介 status_manager&#xff08;状态管理器&#xff09;是 Kubernetes 中的一个组件&am…

【ONE·C++ || 哈希(二)】

总言 主要介绍哈希运用于unordered系列的上层封装框架与相关运用&#xff1a;位图、布隆过滤器、哈希切割。 文章目录 总言0、思维导图3、封装3.1、基础封装3.1.1、框架结构3.1.2、Inset 1.0 3.2、引入迭代器3.2.1、在迭代器中3.2.2、在哈希表中3.2.3、在unordered上层3.2.4、…

springBoot搭建

这里写目录标题 一、在学习spring Boot之前我们来回顾一下Spring二、Spring Boot介绍 三、Spring Boot开发环境搭配四、Spring Boot核心五、Spring Boot添加模块六、Spring Boot新注解介绍 一、在学习spring Boot之前我们来回顾一下Spring 首先说一下spring的优点: spring是轻…

Wireshark 解密https 数据

默认情况下 wireshark 抓到的https 数据包都是加密后的&#xff0c;无法展示明文内容 方式一 -SSLKEYLOGFILE 变量方式 【推荐&#xff0c;适用各种情况】 配置环境变量 浏览器在访问https 站点的时候会检测这个SSLKEYLOGFILE 变量&#xff0c;如果存在&#xff0c;则将https…

SpringCloud Nacos实战应用

目录 1 Nacos安装1.1 Nacos概要1.2 Nacos架构1.3 Nacos安装1.3.1 Nacos Derby安装1.3.2 Nacos MySQL版安装1.3.3 Docker 安装Nacos 2 Nacos功能应用2.1 Nacos服务注册与发现2.2 负载均衡2.3 配置中心2.4 灰度发布 3 Nacos集群3.1 集群架构3.2 Nacos集群部署3.3 客户端接入Nacos…

c# 依赖注入

依赖注入 文章目录 依赖注入一、.net core主要提供了三种依赖注入的方式二、权重三、如果我们需要注入的对象很多怎么办 一、.net core主要提供了三种依赖注入的方式 AddTransient瞬时模式&#xff1a; 每次请求&#xff0c;都获取一个新的实例。即使同一个请求获取多次也会是…

2022年度互联网平均薪资出炉!高到离谱!

近期&#xff0c;国家统计局发布2022年平均工资数据&#xff0c;互联网行业薪资再次成为大家关注的焦点。 在2022年分行业门类分岗位就业人员年平均工资中&#xff0c;信息传输、软件和信息技术服务业的薪资遥遥领先其他行业&#xff0c;为全国平均薪资水平的 1.78 倍&#xf…

devfreq

devfreq 是指频率电源可以动态调节的设备&#xff0c;可以添加不同设备及不同govvernor ; devfreq 框架和opp(operating performance point) 频率电源对 devices driver 通过 devfreq profile 交互 devfreq_dev_profile include/linux/devfreq.h devfreq_governor 与 dev…

如何用二极管实现不同电压的输出?

利用二极管的单向导电性可以设计出好玩、实用的电路。本文分析限幅电路和钳位电路&#xff0c;是如何用二极管来实现的。 限幅电路 如下图所示&#xff0c;当在正半周期&#xff0c;并且VIN大于等于0.7V&#xff0c;二极管正向导通。此时&#xff0c;VOUT会被钳位在0.7V上。 …

C++11:右值引用 -- 移动构造和移动赋值

目录 一. 左值引用和右值引用的概念和性质 1.1 什么是左值引用和右值引用 1.2 左值引用和右值引用的性质 二. 移动构造和移动赋值 2.1 左值引用的缺陷 2.2 临时对象返回减少拷贝的问题&#xff08;移动构造和移动赋值&#xff09; 2.3 C11 STL容器接口的一些变化 三. 完…

【C++进阶之路】手把手教你使用string类的接口

文章目录 前言基本认识基本使用 一.构造函数默认构造函数拷贝构造函数其它构造函数①string(const char* s)②string(size_t n, char c)③string (const string& str, size_t pos, size_t len npos) 二.容量接口①size与length②max_size③capacity④empty⑤clear⑥revers…

Elastic Learned Sparse Encoder 简介:Elastic 用于语义搜索的 AI 模型

作者&#xff1a;Aris Papadopoulos, Gilad Gal 寻找意义&#xff0c;而不仅仅是文字 我们很高兴地与大家分享&#xff0c;在 8.8 中&#xff0c;Elastic 提供开箱即用的语义搜索。语义搜索旨在根据文本的意图或含义进行搜索&#xff0c;而不是词汇匹配或关键字查询。与传统的…

华为云服务器租用费用及CPU性能(1核2G/2核4G/4核8G)

华为云HECS云服务器即云耀云服务器&#xff0c;类似于阿里云和腾讯云的轻量应用服务器&#xff0c;HECS云服务器1核2G配置39.02元一年、2核4G配置99元一年、4核8G配置69.94元3个月&#xff0c;华为云百科分享华为云HECS云服务器租用费用及CPU性能详解&#xff1a; 目录 华为云…

图解LeetCode链表题

&#x1f490;文章导读 本篇文章主要详细的用图解的方式为大家讲解了简单程度的链表题&#xff0c;如果题中有错误的地方&#xff0c;还麻烦您在评论区指出&#xff0c;你的意见就是我最大的进步&#xff01;&#xff01;&#xff01; &#x1f490;专栏导读 &#x1f934;作者…

什么是数字化?企业为什么要数字化转型

一、什么是数字化&#xff1f; 什么是数字化&#xff1f;在我理解&#xff0c;数字化是一个基于时代科技发展所产生的概念&#xff0c;首先它是一个工具&#xff0c;在企业的经营发展中将信息技术融入到传统的企业模式中&#xff0c;起到了转型的作用。 其次数字化转型是企业…

国产易灵思FPGA的FIFO应用详解

一、软件设置界面 FIFO&#xff08;First In First Out&#xff0c;即先入先出&#xff09;&#xff0c;是一种数据缓冲器&#xff0c;用来实现数据先入先出的读写。与 ROM 或 RAM 的按地址读写方式不同&#xff0c; FIFO 的读写遵循“先进先出”的原则&#xff0c;即数据按顺…

关于this->moveToThread(this)——QtWidgets

前言 官方关于QThread的用法有两种&#xff1a;一是子类QThread&#xff0c;并重新实现run&#xff1b;二是使用QObject::MoveToThread&#xff0c;通过信号槽在不同的线程内通信。 最近看到了一种写法&#xff0c;就是将两者融合就是子类QThread&#xff0c;然后this->mo…

【小程序】封装时间选择组件:用单元格van-cell和插槽slot,包括起始时间和终止时间

效果 可以选择起始时间和终止时间&#xff0c;并显示。 时间选择器放在van-cell的value插槽中。 用的库&#xff1a; https://vant-contrib.gitee.io/vant-weapp/#/home https://dayjs.fenxianglu.cn/category/ 用的组件&#xff1a;Cell单元格、DatetimePicker时间选择、Pop…

【Unity编辑器扩展】(二)PSD转UGUI Prefab, 图层解析和碎图导出

书接上回&#xff1a;【Unity编辑器扩展】(一)PSD转UGUI Prefab, Aspose.PSD和Harmony库的使用_TopGames的博客-CSDN博客 工具使用预览&#xff1a; 工具目标&#xff1a; 1. 实现将psd解析生成为UI预制体&#xff0c;并导出UI图片。需支持UGUI和TextMeshProGUI, 如Button、To…

文心一言 VS 讯飞星火 VS chatgpt (22)-- 算法导论4.2 2题

二、为Strassen算法编写伪代码。 文心一言&#xff1a; Strassen算法是一种用于矩阵乘法的算法&#xff0c;它的核心思想是通过不断将原始矩阵分割成较小的子矩阵来实现高效的乘法运算。以下是Strassen算法的伪代码&#xff1a; function Strassen(A, B): if A[0][0] 0 or…