chapter3-排序和查找2
2.基础查找
所谓查找,就是在查找空间中找寻符合要求的解的过程。查找方法有多种,下面简单介绍3种。不同的策略对查找的效率和结果有不同的影响。
2.1 线性查找
从首元素开始,遍历整个序列,直到找到目标元素,则结束算法;或者遍历完序列还没有匹配,则查找失败结束算法。时间复杂度为O(n)。
线性查找
//基础查找-线性查找 2024-02-15 #include <iostream> #include <cstdio> using namespace std; const int MAXN = 100 + 10; int arr[MAXN]; //线性查找 bool LinearSearch(int n, int target) { for(int i=0; i<n; i++) { if(target == arr[i]) return true; } return false; } int main() { int n; scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &arr[i]); } int m, target; scanf("%d", &m); for(int i=0; i<m; i++) { scanf("%d", &target); if(LinearSearch(n, target)) { printf("YES\n"); } else{ printf("NO\n"); } } return 0; }
2.2 二分查找
二分查找的前提是有序序列。有两种方法,一种是自定义,自己写一个函数用来贴合题面的要求;第二种是内定义,即使用C++内部封装好的函数来实现二分查找。时间复杂度为O(logn)。
2.2.1 自定义
定义两个变量L和R分别指向首元素和序列的尾元素,计算middle,如果middle所指向的元素和要找的目标值target相等,则查找成功,结束算法;否则如果middle所指向的元素比target小,则在右半边继续查找;左半边同理;直至查找到目标值,或者当R<L时算法结束,查找失败。
二分查找_自定义
//基础查找-二分查找-前提序列有序-自定义 2024-02-15 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int MAXN = 100 + 10; int arr[MAXN]; bool BinarySearch(int n, int target) { int left = 0; int right = n-1; while(left <= right) { int middle = left + (right - left)/2; if(arr[middle] == target) { return true; } else if(arr[middle] < target)//搜索右半部分 { left = middle + 1; } else{ right = middle -1; } } return false; } int main() { int n; scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &arr[i]); } sort(arr, arr+n);//默认compare升序 int m, target; scanf("%d", &m); for(int i=0; i<m; i++) { scanf("%d", &target); if(BinarySearch(n, target)) { printf("YES\n"); } else{ printf("NO\n"); } } return 0; }
2.2.2 内定义
C++内部封装了两个用于实现二分查找的函数,即lower_bound和upper_bound。需要引用头文件#include <algorithm>
1、lower_bound:返回大于或等于目标值的第一个位置。
2、upper_bound:返回大于目标值的第一个位置。
lower_bound(first, last, target)有三个参数,分别是有序序列的起始地址、结束地址和目标值,target可为任意数据类型。
注意考虑lower_bound在查找目标值时的3种情况。其一如上图所示;其二是有序序列中没有目标值,lower_bound会返回最靠近目标值而大于目标值的元素的下标;其三,要查找的target值大于有序序列的最大值,此时lower_bound会移出序列,指向下标n,即越界访问。
注意:lower_bound函数返回的不是数组元素的下标,而是元素所在的地址,减去数组起始地址,即可得到数组下标。int position = lower_bound(arr, arr+n, target) - arr;
二分查找_内定义
//基础查找-二分查找-前提序列有序-内定义 2024-02-15 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int MAXN = 100 + 10; int arr[MAXN]; int main() { int n; scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &arr[i]); } sort(arr, arr+n);//默认compare升序 int m, target; scanf("%d", &m); for(int i=0; i<m; i++) { scanf("%d", &target); int position = lower_bound(arr, arr + n, target) - arr ; if(position != n && arr[position] == target) { printf("YES\n"); } else{ printf("NO\n"); } } return 0; }
2.3 散列查找
线性查找和二分查找都是以数组下标为索引,去遍历查找target值,而散列查找使用散列函数,使得元素值经过常数时间的Hash函数计算后,直接得到其下标索引。时间复杂度为O(1)。
散列查找也有两种方法,一种是自定义,一种是内定义。
2.3.1 自定义
这里散列函数搞一个最简单的线性映射,即开一个和数据范围一样大的bool型辅助数组,在输入元素时,给对应的辅助数组赋值为true。未得到赋值的默认为false。
散列查找_自定义
//基础查找-散列查找 2024-02-15 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int MAXN = 100 + 10; const int RANGE = 1e6; int arr[MAXN]; bool hashTable[RANGE]; int main() { int n; scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &arr[i]); hashTable[arr[i]] = true; } sort(arr, arr+n);//默认compare升序 int m, target; scanf("%d", &m); for(int i=0; i<m; i++) { scanf("%d", &target); if(hashTable[target]) { printf("YES\n"); } else{ printf("NO\n"); } } return 0; }
2.3.2 内定义
C++内部封装了散列函数unordered_map,需要引用头文件#include <unordered_map>
。
散列查找_内定义
//基础查找-散列查找-内定义 2024-02-15 #include <iostream> #include <cstdio> #include <algorithm> #include <unordered_map> using namespace std; const int MAXN = 100 + 10; int arr[MAXN]; unordered_map<int, bool> hashTable;//1:元素的类型;2:是否出现过用bool表示 //相当于定义了一个辅助数组用于线性映射,就是散列函数 int main() { int n; scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &arr[i]); hashTable[arr[i]] = true; } sort(arr, arr+n);//默认compare升序 int m, target; scanf("%d", &m); for(int i=0; i<m; i++) { scanf("%d", &target); if(hashTable[target]) { printf("YES\n"); } else{ printf("NO\n"); } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具