名稱空間
變體
操作

std::search_n

來自 cppreference.com
< cpp‎ | 演算法
 
 
演算法庫
有約束演算法與針對範圍的演算法 (C++20)
有約束的演算法,例如 ranges::copyranges::sort 等……
執行策略 (C++17)
排序及相關操作
劃分操作
排序操作
二分搜尋操作
(於已劃分範圍上)
集合操作(於已排序範圍上)
歸併操作(於已排序範圍上)
堆操作
最小/最大值操作
(C++11)
(C++17)
字典序比較操作
排列操作
C 庫
數值操作
未初始化記憶體上的操作
 
定義於標頭檔案 <algorithm>
(1)
template< class ForwardIt, class Size, class T >

ForwardIt search_n( ForwardIt first, ForwardIt last,

                    Size count, const T& value );
(C++20 起為 constexpr)
(直到 C++26)
template< class ForwardIt, class Size,

          class T = typename std::iterator_traits
                        <ForwardIt>::value_type >
constexpr ForwardIt search_n( ForwardIt first, ForwardIt last,

                              Size count, const T& value );
(C++26 起)
(2)
template< class ExecutionPolicy,

          class ForwardIt, class Size, class T >
ForwardIt search_n( ExecutionPolicy&& policy,
                    ForwardIt first, ForwardIt last,

                    Size count, const T& value );
(C++17 起)
(直到 C++26)
template< class ExecutionPolicy,

          class ForwardIt, class Size,
          class T = typename std::iterator_traits
                        <ForwardIt>::value_type >
ForwardIt search_n( ExecutionPolicy&& policy,
                    ForwardIt first, ForwardIt last,

                    Size count, const T& value );
(C++26 起)
(3)
template< class ForwardIt, class Size, class T, class BinaryPred >

ForwardIt search_n( ForwardIt first, ForwardIt last,

                    Size count, const T& value, BinaryPred p );
(C++20 起為 constexpr)
(直到 C++26)
template< class ForwardIt, class Size,

          class T = typename std::iterator_traits
                        <ForwardIt>::value_type,
          class BinaryPred >
constexpr ForwardIt search_n( ForwardIt first, ForwardIt last,

                    Size count, const T& value, BinaryPred p );
(C++26 起)
(4)
template< class ExecutionPolicy, class ForwardIt, class Size,

          class T, class BinaryPred >
ForwardIt search_n( ExecutionPolicy&& policy,
                    ForwardIt first, ForwardIt last,

                    Size count, const T& value, BinaryPred p );
(C++17 起)
(直到 C++26)
template< class ExecutionPolicy, class ForwardIt, class Size,

          class T = typename std::iterator_traits
                        <ForwardIt>::value_type,
          class BinaryPred >
ForwardIt search_n( ExecutionPolicy&& policy,
                    ForwardIt first, ForwardIt last,

                    Size count, const T& value, BinaryPred p );
(C++26 起)

在範圍 [firstlast) 中搜索第一個由 count 個相同元素組成的序列,每個元素都等於給定 value

1) 使用 operator== 比較元素。
3) 使用給定二元謂詞 p 比較元素。
2,4)(1,3),但按 policy 執行。
僅當滿足所有以下條件時,這些過載才參與過載決議

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>true

(C++20 前)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true

(C++20 起)

目錄

[edit] 引數

first, last - 定義要檢查的元素範圍的迭代器對
count - 要搜尋的序列長度
value - 要搜尋的元素值
policy - 要使用的 執行策略
p - 二元謂詞,如果元素應被視為相等,則返回 true。

謂詞函式的簽名應等效於以下內容:

 bool pred(const Type1 &a, const Type2 &b);

儘管簽名不需要包含 const &,但函式不得修改傳遞給它的物件,並且必須能夠接受 Type1Type2 型別的所有值(可能為 const),而不管 值類別(因此,不允許 Type1 &,除非對於 Type1 移動等同於複製,否則也不允許 Type1(自 C++11 起))。
型別 Type1 必須使得型別為 ForwardIt 的物件可以被解引用,然後隱式轉換為 Type1。型別 Type2 必須使得型別為 T 的物件可以隱式轉換為 Type2。​

型別要求
-
ForwardIt 必須滿足 LegacyForwardIterator 的要求。
-
BinaryPred 必須滿足 BinaryPredicate 的要求。
-
Size 必須可隱式轉換為整數型別

[edit] 返回值

如果 count 為正,則返回指向在範圍 [firstlast) 中找到的第一個序列開頭的迭代器。序列中的每個迭代器 it 都應滿足以下條件

1,2) *it == valuetrue
3,4) p(*it, value) != falsetrue

如果未找到此類序列,則返回 last

如果 count 為零或負,則返回 first

[edit] 複雜度

給定 N 作為 std::distance(first, last)

1,2) 最多 N 次使用 operator== 的比較。
3,4) 最多 N 次謂詞 p 的應用。

[edit] 異常

帶有模板引數 ExecutionPolicy 的過載按如下方式報告錯誤

  • 如果作為演算法一部分呼叫的函式執行丟擲異常,並且 ExecutionPolicy標準策略之一,則呼叫 std::terminate。對於任何其他 ExecutionPolicy,行為是實現定義的。
  • 如果演算法未能分配記憶體,則丟擲 std::bad_alloc

[edit] 可能的實現

search_n (1)
template<class ForwardIt, class Size,
         class T = typename std::iterator_traits<ForwardIt>::value_type>
ForwardIt search_n(ForwardIt first, ForwardIt last, Size count, const T& value)
{
    if (count <= 0)
        return first;
 
    for (; first != last; ++first)
    {
        if (!(*first == value))
            continue;
 
        ForwardIt candidate = first;
 
        for (Size cur_count = 1; true; ++cur_count)
        {
            if (cur_count >= count)
                return candidate; // success
 
            ++first;
            if (first == last)
                return last; // exhausted the list
 
            if (!(*first == value))
                break; // too few in a row
        }
    }
    return last;
}
search_n (3)
template<class ForwardIt, class Size,
         class T = typename std::iterator_traits<ForwardIt>::value_type,
         class BinaryPred>
ForwardIt search_n(ForwardIt first, ForwardIt last, Size count, const T& value,
                   BinaryPred p)
{
    if (count <= 0)
        return first;
 
    for (; first != last; ++first)
    {
        if (!p(*first, value))
            continue;
 
        ForwardIt candidate = first;
 
        for (Size cur_count = 1; true; ++cur_count)
        {
            if (cur_count >= count)
                return candidate; // success
 
            ++first;
            if (first == last)
                return last; // exhausted the list
 
            if (!p(*first, value))
                break; // too few in a row
        }
    }
    return last;
}

[edit] 注意

特性測試 標準 特性
__cpp_lib_algorithm_default_value_type 202403 (C++26) 演算法的列表初始化 (1-4)

[edit] 示例

#include <algorithm>
#include <cassert>
#include <complex>
#include <iostream>
#include <iterator>
#include <vector>
 
template<class Container, class Size, class T>
constexpr bool consecutive_values(const Container& c, Size count, const T& v)
{
    return std::search_n(std::begin(c), std::end(c), count, v) != std::end(c);
}
 
int main()
{
    constexpr char sequence[] = ".0_0.000.0_0.";
 
    static_assert(consecutive_values(sequence, 3, '0'));
 
    for (int n : {4, 3, 2})
        std::cout << std::boolalpha
                  << "Has " << n << " consecutive zeros: "
                  << consecutive_values(sequence, n, '0') << '\n';
 
    std::vector<std::complex<double>> nums{{4, 2}, {4, 2}, {1, 3}};
    #ifdef __cpp_lib_algorithm_default_value_type
        auto it = std::search_n(nums.cbegin(), nums.cend(), 2, {4, 2});
    #else
        auto it = std::search_n(nums.cbegin(), nums.cend(), 2, std::complex<double>{4, 2});
    #endif
    assert(it == nums.begin());
}

輸出

Has 4 consecutive zeros: false
Has 3 consecutive zeros: true
Has 2 consecutive zeros: true

[edit] 缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
LWG 283 C++98 要求 TEqualityComparable,但
InputIt 的值型別並非總是 T
移除了此要求
LWG 426 C++98 複雜度上限為 N·count
如果 count 為負,則為負
上限為 0
如果 count 為非正
LWG 714 C++98 如果 count > 0,複雜度上限為 N·count,但在
最壞情況下,比較/操作次數始終為 N
在這種情況下將上限
更改為 N
LWG 2150 C++98 “序列出現”的條件不正確 已更正

[edit] 另請參閱

在特定範圍中尋找最後一次出現的元素序列
(函式模板) [編輯]
尋找第一個滿足特定條件的元素
(函式模板) [編輯]
搜尋一個範圍的元素首次出現的位置
(函式模板) [編輯]
在一個範圍內搜尋一個元素的連續 N 次副本首次出現的位置
(演算法函式物件)[編輯]