C++进阶 - STL算法设计理念分析
C++ 中 STL 的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
学好 STL 其实主要在于其设计理念和算法实现,再清晰一点其实就是 algorithm(算法)、container(容器)和iterator(迭代器)的分离思想,我们平时也可以把这种思想用到我们的 Android 开发中,甚至是任意一门语言。
基于这种思想,我们来看一个简单的例子,比如要对一个班的学生按成绩等级进行排序,我们是这么写的。
// 函数对象 仿函数
struct comparefuction
{
// 函数重载了 () 运算符,函数对象,仿函数
bool operator()(const Student& _Left, const Student& _Right) const{
return _Left.grade > _Right.grade;
}
};
// 对象数据类型
void main(){
set<Student, comparefuction> s;
Student s1("Darren1", 2);
Student s2("Darren2", 9);
Student s3("Darren3", 5);
s.insert(s1);
s.insert(s2);
s.insert(s3);
for (set<Student>::iterator it = s.begin(); it != s.end(); it++)
{
cout << it->name.c_str() << "," << it->grade << endl;
}
getchar();
}
通过上面的事例我们就能发现,容器的内部排序算法与数据是分离的,也就是说 set 集合无论放什么样的数据都能排序,而排序的规则是由仿函数来决定。这有点类似于 Android 开发中的接口。
平时我们在写项目代码的时候,完全可以参考这种思想。我的架构、数据、业务和逻辑是否是分离的,是否适用于各种场景?当然平时我们要学会画 UML 图,脑子里要有各种设计模式和它的使用场景,看大量的第三方库和系统源码,并且能从中吸取营养,学习知识时,不再是简单的停留在用的层次,而是会去思考别人的设计理念。接下来我们再举一个非常简单的例子,比如排序算法,这里我们就用最一种最简单的排序方式 - 冒泡排序。
// 冒泡排序 - 基础版
void bubblesort(int arr[], int len)
{
// 双层循环
int i, j;
for (i = 0; i < len - 1; i++)
{
for (j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
swap(arr[j], arr[j + 1]);
}
}
}
}
排序算法还要自己写吗?系统本来就有 sort 这个函数,我们这里只是举个例子。但是还是想问一下各位看官哪那种排序算法最好?我们基本都会认为时间复杂度为 O(n*log2n) 的排序算法较佳,但其实各种排序算法在不同场景下都有不同的优势,没有最好只有最合适。现在我们回到 STL 的设计理念来,我们需要对数据和算法进行分离,也就是说现在我们的代码只适用于 int 类型,这显然是不符合理念的,我们再对其进行改进。
// 冒泡排序 - 改进版
template <typename T>
void bubblesort(T arr[], int len)
{
// 双层循环
int i, j;
for (i = 0; i < len - 1; i++)
{
for (j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
swap(arr[j], arr[j + 1]);
}
}
}
}
最后我们肯定还可以对冒泡排序算法进行优化,但这已不属于本文的范畴,我们会在后面的数据结构和算法的文章中再去分析。因此学好 STL 不光需要了解系统自带的方法,还需要了解其设计理念,也需要知道其内部算法的具体实现。
视频链接:https://pan.baidu.com/s/1TnWZ3FOIAnxpFZEXTcvCFQ
视频密码:0q1n