线性查找:
线性查找(Linear Search)是一种简单的查找技术,用于在列表、数组或其他线性数据结构中查找一个特定的元素。线性查找的基本思想是从数据结构的一端开始,逐个检查每个元素,直到找到所需的元素或搜索完整个数据结构为止。
线性查找步骤:
1.从数据结构的一端开始:通常是从第一个元素开始。
2.逐个检查元素:将当前元素与目标元素进行比较。
3.如果找到目标元素:则返回该元素的位置(或该元素的引用、值等,取决于具体的应用场景)。
4.如果当前元素不是目标元素:则继续检查下一个元素。
5.重复步骤2-4:直到找到目标元素或检查完所有元素。
6.如果未找到目标元素:则根据具体的应用场景,可能返回一个错误码、空值或-1等,表示未找到目标元素,一般来说返回-1.
线性查找代码:
#include <iostream>
using namespace std;
int LinearSearch(const int AA[],int key,int SizeofAA){
//const int AA[]表示AA[]数组是一个整型的常量数组,key表示查找的数值,SizeofAA表示元素个数
for(int i=0;i<SizeofAA;i++){
if(key==AA[i])
return i; //返回索引
}
return -1;//索引>=0,而返回-1表示key不在数组中,用于主函数的判断
}
int main(){
int aSize=10;//数组的元素个数
int A[aSize]={1,3,9,2,4,5,6,7,11,88};
int Searchkey;
cout <<"请输入要查找的值:"<<endl;
cin >>Searchkey;
int b=LinearSearch(A,Searchkey,aSize);
if(b==-1){
cout <<"该数不在数组中,查找失败"<<endl;
}
else{
cout<<"该数在数组中,索引下标为:"<<b<<" 查找成功"<<endl;
}
return 0;
}
线性查找复杂度:
- 时间复杂度:在最坏的情况下(即目标元素不在数据结构中或位于数据结构的末尾),需要检查所有的元素,因此时间复杂度为O(n),其中n是数据结构中元素的数量。在最好的情况下(即目标元素是数据结构的第一个元素),时间复杂度为O(1)。然而,由于我们不能预测目标元素的位置,因此通常考虑最坏情况的时间复杂度。
- 空间复杂度:线性查找不需要额外的存储空间(除了几个用于循环和比较的变量外),因此空间复杂度为O(1)。
折半查找:
折半查找(Binary Search),也被称为二分查找,是一种在有序数组中查找特定元素的搜索算法。其基本原理是通过将待查找的区间分成两半,判断待查找的元素可能在哪一半,然后继续在可能存在该元素的那一半区间内查找,以此逐步缩小查找范围,直到找到该元素或确定该元素不存在。
折半查找步骤 :
确定查找范围:首先,确定整个数组作为查找范围,即定义两个指针(或索引)
low
和high
,分别指向数组的第一个元素和最后一个元素。计算中间位置:计算
low
和high
中间位置的索引mid
,可以使用(low + high) / 2
或low + (high - low) / 2
来避免可能的整数溢出问题。比较中间元素:将中间位置的元素与待查找的元素(称为
key
)进行比较。如果相等,则查找成功,返回中间位置的索引。如果
key
小于中间位置的元素,说明待查找的元素只可能出现在左半部分,因此将high
更新为mid - 1
,继续在左半部分查找。如果key
大于中间位置的元素,说明待查找的元素只可能出现在右半部分,因此将low
更新为mid + 1
,继续在右半部分查找。缩小查找范围:重复步骤2和步骤3,直到找到元素或
low
大于high
(说明元素不存在于数组中)。返回结果:如果找到元素,则返回其索引;如果未找到,则通常返回某个特殊值(如
-1
)表示查找失败。
折半查找代码:
#include <iostream>
#include <vector>
using namespace std;
// 二分查找函数,返回目标值在数组中的索引,如果未找到则返回-1
int binarySearch(const vector<int>& arr, int target) {
int left = 0; // 查找范围的左边界
int right = arr.size() - 1; // 查找范围的右边界
while (left <= right) {
// 防止(left + right)直接相加导致的溢出,同时计算中间索引
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
// 找到目标值,返回索引
return mid;
} else if (arr[mid] < target) {
// 目标值在右半部分,调整左边界
left = mid + 1;
} else {
// 目标值在左半部分,调整右边界
right = mid - 1;
}
}
// 未找到目标值,返回-1
return -1;
}
int main() {
int tempArray[] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}; // 使用数组初始化 ,已经从小到大排序完成的数组
vector<int> arr(tempArray, tempArray + sizeof(tempArray) / sizeof(tempArray[0])); // 从数组初始化vector
int target ; // 要查找的目标值
cout <<"请输入需要查找的值:"<<endl;
cin>>target;
int result = binarySearch(arr, target);
if (result != -1) {
cout << "元素 " << target << " 找到,索引为:" << result << endl;
} else {
cout << "元素 " << target << " 未找到" << endl;
}
return 0;
}
折半查找复杂度:
时间复杂度
最好情况:当目标值正好是数组的中间元素时,算法只需要一次比较就能找到目标值,此时的时间复杂度为 O(1)。但是,由于这种情况并不常见,且依赖于目标值的具体位置,因此在分析折半查找的复杂度时通常不考虑最好情况。
最坏情况:当目标值不存在于数组中,或者目标值位于数组的第一个或最后一个位置(并且数组很大,使得每次查找都需要遍历到另一端),算法需要进行 log₂(n) + 1 次比较(其中 n 是数组的长度,因为算法是向下取整,所以实际比较次数可能比 log₂(n) 多一次)。因此,最坏情况下的时间复杂度是 O(log n)。
平均情况:由于每次查找都会将搜索范围减半,平均情况下也需要进行大约 log₂(n) 次比较。因此,平均情况下的时间复杂度也是 O(log n)。
空间复杂度
折半查找算法的空间复杂度是 O(1)。这是因为算法在查找过程中只需要维护几个指针或索(如左边界
left
、右边界right
和中间位置mid
),这些都不随输入规模 n 的增长而增长。算法没有使用额外的数据结构来存储中间结果,因此空间复杂度是常数级别的。