STL源码剖析 算法开篇

53 篇文章 1 订阅
31 篇文章 2 订阅

质变算法

  • 质变算法 - 会改变操作对象的数值,比如互换、替换、填写、删除、排列组合、分隔、随机重排、排序等
#include <iostream>
#include <vector>

int main(){
    int ia[] = {22,30,20,34,45,64,34,56,75,34};
    std::vector<int>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<int>::const_iterator cit1 = iv.begin();
//    std::vector<int>::const_iterator cit2 = iv.end();
//    std::sort(iv.begin(),iv.end());

    std::vector<int>::iterator cit1 = iv.begin();
    std::vector<int>::iterator cit2 = iv.end();
    std::sort(cit1,cit2);


}

非质变算法

  • 运算过程中不会改变 迭代器标示出来的区间上的元素内容。查找(find)、匹配(find_if)、计数(count)、巡防(for_each)、比较(equal)、寻找极值(max、min)等
  • 但是如果在迭代区间上应用一个会改变元素内容的仿函数,也会改变元素的数值
#include <iostream>
#include <vector>

template<class T>
struct plus2{
    void operator()(T& x){
        x += 2;
    }
};

//template <class T>
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<int>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<int>());
    std::for_each(iv.begin(),iv.end(), plus3_fun);
    for (int i : iv) {
        std::cout << i << ' ';
    }
}
  • 算法的泛型话的主要目的是为了,抽象化操作对象的型别、操作对象的标示法和区间目标的移动行为,整个算法也就在一个抽象层面了
  • 以简单的循环查找为例,写一个find函数
#include<iostream>

int * 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指针进行比较,但是不能提领其数值
#include<iostream>

int * 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是指最后元素的下一个位置)
#include<iostream>

int * 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 T> //关键词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的下一个节点,这里指定的是迭代器,其本质是一种智能指针,也就是行为类似指针的对象。
template <class Iterator,class T>
Iterator find(Iterator begin,Iterator end,const T& value){
    while (begin != end && *begin!=value){
        ++begin;
    }
    return begin;
}    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值