【C++提高编程-09】----C++ STL之常用排序算法

🎩 欢迎来到技术探索的奇幻世界👨‍💻

📜 个人主页@一伦明悦-CSDN博客

✍🏻 作者简介: C++软件开发、Python机器学习爱好者

🗣️ 互动与支持💬评论      👍🏻点赞      📂收藏     👀关注+

如果文章有所帮助,欢迎留下您宝贵的评论,

点赞加收藏支持我,点击关注,一起进步!

前言

       STL(Standard Template Library)是C++标准库的一部分,提供了丰富的数据结构和算法,用于处理数据和实现常见的计算任务。STL中的算法分为几类,包括遍历算法、修改算法、排序算法、查找算法、数值算法等,每类算法都有其特定的应用场景和功能。

正文

01-排序算法之sort用法     

sort 算法详解

语法

template <class RandomAccessIterator>
void sort (RandomAccessIterator first, RandomAccessIterator last);

template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
  • RandomAccessIterator:表示随机访问迭代器类型,用于指定排序范围。
  • first:表示排序范围的起始位置。
  • last:表示排序范围的结束位置,不包含在范围内。
  • comp:可选参数,用于指定排序的比较函数对象。

参数

  • first:排序范围的起始位置。
  • last:排序范围的结束位置,不包含在范围内。
  • comp:可选参数,用于指定排序的比较函数对象。如果不提供此参数,默认使用 < 运算符进行比较。

功能

sort 算法用于对范围 [first, last) 内的元素进行排序,默认以升序方式排列。

返回值

  • sort 函数没有返回值,直接在原始范围上进行排序操作。

示例

以下是使用 sort 算法对整数向量进行排序的示例:

#include <iostream>
#include <vector>
#include <algorithm> // 包含 sort 函数

int main() {
    std::vector<int> numbers = {5, 2, 8, 3, 1, 4};

    // 使用 sort 对向量进行升序排序
    std::sort(numbers.begin(), numbers.end());

    std::cout << "升序排序后的结果为: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果将是 “升序排序后的结果为: 1 2 3 4 5 8”。在这个例子中,sort 函数对向量 numbers 中的元素进行了升序排序,并输出排序后的结果。

注意事项

  • sort 算法默认使用 < 运算符进行比较,可通过提供自定义的比较函数对象 comp 进行特定排序。
  • 对于自定义数据类型,确保比较函数对象 comp 或重载 < 运算符,以确保算法能正确比较对象。

通过 sort 算法,可以方便地对容器内的元素进行排序操作,适用于各种数据结构和排序需求。

        这段代码演示了C++中对vector容器内元素进行排序的基本用法,并展示了如何使用自定义的比较函数来实现不同的排序顺序。

  1. 包含头文件和定义函数

    • #include <algorithm>:包含了标准库中的排序算法 sort 和 greater
    • #include <vector>:包含了使用的容器 vector
    • void myPrint(int val):定义了一个简单的函数 myPrint,用于输出整数值。
  2. 定义测试函数 test01()

    • 创建了一个整数类型的 vector v,并向其中添加了几个整数元素。
    • 使用 sort(v.begin(), v.end()) 对 vector v 进行升序排序(默认情况下)。
    • 使用 for_each(v.begin(), v.end(), myPrint) 遍历输出排序后的元素,函数 myPrint 负责打印每个元素。
    • 执行 cout << endl; 输出换行。
  3. 反向排序示例

    • 使用 sort(v.begin(), v.end(), greater<int>()) 对 vector v 进行降序排序。greater<int>() 是一个函数对象,表示按照大于号 (>) 的方式进行比较。
    • 再次使用 for_each(v.begin(), v.end(), myPrint) 输出降序排序后的元素。
    • 执行 cout << endl; 输出换行。
  4. 主函数 main()

    • 调用 test01() 函数来执行上述排序和输出操作。
    • 最后使用 system("pause"); 在控制台暂停程序的执行,等待用户按下任意键结束程序。

这段代码通过展示 sort 函数的基本使用,演示了如何实现升序和降序排序,以及如何自定义比较函数来满足不同的排序需求。

#include <algorithm>
#include <vector>
void myPrint(int val)
{
	cout << val << " ";
}
void test01() {
	vector<int> v;
	v.push_back(10);
	v.push_back(30);
	v.push_back(50);
	v.push_back(20);
	v.push_back(40);
	//sort默认从小到大排序
	sort(v.begin(), v.end());
	for_each(v.begin(), v.end(), myPrint);
	cout << endl;
	//从大到小排序
	sort(v.begin(), v.end(), greater<int>());
	for_each(v.begin(), v.end(), myPrint);
	cout << endl;
}
int main() {
	test01();
	system("pause");
	return 0;
}

02-排序算法之random_shuffle用法     

random_shuffle 算法详解

语法

template <class RandomAccessIterator>
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last);

template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle (RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator&& rand);
  • RandomAccessIterator:表示随机访问迭代器类型,用于指定要打乱的范围。
  • first:表示打乱范围的起始位置。
  • last:表示打乱范围的结束位置,不包含在范围内。
  • rand:可选参数,表示用于生成随机数的随机数生成器对象。

参数

  • first:打乱范围的起始位置。
  • last:打乱范围的结束位置,不包含在范围内。
  • rand:可选参数,用于指定随机数生成器对象。如果不提供此参数,默认使用 std::default_random_engine 生成随机数。

功能

random_shuffle 算法用于对范围 [first, last) 内的元素进行随机打乱。

返回值

  • random_shuffle 函数没有返回值,直接在原始范围上进行元素打乱操作。

示例

以下是使用 random_shuffle 算法对整数向量进行随机打乱的示例:

#include <iostream>
#include <vector>
#include <algorithm> // 包含 random_shuffle 函数
#include <random> // 包含随机数生成器

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 使用 random_shuffle 对向量进行随机打乱
    std::random_shuffle(numbers.begin(), numbers.end());

    std::cout << "随机打乱后的结果为: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果将是随机的顺序,例如 “随机打乱后的结果为: 5 7 1 4 3 2 8 9 10 6”。在这个例子中,random_shuffle 函数对向量 numbers 中的元素进行了随机打乱,并输出打乱后的结果。

注意事项

  • random_shuffle 算法使用默认的随机数生成器来生成随机数。如果需要定制化的随机数生成器,可以提供自定义的随机数生成器对象。
  • 对于自定义数据类型,确保实现了迭代器的随机访问能力,以便算法能正确操作范围内的元素。

通过 random_shuffle 算法,可以方便地对容器内的元素进行随机打乱操作,适用于各种需要随机顺序的场景。

这段代码展示了如何使用 C++ 的 random_shuffle 算法对 vector 容器内的元素进行随机打乱,并输出打乱后的结果。

  1. 包含头文件和定义类

    • #include <algorithm>:包含了标准库中的 random_shuffle 算法。
    • #include <vector>:包含了使用的容器 vector
    • #include <ctime>:包含了 time 函数,用于获取当前时间。
    • #include <cstdlib>:包含了 srand 和 rand 函数,用于设置和获取随机数种子。
  2. 定义类 myPrint

    • class myPrint:定义了一个仿函数 (function object),其中重载了 operator(),用于输出整数值。
  3. 定义测试函数 test01()

    • srand((unsigned int)time(NULL));:通过调用 srand 函数设置随机数种子,使用当前时间作为种子,确保每次运行得到不同的随机结果。
    • 创建了一个整数类型的 vector v,并使用 for 循环向其中添加了整数元素 0 到 9。
    • 使用 for_each(v.begin(), v.end(), myPrint()) 遍历输出 vector 中的元素,函数对象 myPrint 负责打印每个元素。
    • 执行 cout << endl; 输出换行。
  4. 随机打乱示例

    • 使用 random_shuffle(v.begin(), v.end()) 对 vector v 中的元素进行随机打乱。
    • 再次使用 for_each(v.begin(), v.end(), myPrint()) 输出打乱后的元素。
    • 执行 cout << endl; 输出换行。
  5. 主函数 main()

    • 调用 test01() 函数来执行上述随机打乱和输出操作。
    • 使用 system("pause"); 在控制台暂停程序的执行,等待用户按下任意键结束程序。

这段代码通过调用 random_shuffle 函数实现了对 vector 容器内元素的随机打乱,展示了如何利用随机数种子确保每次打乱结果的随机性。

#include <algorithm>
#include <vector>
#include <ctime>
class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};
void test01()
{
	srand((unsigned int)time(NULL));
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
	//打乱顺序
	random_shuffle(v.begin(), v.end());
	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
}
int main() {
	test01();
	system("pause");
	return 0;
}

03-排序算法之merge用法     

merge 算法详解

语法

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator merge (InputIterator1 first1, InputIterator1 last1,
                      InputIterator2 first2, InputIterator2 last2,
                      OutputIterator result);
  • InputIterator1:表示第一个有序序列的迭代器类型。
  • InputIterator2:表示第二个有序序列的迭代器类型。
  • OutputIterator:表示目标序列的迭代器类型。

参数

  • first1:第一个有序序列的起始位置。
  • last1:第一个有序序列的结束位置(不包含在范围内)。
  • first2:第二个有序序列的起始位置。
  • last2:第二个有序序列的结束位置(不包含在范围内)。
  • result:目标序列的起始位置,用于存储合并后的有序序列。

功能

merge 算法用于将两个已排序的序列合并为一个新的有序序列,并存储到目标序列中。

返回值

  • merge 函数返回一个迭代器,指向目标序列中的末尾位置(合并后序列的下一个位置)。

示例

以下是使用 merge 算法将两个已排序的向量合并为一个新的有序向量的示例:

#include <iostream>
#include <vector>
#include <algorithm> // 包含 merge 函数

int main() {
    std::vector<int> v1 = {1, 3, 5, 7, 9};
    std::vector<int> v2 = {2, 4, 6, 8, 10};
    std::vector<int> merged(v1.size() + v2.size());

    // 使用 merge 将 v1 和 v2 合并为 merged
    std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), merged.begin());

    std::cout << "合并后的有序序列为: ";
    for (int num : merged) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果将是合并后的有序序列,例如 “合并后的有序序列为: 1 2 3 4 5 6 7 8 9 10”。在这个例子中,merge 函数将两个已排序的向量 v1 和 v2 合并为一个新的有序向量 merged

注意事项

  • merge 算法要求输入序列必须是已排序的,否则结果将不符合预期。
  • 如果输入序列有重复元素,merge 算法会保持这些重复元素的顺序。
  • 目标序列 result 的长度必须足够大,能够容纳合并后的所有元素,否则可能导致未定义行为。

通过 merge 算法,可以方便地将两个已排序的序列合并为一个新的有序序列,适用于各种需要合并排序结果的场景。

这段代码展示了如何使用 C++ 的 merge 算法将两个已排序的 vector 合并到一个新的目标 vector 中,并通过自定义的 myPrint 函数对象输出合并后的结果。

代码解释

  1. 包含头文件和定义类

    #include <algorithm>  // 包含 merge 算法
    #include <vector>
    #include <iostream>   // 包含 cout 和 endl
    using namespace std;  // 使用标准命名空间
    
    • #include <algorithm>:包含了标准库中的 merge 算法。
    • #include <vector>:包含了使用的容器 vector
    • #include <iostream>:用于标准输出 cout 和换行 endl
    • using namespace std;:使用标准库的命名空间,避免每次使用标准库中的元素时都需要加上 std:: 前缀。
  2. 定义类 myPrint

    class myPrint
    {
    public:
        void operator()(int val)
        {
            cout << val << " ";
        }
    };
    
    • myPrint 类是一个函数对象,重载了 operator(),用于输出整数值 val,并在每个值后面添加空格。
  3. 定义测试函数 test01()

    void test01()
    {
        vector<int> v1;
        vector<int> v2;
    
        // 向 v1 和 v2 中添加元素
        for (int i = 0; i < 10; i++)
        {
            v1.push_back(i);
            v2.push_back(i + 1);
        }
    
        vector<int> vtarget;
        // 目标容器 vtarget 需要提前开辟空间
        vtarget.resize(v1.size() + v2.size());
    
        // 合并两个有序序列 v1 和 v2 到 vtarget 中
        merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vtarget.begin());
    
        // 使用 for_each 和 myPrint 输出合并后的结果
        for_each(vtarget.begin(), vtarget.end(), myPrint());
        cout << endl;
    }
    
    • 创建了两个 vector 容器 v1 和 v2,分别存储整数序列 {0, 1, 2, ..., 9} 和 {1, 2, 3, ..., 10}
    • 创建了一个目标容器 vtarget,使用 resize 函数提前为其分配了足够的空间,以便存储合并后的结果。
    • 调用 merge 函数,将 v1 和 v2 中的元素合并到 vtarget 中。
    • 使用 for_each 算法遍历 vtarget,并利用 myPrint 函数对象输出每个元素。
  4. 主函数 main()

    int main() {
        test01();
        system("pause");
        return 0;
    }
    
    • 在 main 函数中调用 test01() 来执行上述合并和输出操作。
    • 使用 system("pause") 让程序在控制台暂停,等待用户按任意键结束程序的执行。

总结

这段代码展示了如何利用 merge 算法将两个已排序的 vector 合并成一个新的有序 vector,并通过自定义的函数对象 myPrint 输出合并后的结果。使用 resize 来提前分配空间,确保目标容器能够容纳所有合并后的元素,是 merge 算法使用的必要步骤之一。

#include <algorithm>
#include <vector>
class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};
void test01()
{
	vector<int> v1;
	vector<int> v2;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(i + 1);
	}
	vector<int> vtarget;
	//目标容器需要提前开辟空间
	vtarget.resize(v1.size() + v2.size());
	//合并 需要两个有序序列
	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vtarget.begin());
	for_each(vtarget.begin(), vtarget.end(), myPrint());
	cout << endl;
}
int main() {
	test01();
	system("pause");
	return 0;
}

04-排序算法之reverse用法     

排序算法之reverse用法详细解释一下

reverse 算法详解

语法

template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last);
  • BidirectionalIterator:表示一个能够向前和向后遍历的迭代器类型。

参数

  • first:要反转的序列的起始位置。
  • last:要反转的序列的结束位置(不包含在范围内)。

功能

reverse 算法用于将指定范围内的元素顺序完全反转。

示例

以下是使用 reverse 算法反转一个 vector 的示例:

#include <iostream>
#include <vector>
#include <algorithm> // 包含 reverse 函数

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 使用 reverse 将 vector 反转
    std::reverse(v.begin(), v.end());

    std::cout << "反转后的 vector: ";
    for (int num : v) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

输出结果将是反转后的 vector,例如 “反转后的 vector: 5 4 3 2 1”。在这个例子中,reverse 函数将 v 中的元素顺序完全反转。

注意事项

  • reverse 算法会直接修改原始序列,而不是返回新的序列。
  • 序列中的元素顺序完全反转,即第一个元素变成最后一个,最后一个变成第一个,依此类推。
  • 如果 first == last,或者序列中只有一个元素,则不会进行任何操作。

通过 reverse 算法,可以方便地对容器或者数组中的元素顺序进行反转操作,适用于各种需要逆序处理的场景。

这段代码展示了如何使用 C++ 标准库中的 reverse 算法来反转一个 vector 中的元素,并通过自定义的 myPrint 函数对象输出反转前后的结果。

  1. 包含头文件和定义类

    #include <algorithm>  // 包含 reverse 算法
    #include <vector>
    #include <iostream>   // 包含 cout 和 endl
    using namespace std;  // 使用标准命名空间
    
    • #include <algorithm>:包含了标准库中的 reverse 算法。
    • #include <vector>:包含了使用的容器 vector
    • #include <iostream>:用于标准输出 cout 和换行 endl
    • using namespace std;:使用标准库的命名空间,避免每次使用标准库中的元素时都需要加上 std:: 前缀。
  2. 定义类 myPrint

    class myPrint
    {
    public:
        void operator()(int val)
        {
            cout << val << " ";
        }
    };
    
    • myPrint 类是一个函数对象,重载了 operator(),用于输出整数值 val,并在每个值后面添加空格。
  3. 定义测试函数 test01()

    void test01()
    {
        vector<int> v = {10, 30, 50, 20, 40};
    
        cout << "反转前: " << endl;
        for_each(v.begin(), v.end(), myPrint());
        cout << endl;
    
        // 使用 reverse 函数反转 vector v 中的元素
        reverse(v.begin(), v.end());
    
        cout << "反转后: " << endl;
        for_each(v.begin(), v.end(), myPrint());
        cout << endl;
    }
    
    • 创建了一个 vector 容器 v,并向其中添加了整数元素 {10, 30, 50, 20, 40}

    • 使用 for_each 算法和自定义的 myPrint 函数对象输出 vector 中的元素,展示了反转前的顺序。

    • 调用 reverse(v.begin(), v.end()) 将 vector v 中的元素顺序完全反转。

    • 再次使用 for_each 和 myPrint 输出反转后的 vector 元素顺序。

  4. 主函数 main()

    int main() {
        test01();
        system("pause");
        return 0;
    }
    
    • 在 main 函数中调用 test01() 来执行上述反转和输出操作。
    • 使用 system("pause") 让程序在控制台暂停,等待用户按任意键结束程序的执行。

总结

这段代码演示了如何使用 C++ 标准库的 reverse 算法来反转 vector 容器中的元素。通过 reverse 函数可以快速、方便地修改容器中元素的顺序,适用于需要倒序处理数据的各种场景。

#include <algorithm>
#include <vector>
class myPrint
{
public:
	void operator()(int val)
	{
		cout << val << " ";
	}
};
void test01()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(30);
	v.push_back(50);
	v.push_back(20);
	v.push_back(40);
	cout << "反转前: " << endl;
	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
	cout << "反转后: " << endl;
	reverse(v.begin(), v.end());
	for_each(v.begin(), v.end(), myPrint());
	cout << endl;
}
int main() {
	test01();
	system("pause");
	return 0;
}

总结

      STL(Standard Template Library)提供了多种排序算法,每种算法都有其特定的优势和适用场景。

  • 33
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一伦明悦

感谢,您的支持是我最大的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值