在C++ STL中查找向量中元素的不同方法

631 阅读3分钟

在这篇文章中,我们讲解呢在C++ STL中寻找向量元素的不同方法,包括使用std::find(), std::find_if, std::distance, std::count和线性搜索。

目录。

  1. 在C++和STL中介绍向量
  2. 我们如何使用STL找到一个元素?
  3. 方法1:使用std::find()返回元素的索引
  4. 使用std::find_if()与std::distance()。
  5. 使用std::count()
  6. 线性搜索

让我们开始学习在C++ STL中查找向量元素的不同方法。

介绍C++和STL中的向量

C++中的向量就像其他语言中的数组一样,但它是动态的,这意味着它的大小不是静态的。为什么是向量?嗯,C++中的数组是静态的,一旦声明,我们就不能改变它们的大小,当我们需要存储一个我们不确定大小的数据集时,这是不可取的。

与数组不同,我们可以在运行时确定向量的大小,这也是向量成为这些类型场景的完美选择的原因,它们是动态分配的,这意味着它们可以被调整大小。

STL是标准模板库的意思。基本上STL包含一些通用函数,我们在本教程中需要这些函数。

我们如何使用STL找到一个元素?

image002

有三种方法可以解决这个问题。

**方法1:**通过返回元素在向量中的索引位置。这里我们使用std::find()和std::find_if()

**方法2:**通过返回一个布尔值,如果元素在向量中是真,否则是假。这里我们使用std::count()。

**方法3:**这里没有STL,我们使用线性搜索,我们通过向量元素,在元素和键k之间进行比较。

方法1:使用std::find()返回元素的索引

std::find()
在我们的例子中,它看起来像下面
这样。

it = std::find(arr.begin(), arr.end(), k)

这里传递的参数是键k,函数调用将返回一个指向向量中键k的迭代器。

#include<bits/stdc++.h>

int searchResult(std::vector<int> arr, int k){
    std::vector<int>::iterator it;
    it = std::find(arr.begin(), arr.end(), k);
    if(it != arr.end())
        return (it - arr.begin());
    else
        return -1;
}

int main(){
    std::vector<int> arr = {1, 2, 3, 4, 5, 6};
    int k = 4;
    std::cout << searchResult(arr, k) << std::endl;
    return 0;
}

代码解释

这段代码返回我们试图寻找的元素的索引,如果该元素不在向量中,则返回-1。

_第1行。_声明的头文件包括c++中的每一个标准库,它包含了我们需要的查找函数。
_第2行。_我们声明一个以向量和要搜索的键为参数的函数。
_第3行。_我们为我们的向量声明一个迭代器。它指向该向量的内存地址。
你可以在本帖末尾提供的链接中阅读迭代器的内容。
_第4行。_我们对std::find进行函数调用,将返回一个包含键k在向量中的位置的迭代器。 第
5-8行:
这里我们做一个if检查,如果元素在向量中,我们返回它的位置,否则我们返回-1,表示它不在向量中。

时间复杂度是线性的O(n),这是因为函数调用在向量中穿过n个项目以找到我们要找的键。
空间复杂度是常数O(1),没有使用额外的空间,只是穿过向量并进行比较。

2.使用std::find_if()和std::distance()。

如果搜索需要满足一个特定的逻辑,例如,使用质数逻辑找到一个质数的向量中的元素索引,这是一个推荐的方法。

_std::find_if()_返回一个迭代器到第一个到最后一个范围内的第一个元素,我们的谓词(比较结构)返回真。如果没有这样的键,该函数将返回end(last),指向last。

_std::distance()_返回从第一个到最后一个的跳数。在我们的例子中,它返回从向量的开始到指向键k的迭代器的跳数,这是我们正在搜索的元素的位置索引。跳数将是键k的索引。

#include<bits/stdc++.h>

struct compare{
    int k;
    compare(int const &i): k(i) {}
    bool operator()(int const &i) {
        return (i == k);
    }
};

int searchResult(std::vector<int> arr, int k){
    auto itr = std::find_if(arr.cbegin(), arr.cend(), compare(k));
    if(itr != arr.cend())
        return std::distance(arr.cbegin(), itr);
    return -1;
}

int main(){
    std::vector<int> arr = {1, 2, 3, 4, 5, 6};
    int k = 4;
    std::cout << searchResult(arr, k) << std::endl;
    return 0;
}

代码解释

函数searchResult()返回向量中元素的索引或-1表示向量中没有该元素。
_第2-8行:_我们声明了一个结构compare,将int k与参数中传递的值进行比较。
你可以在本帖最后提供的外部链接中阅读C++结构。
第9行。
_第10行:_我们再次调用STL库中的find_if函数,但在这种情况下,我们传递了指向开始(arr.cbegin())和指向结束(arr.cend())的常量随机访问迭代器,以及以键k为参数的比较结构。
这里的auto关键字指定声明的变量类型将自动从其初始化器中扣除。
_第10-13行:_我们执行if检查,看迭代器是否返回了一个值。
std::distance将执行上面讨论的内容。
此时,它的跳数将指向向量中键k的索引。

这里的时间复杂度也是线性的O(n),因为我们通过整个向量来寻找元素。
空间复杂度是常数O(1),没有使用额外的空间。

方法2:返回布尔值

3:使用std::count()

_std::count()_返回一个元素在向量中出现的次数,
我们可以在需要检查一个元素在向量中出现的情况下应用它,并返回该元素在向量中出现的次数。

#include<bits/stdc++.h>

bool searchResult(std::vector<int> arr, int k){
    return std::count(arr.begin(), arr.end(), k);
}

int main(){
    std::vector<int> arr = {1, 2, 3, 4, 5, 6};
    int k = 4;
    std::cout << searchResult(arr, k) << std::endl;
    return 0;
}

代码解释

_第2行。_函数searchResult()以向量arr和键k为参数,
返回1表示真,0表示假。
_第3行:_Count STL函数对键k的出现进行计数,如果有,它返回元素出现的数量。
我们可以做一个if检查,如果计数大于0,则该元素存在,否则不存在。

时间复杂度是线性的O(n),因为我们遍历了整个向量。
空间复杂度是常数O(1),因为没有使用额外的空间。

方法3:线性搜索

在这种情况下,我们不使用任何STL函数,而是使用for循环逐个元素遍历向量,并在目标和每个元素之间进行比较,如果一个元素符合我们的目标,我们就返回其索引。

#include<bits/stdc++.h>

int searchResult(std::vector<int> arr, int k){
    for(int i = 0; i < arr.size(); i++){
        if(arr[i] == k){
            return i;
        }
    }
    return -1;
}

int main(){
    std::vector<int> arr = {1, 4, 33, 44, 5, 6, 100, 4, 5, 7, 9, 0};
    int k = 4;
    std::cout << searchResult(arr, k) << std::endl;
    return 0;
}

代码解释

该函数以一个向量和键k为参数,如果元素存在,则返回索引,否则返回-1,表示没有该元素。

_第3行。_我们使用一个for循环,通过向量进行元素和目标的比较。
_第4行。_我们做一个if检查,如果索引处的元素等于我们的目标,我们返回索引,否则我们退出循环并返回-1。