【C++之泛型算法】006Fredicate用以检验区间

is_sorted()

std::is_sorted 是 C++ 标准库中的一个泛型算法,用于检查一个序列是否已按升序排序。它接受两个迭代器,分别表示序列的开始和结束,并返回一个布尔值,指示序列是否已排序。

下面是一个使用 std::is_sorted 的例子:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 创建一个整数向量并初始化
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用 is_sorted 检查向量是否已排序
    bool isSorted = std::is_sorted(vec.begin(), vec.end());

    // 输出检查结果
    if (isSorted) {
        std::cout << "The vector is sorted." << std::endl;
    } else {
        std::cout << "The vector is not sorted." << std::endl;
    }

    // 修改向量中的一个元素以使其不再排序
    vec[2] = 0;

    // 再次检查向量是否已排序
    isSorted = std::is_sorted(vec.begin(), vec.end());

    // 输出检查结果
    if (isSorted) {
        std::cout << "The vector is sorted." << std::endl;
    } else {
        std::cout << "The vector is not sorted." << std::endl;
    }

    return 0;
}

在这个例子中,我们首先创建了一个整数向量 vec 并初始化为升序排列。然后,我们使用 std::is_sorted 来检查这个向量是否已排序,由于它是升序排列的,所以输出将是 “The vector is sorted.”。

接下来,我们修改了向量中的一个元素,使其不再按升序排列。再次调用 std::is_sorted 检查向量时,这次它将返回 false,因此输出将是 “The vector is not sorted.”。

std::is_sorted 还有一个带自定义比较函数的版本,允许你提供自己的比较逻辑。这在你需要对非标准类型的序列进行排序检查时非常有用。下面是一个使用自定义比较函数的 std::is_sorted 的例子:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义比较函数,用于比较两个字符串的长度
bool compare_by_length(const std::string& a, const std::string& b) {
    return a.size() < b.size();
}

int main() {
    // 创建一个字符串向量
    std::vector<std::string> vec = {"apple", "banana", "cherry", "blueberry"};

    // 使用自定义比较函数检查向量是否已排序
    bool isSorted = std::is_sorted(vec.begin(), vec.end(), compare_by_length);

    // 输出检查结果
    if (isSorted) {
        std::cout << "The vector is sorted by length." << std::endl;
    } else {
        std::cout << "The vector is not sorted by length." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个比较函数 compare_by_length,它比较两个字符串的长度。然后,我们将这个函数作为第三个参数传递给 std::is_sorted,以检查向量是否按字符串长度升序排列。

is_sorted_until()

std::is_sorted_until 是 C++ 标准库中的一个泛型算法,它用于查找一个序列中第一个破坏排序顺序的元素。换句话说,它返回指向序列中第一个不满足排序条件的元素的迭代器。如果整个序列都是排序的,则它返回序列的尾迭代器。

这个算法对于确定一个序列的哪部分是有序的,而无需检查整个序列非常有用。

下面是使用 std::is_sorted_until 的一个例子:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 创建一个整数向量并初始化
    std::vector<int> vec = {1, 2, 3, 5, 4, 6, 7, 8};

    // 使用 is_sorted_until 查找第一个破坏排序顺序的元素
    auto it = std::is_sorted_until(vec.begin(), vec.end());

    // 输出结果
    if (it != vec.end()) {
        std::cout << "The first element that is out of order is: " << *it << std::endl;
    } else {
        std::cout << "The entire sequence is sorted." << std::endl;
    }

    // 输出从开始到破坏排序的元素之前的所有元素
    for (auto elem = vec.begin(); elem != it; ++elem) {
        std::cout << *elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,vec 是一个整数向量,其中第四个元素 5 破坏了升序排序。std::is_sorted_until 返回指向这个元素的迭代器,然后我们输出这个元素以及它之前的所有元素。

std::is_sorted_until 同样有一个接受自定义比较函数的版本,允许你提供自定义的比较逻辑来判定元素是否满足排序条件。以下是一个使用自定义比较函数的 std::is_sorted_until 的例子:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义比较函数,用于比较两个整数的绝对值
bool compare_absolute_value(int a, int b) {
    return std::abs(a) < std::abs(b);
}

int main() {
    // 创建一个整数向量并初始化
    std::vector<int> vec = {-3, -1, 2, -4, 1, 5, -6};

    // 使用 is_sorted_until 和自定义比较函数查找第一个破坏排序顺序的元素
    auto it = std::is_sorted_until(vec.begin(), vec.end(), compare_absolute_value);

    // 输出结果
    if (it != vec.end()) {
        std::cout << "The first element that is out of order (by absolute value) is: " << *it << std::endl;
    } else {
        std::cout << "The entire sequence is sorted by absolute value." << std::endl;
    }

    // 输出从开始到破坏排序的元素之前的所有元素
    for (auto elem = vec.begin(); elem != it; ++elem) {
        std::cout << *elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,我们定义了一个比较函数 compare_absolute_value,它比较两个整数的绝对值。然后,我们将这个函数作为 std::is_sorted_until 的第三个参数传递,以便算法使用这个自定义的比较逻辑来检查序列的排序状态。

is_partitioned()

std::is_partitioned 是 C++ 标准库中的一个泛型算法,用于检查一个序列是否根据给定的谓词(predicate)被划分成两部分。换句话说,这个算法检查序列是否可以从一个点开始被划分为两部分,使得在划分点之前的所有元素都满足谓词,而之后的元素都不满足谓词。

以下是 std::is_partitioned 的基本用法示例:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义谓词函数,检查一个整数是否小于 5
bool is_less_than_five(int n) {
    return n < 5;
}

int main() {
    // 创建一个整数向量
    std::vector<int> vec = {1, 2, 3, 6, 7, 8};

    // 使用 is_partitioned 检查向量是否根据谓词 is_less_than_five 被划分
    bool result = std::is_partitioned(vec.begin(), vec.end(), is_less_than_five);

    // 输出结果
    if (result) {
        std::cout << "The vector is partitioned according to the predicate." << std::endl;
    } else {
        std::cout << "The vector is not partitioned according to the predicate." << std::endl;
    }

    // 更改向量中的一个元素,使其不满足谓词
    vec[2] = 6;

    // 再次检查向量是否根据谓词被划分
    result = std::is_partitioned(vec.begin(), vec.end(), is_less_than_five);

    // 输出结果
    if (result) {
        std::cout << "The vector is partitioned according to the predicate." << std::endl;
    } else {
        std::cout << "The vector is not partitioned according to the predicate." << std::endl;
    }

    return 0;
}

在这个例子中,我们首先定义了一个谓词函数 is_less_than_five,它检查一个整数是否小于 5。然后,我们创建了一个整数向量 vec 并用 std::is_partitioned 检查它是否根据这个谓词被划分。由于 vec 的前三个元素(1, 2, 3)都小于 5,而后面的元素(6, 7, 8)都不小于 5,所以第一次调用 std::is_partitioned 返回 true。

接着,我们更改了 vec 的第三个元素为 6,这样它就不再满足谓词 is_less_than_five。因此,当我们再次调用 std::is_partitioned 时,它返回 false,因为序列现在不能被单一划分点划分为两部分,使得划分点之前的所有元素都满足谓词。

注意,std::is_partitioned 只检查是否存在这样的划分点,而不返回这个划分点的位置。如果你需要找到这个划分点的位置,可以使用 std::partition_point 算法。

partition_point()

std::partition_point 是 C++ 标准库中的一个泛型算法,它用于确定一个序列中满足特定谓词(predicate)的第一个元素的位置。这个算法常用于配合 std::partition 或 std::stable_partition 使用,这些算法会重新排列序列,使得满足谓词的元素出现在不满足谓词的元素之前。std::partition_point 则返回这个分界点的位置。

std::partition_point 的使用场景通常是在你已经对序列进行了划分操作后,想要知道划分点在哪里,而不必重新对整个序列进行划分。

下面是一个使用 std::partition_point 的例子:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义谓词函数,检查一个整数是否小于 5
bool is_less_than_five(int n) {
    return n < 5;
}

int main() {
    // 创建一个整数向量
    std::vector<int> vec = {1, 2, 3, 6, 7, 8};

    // 使用 partition 对向量进行划分,使得小于 5 的元素在前
    std::partition(vec.begin(), vec.end(), is_less_than_five);

    // 使用 partition_point 查找划分点的位置
    auto partition_point_it = std::partition_point(vec.begin(), vec.end(), is_less_than_five);

    // 输出划分点的位置
    std::cout << "Partition point: " << std::distance(vec.begin(), partition_point_it) << std::endl;

    // 输出划分点之前的所有元素
    for (auto it = vec.begin(); it != partition_point_it; ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,我们首先使用 std::partition 对 vec 进行划分,使得所有小于 5 的元素都出现在大于或等于 5 的元素之前。然后,我们使用 std::partition_point 查找划分点的位置,并输出它。最后,我们遍历并输出划分点之前的所有元素。

注意,std::partition 和 std::partition_point 都不会保证划分点之后的元素满足谓词或不满足谓词,它们只保证划分点之前的元素都满足谓词。如果你需要确保划分点之后的元素都不满足谓词,你可以使用 std::stable_partition 代替 std::partition。

is_heap()

std::is_heap 是 C++ 标准库中的一个泛型算法,用于检查给定范围的元素是否形成堆(Heap)。堆是一种特殊的树形数据结构,通常通过数组来实现,其中每个父节点的值都大于或等于(在最大堆中)或小于或等于(在最小堆中)其子节点的值。

std::is_heap 有两个版本:默认版本和自定义比较版本。
默认版本

默认版本的 std::is_heap 接受两个迭代器作为参数,分别表示要检查的序列的开始和结束。它返回一个布尔值,指示该序列是否形成一个有效的最大堆。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 创建一个整数向量并初始化为最大堆
    std::vector<int> vec = {9, 5, 7, 3, 1};

    // 使用 make_heap 将向量转换为最大堆
    std::make_heap(vec.begin(), vec.end());

    // 检查向量是否是一个有效的最大堆
    bool isMaxHeap = std::is_heap(vec.begin(), vec.end());

    // 输出检查结果
    if (isMaxHeap) {
        std::cout << "The vector is a valid max heap." << std::endl;
    } else {
        std::cout << "The vector is not a valid max heap." << std::endl;
    }

    return 0;
}

在这个例子中,我们首先创建了一个整数向量 vec 并初始化为一个序列。然后,我们使用 std::make_heap 将这个序列转换为一个最大堆。最后,我们使用 std::is_heap 检查转换后的向量是否仍然是一个有效的最大堆,并输出检查结果。
自定义比较版本

自定义比较版本的 std::is_heap 接受三个参数:两个迭代器表示要检查的序列的开始和结束,以及一个比较函数或可调用对象,用于定义堆的顺序。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义比较函数,用于定义最小堆的顺序
bool isLess(int a, int b) {
    return a < b;
}

int main() {
    // 创建一个整数向量并初始化为最小堆
    std::vector<int> vec = {1, 3, 5, 7, 9};

    // 使用自定义比较函数检查向量是否是一个有效的最小堆
    bool isMinHeap = std::is_heap(vec.begin(), vec.end(), isLess);

    // 输出检查结果
    if (isMinHeap) {
        std::cout << "The vector is a valid min heap." << std::endl;
    } else {
        std::cout << "The vector is not a valid min heap." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个自定义比较函数 isLess,用于检查一个整数是否小于另一个整数。然后,我们创建了一个整数向量 vec 并初始化为一个最小堆。最后,我们使用 std::is_heap 和自定义比较函数检查这个向量是否仍然是一个有效的最小堆,并输出检查结果。

is_heap_until()

std::is_heap_until 是 C++ 标准库中的一个泛型算法,用于确定给定范围内的元素序列保持堆性质的最后位置。换句话说,它会找到最后一个违反堆性质的元素,并返回指向该元素之后的位置的迭代器。如果整个序列都是有效的堆,那么它将返回范围的末尾迭代器。

std::is_heap_until 有两个版本:默认版本和自定义比较版本。
默认版本

默认版本的 std::is_heap_until 接受两个迭代器作为参数,分别表示要检查的序列的开始和结束。它返回一个迭代器,指向保持堆性质的最后一个元素之后的位置。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 创建一个整数向量并初始化为最大堆
    std::vector<int> vec = {9, 5, 7, 3, 1, 2, 6};

    // 假设 vec 的前五个元素是有效的最大堆

    // 使用 is_heap_until 查找违反堆性质的第一个元素
    auto it = std::is_heap_until(vec.begin(), vec.end());

    // it 现在指向第一个违反堆性质的元素,即 vec[5]

    // 输出结果
    std::cout << "The sequence is a valid heap until position: " 
              << std::distance(vec.begin(), it) << std::endl;

    return 0;
}

在这个例子中,我们创建了一个包含七个元素的整数向量 vec。假设前五个元素(9, 5, 7, 3, 1)是一个有效的最大堆,但从第六个元素开始,堆性质被破坏了(因为 1 大于 2)。std::is_heap_until 将返回指向第六个元素(即 2)的迭代器,因为这个元素是第一个违反堆性质的元素。
自定义比较版本

自定义比较版本的 std::is_heap_until 接受三个参数:两个迭代器表示要检查的序列的开始和结束,以及一个比较函数或可调用对象,用于定义堆的顺序。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义比较函数,用于定义最小堆的顺序
bool isLess(int a, int b) {
    return a < b;
}

int main() {
    // 创建一个整数向量并初始化为最小堆
    std::vector<int> vec = {1, 3, 5, 7, 9, 2, 6};

    // 假设 vec 的前五个元素是有效的最小堆

    // 使用自定义比较函数和 is_heap_until 查找违反堆性质的第一个元素
    auto it = std::is_heap_until(vec.begin(), vec.end(), isLess);

    // it 现在指向第一个违反堆性质的元素,即 vec[5]

    // 输出结果
    std::cout << "The sequence is a valid heap until position: " 
              << std::distance(vec.begin(), it) << std::endl;

    return 0;
}

在这个例子中,我们定义了一个自定义比较函数 isLess,用于检查一个整数是否小于另一个整数。然后,我们创建了一个包含七个元素的整数向量 vec,并假设前五个元素(1, 3, 5, 7, 9)是一个有效的最小堆。从第六个元素开始,堆性质被破坏了(因为 9 小于 2)。使用自定义比较函数和 std::is_heap_until,我们可以找到第一个违反最小堆性质的元素(即 2),并输出其位置。

all_of()

std::all_of 是 C++ 标准库中的一个算法,它用于检查给定范围内的所有元素是否都满足某个条件。该算法接受一个范围(由两个迭代器定义)和一个断言函数或可调用对象,然后应用该断言函数到范围中的每个元素,并检查是否所有元素都使断言函数返回 true。如果所有元素都满足条件,则 std::all_of 返回 true,否则返回 false。
默认版本

默认版本的 std::all_of 使用给定的断言函数或 lambda 表达式来检查范围内的所有元素。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 创建一个整数向量
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用 std::all_of 检查所有元素是否都大于 0
    bool allPositive = std::all_of(numbers.begin(), numbers.end(), [](int n) {
        return n > 0;
    });

    // 输出结果
    if (allPositive) {
        std::cout << "All numbers are positive." << std::endl;
    } else {
        std::cout << "There are negative numbers." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个 lambda 表达式来检查一个整数是否大于 0。std::all_of 应用这个 lambda 表达式到 numbers 向量中的每个元素,并因为所有元素都大于 0,所以返回 true。
自定义断言版本

你也可以提供一个自定义的断言函数作为 std::all_of 的第三个参数。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义断言函数,检查一个整数是否是偶数
bool isEven(int n) {
    return n % 2 == 0;
}

int main() {
    // 创建一个整数向量
    std::vector<int> numbers = {2, 4, 6, 8, 10};

    // 使用自定义断言函数检查所有元素是否都是偶数
    bool allEven = std::all_of(numbers.begin(), numbers.end(), isEven);

    // 输出结果
    if (allEven) {
        std::cout << "All numbers are even." << std::endl;
    } else {
        std::cout << "There are odd numbers." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个名为 isEven 的函数,它检查一个整数是否是偶数。然后,我们将这个函数作为 std::all_of 的第三个参数,以检查 numbers 向量中的所有元素是否都是偶数。因为所有元素都是偶数,所以 std::all_of 返回 true。

这两种版本(默认和自定义断言)的用法都非常灵活,可以根据需要选择使用 lambda 表达式还是自定义函数来定义检查条件

any_of()

std::any_of 是 C++ 标准库中的一个算法,用于检查给定范围内的元素是否满足某个条件。这个算法会应用一个断言函数或可调用对象到范围中的每个元素,并返回 true 一旦找到使断言函数返回 true 的元素,否则如果范围中的所有元素都不满足条件,则返回 false。

std::any_of 有两个版本:默认版本和自定义断言版本。
默认版本

默认版本的 std::any_of 接受两个迭代器表示范围的开始和结束,以及一个断言函数或可调用对象。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 创建一个整数向量
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用 std::any_of 检查是否有任何元素是偶数
    bool hasEven = std::any_of(numbers.begin(), numbers.end(), [](int n) {
        return n % 2 == 0;
    });

    // 输出结果
    if (hasEven) {
        std::cout << "There are even numbers in the range." << std::endl;
    } else {
        std::cout << "There are no even numbers in the range." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个 lambda 表达式来检查一个整数是否是偶数。std::any_of 应用这个 lambda 表达式到 numbers 向量中的每个元素,一旦找到至少一个偶数,就返回 true。
自定义断言版本

你也可以提供一个自定义的断言函数作为 std::any_of 的第三个参数。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义断言函数,检查一个整数是否大于某个值
bool isGreaterThanThree(int n) {
    return n > 3;
}

int main() {
    // 创建一个整数向量
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用自定义断言函数检查是否有任何元素大于3
    bool hasGreaterThanThree = std::any_of(numbers.begin(), numbers.end(), isGreaterThanThree);

    // 输出结果
    if (hasGreaterThanThree) {
        std::cout << "There are numbers greater than 3 in the range." << std::endl;
    } else {
        std::cout << "There are no numbers greater than 3 in the range." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个名为 isGreaterThanThree 的函数,它检查一个整数是否大于 3。然后,我们将这个函数作为 std::any_of 的第三个参数,以检查 numbers 向量中是否有任何元素大于 3。因为 4 和 5 都大于 3,所以 std::any_of 返回 true。

这两种版本(默认和自定义断言)的用法都非常灵活,可以根据需要选择使用 lambda 表达式还是自定义函数来定义检查条件。

none_of()

std::none_of 是 C++ 标准库中的一个算法,用于检查给定范围内的元素是否都不满足某个条件。换句话说,它验证是否没有一个元素使给定的断言函数或可调用对象返回 true。如果范围内没有元素满足条件,std::none_of 返回 true,否则返回 false。
默认版本

默认版本的 std::none_of 接受两个迭代器表示范围的开始和结束,以及一个断言函数或可调用对象。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    // 创建一个整数向量
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用 std::none_of 检查是否没有任何元素是偶数
    bool noEvenNumbers = std::none_of(numbers.begin(), numbers.end(), [](int n) {
        return n % 2 == 0;
    });

    // 输出结果
    if (noEvenNumbers) {
        std::cout << "There are no even numbers in the range." << std::endl;
    } else {
        std::cout << "There are even numbers in the range." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个 lambda 表达式来检查一个整数是否是偶数。std::none_of 应用这个 lambda 表达式到 numbers 向量中的每个元素。因为 numbers 向量中至少有一个元素(即 2)是偶数,所以 std::none_of 返回 false。
自定义比较版本

你也可以提供一个自定义的比较函数作为 std::none_of 的第三个参数。

示例:

#include <iostream>
#include <vector>
#include <algorithm>

// 自定义比较函数,检查一个整数是否小于等于 3
bool isLessThanOrEqualToThree(int n) {
    return n <= 3;
}

int main() {
    // 创建一个整数向量
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用自定义比较函数检查是否没有任何元素小于等于 3
    bool noElementLessThanOrEqualToThree = std::none_of(numbers.begin(), numbers.end(), isLessThanOrEqualToThree);

    // 输出结果
    if (noElementLessThanOrEqualToThree) {
        std::cout << "There are no numbers less than or equal to 3 in the range." << std::endl;
    } else {
        std::cout << "There are numbers less than or equal to 3 in the range." << std::endl;
    }

    return 0;
}

在这个例子中,我们定义了一个名为 isLessThanOrEqualToThree 的函数,它检查一个整数是否小于或等于 3。然后,我们将这个函数作为 std::none_of 的第三个参数,以检查 numbers 向量中是否有任何元素小于或等于 3。因为 numbers 向量中有多个元素(即 1、2、3)满足这个条件,所以 std::none_of 返回 false。

这两个版本(默认和自定义比较)都允许你灵活地使用 lambda 表达式或自定义函数来定义检查条件,以便确定范围内是否有元素满足该条件。

  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊猫Devin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值