- STL源码剖析 算法章节 算法总览_CHYabc123456hh的博客-CSDN博客
- 质变算法 - 会改变 *** 作对象的数值,比如互换、替换、填写、删除、排列组合、分隔、随机重排、排序等
#include非质变算法#include int main(){ int ia[] = {22,30,20,34,45,64,34,56,75,34}; std::vector iv(ia,ia+(sizeof (ia) / sizeof (int))); for (int i = 0; i < iv.size(); ++i) { std::cout << iv[i] << ' '; } std::cout << std::endl; std::cout << iv.size() << ' '; //错误的 sort属于质变算法 不应该使用const迭代器 // std::vector ::const_iterator cit1 = iv.begin(); // std::vector ::const_iterator cit2 = iv.end(); // std::sort(iv.begin(),iv.end()); std::vector ::iterator cit1 = iv.begin(); std::vector ::iterator cit2 = iv.end(); std::sort(cit1,cit2); }
- 运算过程中不会改变 迭代器标示出来的区间上的元素内容。查找(find)、匹配(find_if)、计数(count)、巡防(for_each)、比较(equal)、寻找极值(max、min)等
- 但是如果在迭代区间上应用一个会改变元素内容的仿函数,也会改变元素的数值
#include#include template struct plus2{ void operator()(T& x){ x += 2; } }; //template void plus3_fun(int& x){ x += 3; // std::cout << x << " "; } int main(){ int ia[] = {22,30,20,34,45,64,34,56,75,34}; std::vector iv(ia,ia+(sizeof (ia) / sizeof (int))); for (int i : iv) { std::cout << i << ' '; } std::cout << std::endl; std::cout << iv.size() << ' '; std::cout << std::endl; // std::for_each(iv.begin(),iv.end(),plus2 ()); std::for_each(iv.begin(),iv.end(), plus3_fun); for (int i : iv) { std::cout << i << ' '; } }
- 算法的泛型话的主要目的是为了,抽象化 *** 作对象的型别、 *** 作对象的标示法和区间目标的移动行为,整个算法也就在一个抽象层面了
- 以简单的循环查找为例,写一个find函数
#includeint * find(int* arrayHead,int arraySize,int value){ int i = 0; for (; i < arraySize; ++i) { if (arrayHead[i] == value){ break; } } return &(arrayHead[i]); } int main(){ int array[] = {11,13,34,56,77,8,945,56}; int *ptr = nullptr; std::cout << sizeof(array) << std::endl; ptr = find(array,8,13); std::cout << *ptr; }
- 设定end()即为指向array尾端以外的任何位置,主要目的是为了和其他array指针进行比较,但是不能提领其数值
#includeint * find(int* arrayHead,int arraySize,int value){ int i = 0; for (; i < arraySize; ++i) { if (arrayHead[i] == value){ break; } } return &(arrayHead[i]); } int main(){ const int size = 8; int array[] = {11,13,34,56,77,8,945,56}; int *end = array + size;//最后一个元素的位置 int *ptr = nullptr; std::cout << sizeof(array)/sizeof(int) << std::endl; ptr = find(array,sizeof(array)/sizeof(int),13); if (ptr == end){ std::cout << "Not found!" << std::endl; } else{ std::cout << *ptr << " found!" << std::endl; } }
- 上述find()暴露了容器太多的细节,且太限定于特定的容器。为了让find函数适配于所有类型的容器,其 *** 作需要更进一步的抽象化
int * find(int* begin,int* end,int value){ while (begin != end && *begin != value){ ++begin; } return begin; }
- 上述函数适用于[begin() , end) (不包含end指针,end是指最后元素的下一个位置)
#includeint * find(int* begin,int* end,int value){ while (begin != end && *begin != value){ ++begin; } return begin; } int main(){ const int size = 8; int array[] = {11,13,34,56,77,8,945,56}; int *end = array + size;//最后一个元素的位置 int*ptr = find(array,end,13); if (ptr == end){ std::cout << "not found" << std::endl; } else std::cout << *ptr << " found" << std::endl; //也可以适用于查找特定的子区间 int* ip = find(array+2,array+5,3); }
- 更进一步将其修改为模板的形式
template//关键词typename 也可以使用class替代 T * find(T* begin,T* end,T value){ //以下用到了operator!= operator* operator++ //需要 *** 作符重载 while (begin != end && *begin != value){ ++begin; } //以下 *** 作 会引发copy行为 return begin; }
- 数值的传递可由 pass by value改为pass by reference to const 主要目的是出于不是基本数据类型,对象很大,传递成本很高,使用引用传递可以避免这些成本
- 更进一步 超出指针的思维局限,比如find函数针对的是list,对于指针进行++运算不会将指针指向下一个串行节点,但是如果设计一个class,拥有原生指针的行为,并且对其进行++ *** 作可以指向list的下一个节点,这里指定的是迭代器,其本质是一种智能指针,也就是行为类似指针的对象。
templateIterator find(Iterator begin,Iterator end,const T& value){ while (begin != end && *begin!=value){ ++begin; } return begin; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)