• 后台开发核心技术与应用实践看书笔记(三):常用STL的使用


    STL是什么

    STL是一个标准模板库,高效的C++程序库。

    stdlib.h库提供了quit-sort函数。

    string

    //字符指针,字符数组
    char str[12]="hello";
    char *p=str;
    *p='h';//改变第一个字母
    
    char *ptr="hello";
    *ptr='h';//错误
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    第一个字符串用数组开辟,可以改变。

    第二个字符串是一个常量,值是不能改变的,只可以改变指针指向。

    string类的构造函数和析构函数

    string s;                         // 生成一个空字符串
    
    string s(string str)               // 拷贝构造函数生成str的复制品
    
    
    string s(string str,int stridx)          // 将字符串str内“始于位置stridx”的部分当作
                                  // 字符串的初值
    
    string s(char *str,int stridx,int strlen)     // 将字符串str内“始于stridx且长度顶多strlen”
        										// 的部分作为字符串的初值
    
    string s(char *cstr)               // 将C字符串作为s的初值
    
    string s(char *chars,int chars_len)     // 将C字符串前chars_len个字符作为字符串s的
        									// 初值
    
    string s(int num,char c)               // 生成一个字符串,包含num个c字符
    
    string s(char *beg,char *end)          // 以区间beg;end(不包含end)内的字符作为字符
    			                           // 串s的初值
        
    s.~string()                    // 销毁s字符,释放内存
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    C++字符串和C字符串的转换

    左边转右边方法

    • data(),返回字符数组,不添加’\0’
    • c_str(),返回’\0’结尾的字符数组,它是临时的,当原本数据改变后,数据就会失效。
    • copy(),把字符串的内容复制或写入既有c_string或字符数组内。

    C++字符串不以’\0’结尾。

    注意c_str()。

    #include
    #include
    using namespace std;
    int main(){
        string str="Hello world.";
        const char * cstr=str.c_str();
        cout<<cstr<<endl;
        str="Abcd.";
        cout<<cstr<<endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    结果

    hello world.
    abcd.
    
    • 1
    • 2

    容易出现错误。

    可以考虑把数据深拷贝来解决问题

    #include
    #include
    #include
    using namespace std;
    int main(){
    	char * cstr=new char[20];
    	string str="Hello world.";
        strncpy(cstr,str.c_str(),str.size());
        cout<<cstr<<endl;
        str="Abcd.";
        cout<<cstr<<endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    结果

    hello world.
    abcd.
    
    • 1
    • 2

    copy(p,n,size_type_Off=0)这句表明从string类型对象中至多复制n个字符到字符指针p指向的空间中,并且默认从首字符开始,也可以指定开始位置(从0开始计数)。不过需要确保p有n个空间存储。

    string和int类型的转换

    int转string

    int snprintf(char *str,size_t size,const char *format,...)
    
    • 1

    功能是:将可变个参数…按照format格式化成字符串,然后将其复制到str中。

    如果格式化后的字符串长度小于size,则全部复制到str中,并且加上结束符’\0’

    如果格式化后的字符串长度不小于size,则只将其中的(size-1)个字符全部复制到str中,并且加上结束符’\0’

    函数的返回值成功就是写入的字符串长度,出错则返回负值。

    string转int函数(细节暂时不追)

    • strtol
    • strtoll
    • strtoul
    • stroull

    string的其他常用成员函数

    • capacity,返回当前容量
    • size(),当前字符串大小
    • resize(),把字符串当前大小置为len,并用字符c填充不足的部分

    vector

    reserve()方法可以调整分配的容量大小。

    赋值和拷贝构造都是值复制一整份。

    vector的增删改查

    for_each遍历

    #include 
    #include 
    #include 
    using namespace std;
    
    void print(int n)
    {
    	cout<<n<<" ";
    }
    
    int main(){
    	int a[7]={1,2,3,4,5,6,7};
    	vector<int> ivector(a,a+7);
    	vector<int>::iterator iter;
        for_each(ivector.begin(),ivector.end(),print);//ÓÃfor_each½øÐбéÀú  
    	cout<<endl;
    	ivector[5]=1;
    	cout<<ivector[5]<<endl<<ivector.size()<<endl;
    	for_each(ivector.begin(),ivector.end(),print);//ÓÃfor_each½øÐбéÀú  
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    vector中存放结构体时的排序

    #include
    #include
    #include
    using namespace std;
    
    typedef struct rect{
        int id;
        int length;
        int width;
        //按照id,length,width升序排序
        bool operator< (const rect &a) const{
            if(id!=a.id)
                return id<a.id;
            else{
                if(length!=a.length)
                    return length<a.length;
                else
                    return width<a.width;
            }
        }
    }Rect;
    
    int main(){
        vector<Rect> vec;
        Rect rect;
        rect.id=2;
        rect.length=3;
        rect.width=4;
        vec.push_back(rect);
        rect.id=1;
        rect.length=2;
        rect.width=3;
        vec.push_back(rect);
        vector<Rect>::iterator it=vec.begin();
    	cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;  
    	sort(vec.begin(),vec.end());
        cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;  
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    运行结果

    2 3 4
    1 2 3
    
    • 1
    • 2

    另一种方式

    #include
    #include
    #include
    using namespace std;
    
    typedef struct rect{
        int id;
        int length;
        int width;
    }Rect;
    int cmp(Rect a,Rect b){
    	if(a.id!=b.id)
    		return a.id<b.id;
        else{
    		if(a.length!=b.length)
                return a.length<b.length;
            else
                return a.width<b.width;
        }
    }
    
    int main(){
        vector<Rect> vec;
        Rect rect;
        rect.id=2;
        rect.length=3;
        rect.width=4;
        vec.push_back(rect);
        rect.id=1;
        rect.length=2;
        rect.width=3;
        vec.push_back(rect);
        vector<Rect>::iterator it=vec.begin();
    	cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;  
        //调用变化了
    	sort(vec.begin(),vec.end(),cmp);
        cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;  
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    运行结果不变

    vector的查找

    #include
    #include
    #include
    using namespace std;
    int main(){
        vector<int> vec;
        vec.push_back(1);
        vec.push_back(2);
        vec.push_back(3);
        vec.push_back(4);
        vec.push_back(5);
        //调用函数
        vector<int>::iterator iter=find(vec.begin(),vec.end(),3);
        if ( iter==vec.end())
            cout << "Not found" << endl;
        else
            cout << "Found" << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    vector的删除

    pop_back删除最后一个元素

    vec.erase(vec.begin()+i,vec.end()+j)删除区间[i,j-1]间的元素。

    for(vector<int>::iterator iter=veci.begin();iter!=veci.end();iter++)
    {
        if(*iter==3)veci.erase(iter);
    }
    
    • 1
    • 2
    • 3
    • 4

    代码隐藏严重错误,当veci.erase(iter)语句执行了之后,iter就变成了一个野指针,对一个野指针进行iter++操作出错。

    修改代码为

    for(vector<int>::iterator iter=veci.begin();iter!=veci.end();iter++)
    {
        if(*iter==3)iter=veci.erase(iter);
    }
    
    • 1
    • 2
    • 3
    • 4

    还是错的,无法删除两个连续的3,数字3位于vector最后位置也会出错(在vec.end()上执行++操作)。

    正确代码

    for(;iter!=vec.end();)
    {
        if(*iter==3)iter=veci.erase(iter);
        else ++iter;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    vector的增加

    #include
    #include
    #include
    using namespace std;
    void print( vector<int>v ){
    	vector<int>::iterator iter=v.begin();
    	for(;iter!=v.end();iter++)
    	    cout<<*iter<<" ";
    	cout<<endl;
    }
    int main(){
        vector<int> v; //现在容器中有0个元素
        int values[] = {1,3,5,7};
        v.insert(v.end(), values+1, values+3);//现在容器中有2个元素分别为:3,5
    	print(v);
        v.push_back(9); //现在容器中有3个元素分别为:3,5,9
    	print(v);
        v.erase(v.begin()+1);//现在容器中有2个元素分别为:3,9
    	print(v);
        v.insert(v.begin()+1, 4);//现在容器中有3个元素分别为:3,4,9
    	print(v);
        v.insert(v.end()-1, 4, 6);//现在容器中有7个元素分别为:3,4,6,6,6,6,9
    	print(v);
        v.erase(v.begin()+1, v.begin()+3); //现在容器中有5个元素分别为:3,6,6,6,9
    	print(v);
        v.pop_back(); //现在容器中有4个元素分别为:3,6,6,6
    	print(v);
        v.clear();//现在容器中有0个元素
    	print(v);
        if (true == v.empty()) //如果容器为空则输出"null"
        {
          std::cout<<"null"<<std::endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    vector的内存管理与效率

    对于vector容器来说,如果有大量的数据需要进行push_back,应当使用reserve()函数提前设定其容量大小,否则会出现许多次容量扩充导致效率低下。

    使用交换技巧来修整vector过剩空间/内存

    有一种办法来把它从曾经最大的容量减少到它现在需要的容量

    即vector(ivec).swap(ivec)。

    .前面的表达式表示建立一个临时vector,它是ivec的一份拷贝。

    但是vector的拷贝构造函数只分配拷贝的元素需要的内容,所以这个临时vector没有多余的容量。

    然后临时vector和ivec交换数据完成,现在临时变量持有了曾经在ivec中没用到的过剩容量。

    然后这个语句结尾处,临时vector被销毁,以释放以前ivec使用的内存,收缩到合适的大小。

    用swap方法强行释放vector所占内存

    vector<int>().swap(v);
    //或者
    v.swap(vector<int>());
    //或者
    
    • 1
    • 2
    • 3
    • 4

    {}包括的变量,会在退出{}后析构掉。

    vector增加容量是2的幂次方

    vector类的简单实现

    #include
    #include
    #include 
    using namespace std;
    template<typename T>
    class myVector
    {
    private:
    	/*walk length*/ 
    	/*myVector each time increase space length*/ 
    	#define WALK_LENGTH 64;
    
    public:
    	/*default constructor*/ 
    	myVector():array(0),theSize(0),theCapacity(0){	}
    	myVector(const T& t,unsigned int n):array(0),theSize(0),theCapacity(0){
    		while(n--){
    			push_back(t);
    		}
    	}
    
    	/*copy constructor*/ 
    	myVector(const myVector<T>& other):array(0),theSize(0),theCapacity(0){
    		*this = other;
    	}
    
    	/*= operator*/ 
    	myVector<T>& operator =(myVector<T>& other){
    		if(this == &other)
    			return *this;
    		clear();
    		theSize = other.size();
    		theCapacity = other.capacity();
    		array = new T[theCapacity];
    		for(unsigned int i = 0 ;i<theSize;++i)
    		{
    			array[i] = other[i];
    		}
    		return *this;
    	}
    
    	/*destructor*/ 
    	~myVector(){
    		clear();
    	}
    
    	/*the pos must be less than myVector.size();*/ 
    	T& operator[](unsigned int pos){
    		assert(pos<theSize);
    		return array[pos];
    	}
    
    	/*element theSize*/ 
    	unsigned int size(){
    		return theSize;
    	}
    
    	/*alloc theSize*/ 
    	unsigned int capacity(){
    		return theCapacity;
    	}
    	
    	/*is  empty*/ 
    	bool empty(){
    		return theSize == 0;
    	}
    
    	/*clear myVector*/ 
    	void clear(){
    		deallocator(array);
    		array = 0;
    		theSize = 0;
    		theCapacity = 0;
    	}
    
    	/*adds an element in the back of myVector*/  
    	void push_back(const T& t){
    		insert_after(theSize-1,t);
    	}
    
    	/*adds an element int the front of myVector*/ 
    	void push_front(const T& t){
    		insert_before(0,t);
    	}
    
    	/*inserts an element after the pos*/ 
    	/*the pos must be in [0,theSize);*/ 
    	void insert_after(int pos,const T& t){
    		insert_before(pos+1,t);
    	}
    
    	/*inserts an element before the pos*/ 
    	/*the pos must be less than the myVector.size()*/ 
    	void insert_before(int pos,const T& t){
    		if(theSize==theCapacity){
    			T* oldArray = array;
    			theCapacity += WALK_LENGTH; 
    			array = allocator(theCapacity);
    			/*memcpy(array,oldArray,theSize*sizeof(T)):*/ 
    			for(unsigned int i = 0 ;i<theSize;++i){
    				array[i] = oldArray[i];
    			}
    			deallocator(oldArray);
    		}
    
    		for(int i = (int)theSize++;i>pos;--i){
    			array[i] = array[i-1];
    		}
    		array[pos] = t;
    	}
    
    	/*erases an element in the pos;*/ 
    	/*pos must be in [0,theSize);*/ 
    	void erase(unsigned int pos){
    		if(pos<theSize){
    			--theSize;
    			for(unsigned int i = pos;i<theSize;++i){
    				array[i] = array[i+1];
    			}
    		}
    	}
    
    private:
    	T*  allocator(unsigned int size){
    		return new T[size];
    	}
    
    	void deallocator(T* arr){
    		if(arr)
    			delete[] arr;
    	}
    private:
    	T*				array;
    	unsigned int	theSize;
    	unsigned int	theCapacity;
    };
    
    void printfVector(myVector<int>& vector1){
    	for(unsigned int i = 0 ; i < vector1.size();++i){
    		cout<<vector1[i]<<",";
    	}
    	cout<<"alloc size = "<<vector1.capacity()<<",size = "<<vector1.size()<<endl;
    }
    
    int main(){
    	myVector<int> myVector1;
    	myVector<int> myVector2(0,10);
    	myVector2.push_front(1);
    	myVector2.erase(11);
    	printfVector(myVector2);
    	myVector1.push_back(2);
    	myVector1.push_front(1);
    	printfVector(myVector1);
    	myVector1.insert_after(1,3);
    	printfVector(myVector1);
    
    	myVector2 = myVector1;
    	myVector2.insert_before(0,0);
    	myVector2.insert_before(1,-1);
    	printfVector(myVector2);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162

    Map

    map内部数据的组织是一棵红黑树,所有数据都是有序的。

    对于key的类型,唯一的约束就是必须支持<操作符。尤其是自定义结构体时要注意重载<操作符

    比如

    typedef struct tagStudentInfo  
    {  
        int iID;  
        string  strName;  
    	bool operator < (tagStudentInfo const& r) const {  
            //这个函数指定排序策略,按iID排序,如果iID相等的话,按strName排序  
            if(iID < r.iID)  return true;  
            if(iID == r.iID) return strName.compare(r.strName) < 0;  
            return false;
        }  
    }StudentInfo;//学生信息 
    
    int main(){
    	/*用学生信息映射分数*/  
        map<StudentInfo, int>mapStudent; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    map的插入

    三种方式

    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(map<int, string>::value_type (1,"student_one"));
    mapStudent[1] =  "student_one";
    
    • 1
    • 2
    • 3
    • 4

    用inser函数插入数据,在数据的插入上涉及集合的唯一性,但使用数组方式就可以覆盖以前该关键字对应的值。

    判断Insert是否插入成功

    pair<map<int, string>::iterator, bool> insert_pair;
         insert_pair = mapStudent.insert(pair<int,string>(1,"student_one"));
        if(insert_pair.second == true){
            cout<<"Insert Successfully"<<endl;
        }
        else{
            cout<<"Insert Failure"<<endl;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    map遍历

    三种方式

    map<int, string>::iterator iter;
        for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++){
            cout<<iter->first<<" "<<iter->second<<endl;
        }
    
    • 1
    • 2
    • 3
    • 4
    map<int, string>::reverse_iterator   iter;
         for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++){
              cout<<iter->first<<" "<<iter->second<<endl;
         }
    
    • 1
    • 2
    • 3
    • 4
    int iSize = mapStudent.size();
        for(int i = 1; i <= iSize; i++){ 
            cout<<i<<" "<<mapStudent[i]<<endl; 
        } 
    
    • 1
    • 2
    • 3
    • 4

    数组访问vector时,下标是从0-size-1。而map是从1-size。

    map的查找

    用find

    map<int, string>::iterator iter=mapStudent.find(1); 
         if(iter != mapStudent.end()){
              cout<<"Found, the value is "<<iter->second<<endl;
         }else{
              cout<<"Do not found"<<endl; 
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    用count函数

    map的删除

    #include 
    #include 
    #include 
    using namespace std;
    int main(){
        map<int, string> mapStudent;
    	mapStudent[1]="student_one";
    	mapStudent[2]="student_two";
    	mapStudent[3]="student_three";
    	mapStudent[4]="student_four";	
        map<int, string>::iterator iter=mapStudent.begin();
        for(;iter!=mapStudent.end();){
    	    if((*iter).second=="student_one"){
    	        mapStudent.erase(iter++);
    	    }
    	    else{
    	        ++iter;
    	    }
    	}	
        for(iter=mapStudent.begin();iter!=mapStudent.end();iter++){
    	    cout<<iter->first<<" "<<iter->second<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    erase(iter++),不是erase(iter),然后iter++。

    因为iter指针被erase之后就失效了,不能再++了。

    它是先让iter++,然后返回原来的iter去erase。这样就没问题。

    map的排序

    默认key从小到大排序。

    map定义

    template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
    	    typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
        class map
    
    • 1
    • 2
    • 3

    第三个参数

    typename _ Compare = std::less<_Key>

    默认值是less<_Key>,它是STL里面的一个函数对象。

    它的实现就是对()操作符进行了重载。

    template<typename _Tp>
        struct less : public binary_function<_Tp, _Tp, bool>
        {
          _GLIBCXX14_CONSTEXPR
          bool
          operator()(const _Tp& __x, const _Tp& __y) const
          { return __x < __y; }
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    stl还提供了greater

    如果要让map中的元素按照key从大到小排序

    map<string, int, greater<string> > mapStudent;
    
    • 1

    如果要按自己的逻辑来比较,比如按照学生姓名的长短排序进行存储。这样做

    #include 
    #include 
    #include 
    using namespace std;
    struct CmpByKeyLength {  
      bool operator()(const string& k1, const string& k2) {  
        return k1.length() < k2.length();  
      }  
    };  
    int main(){
        map<string, int, CmpByKeyLength > mapStudent;
    	mapStudent["LiMin"]=90;
    	mapStudent["ZiLinMi"]=72;
    	mapStudent["BoB"]=79;
        map<string, int>::iterator iter=mapStudent.begin();
        for(iter=mapStudent.begin();iter!=mapStudent.end();iter++){
    	    cout<<iter->first<<" "<<iter->second<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    map按value排序(106-109)

    sort只针对线性,map不是线性。

    要实现排序,元素必须实现了<操作。

    P107 ==问题。

    Set

    stl里的list封装了链表。

    set中每个元素的值都唯一,而且会根据元素的值自动排序。

    stl的关联容器set,multiset,map,multimap内部采用的都是红黑树。

    不要使用过期的iterator(多线程情况下比如vector的iterator可能失效,扩容情况下)

    创建

    /*创建set对象,共5种方式,提示如果比较函数对象及内存分配器未出现,即表示采用的是系统默认方式*/
    
    	/*创建空的set对象,元素类型为int,*/
    	set<int> s1;
    
    	/*创建空的set对象,元素类型char*,比较函数对象(即排序准则)为自定义strLess*/
    	set<const char*, strLess> s2( strLess); 
    
    	/*利用set对象s1,拷贝生成set对象s2*/
    	set<int> s3(s1); 
    
    	/*用迭代区间[&first, &last)所指的元素,创建一个set对象*/
    	int iArray[] = {13, 32, 19};
    	set<int> s4(iArray, iArray + 3);
    
    	/*用迭代区间[&first, &last)所指的元素,及比较函数对象strLess,创建一个set对象*/
    	const char* szArray[] = {"hello", "dog", "bird" };
    	set<const char*, strLess> s5(szArray, szArray + 3, strLess() );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    	/*元素插入:
    	1,插入value,返回pair配对对象,可以根据.second判断是否插入成功。(提示:value不能与set容器内元素重复)
        pair insert(value)
        2,在pos位置之前插入value,返回新元素位置,但不一定能插入成功
        iterator insert(&pos, value)
        3,将迭代区间[&first, &last)内所有的元素,插入到set容器
    	void insert[&first, &last);
    	*/
    	cout<<"s1.insert() : "<<endl;
    	for (int i = 0; i <5 ; i++)
            s1.insert(i*10);
        printSet(s1);
    	
    	cout<<"s1.insert(20).second = "<<endl;
    	if (s1.insert(20).second)
            cout<<"Insert OK!"<<endl;
    	else
            cout<<"Insert Failed!"<<endl;
    
    	cout<<"s1.insert(50).second = "<<endl;
    	if (s1.insert(50).second){
    		cout<<"Insert OK!"<<endl;
    		printSet(s1);
    	}else
    		cout<<"Insert Failed!"<<endl;
    
    	cout<<"pair::iterator, bool> p;\np = s1.insert(60);\nif (p.second):"<<endl;
    
    	pair<set<int>::iterator, bool> p;
    	p = s1.insert(60);
    	if (p.second){
    		cout<<"Insert OK!"<<endl; 
    		printSet(s1);
    	}
    	else
    		cout<<"Insert Failed!"<<endl;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    /*元素删除
        1,size_type erase(value) 移除set容器内元素值为value的所有元素,返回移除的元素个数
        2,void erase(&pos) 移除pos位置上的元素,无返回值
        3,void erase(&first, &last) 移除迭代区间[&first, &last)内的元素,无返回值
        4,void clear(), 移除set容器内所有元素*/
    	cout<<"\ns1.erase(70) = "<<endl;
    	s1.erase(70);
    
    	printSet(s1);
    
    	cout<<"s1.erase(60) = "<<endl;
    	s1.erase(60);
    
    	printSet(s1);
    
        cout<<"set::iterator iter = s1.begin();\ns1.erase(iter) = "<<endl;
        set<int>::iterator iter = s1.begin();
        s1.erase(iter);
        printSet(s1);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    /*元素查找
    	count(value)返回set对象内元素值为value的元素个数
    	iterator find(value)返回value所在位置,找不到value将返回end()
    	lower_bound(value),upper_bound(value), equal_range(value)*/
    	cout<<"\ns1.count(10) = "<<s1.count(10)<<", s1.count(80) = "<<s1.count(80)<<endl;
    	cout<<"s1.find(10) : ";
    	if (s1.find(10) != s1.end()) 
    		cout<<"OK!"<<endl;
    	else
    		cout<<"not found!"<<endl;
    	
    	cout<<"s1.find(80) : ";
    	if (s1.find(80) != s1.end()) 
    		cout<<"OK!"<<endl;
    	else
    		cout<<"not found!"<<endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    用Python如何进行Web开发
    pyarrow 实现hdfs和本地文件传输
    力扣刷题 day47:10-17
    Pandas处理异常值的两种方法
    百度地图1
    Spring Boot创建和使用(重要)
    【集合】单列集合
    详解单例模式
    澳大利亚昆士兰大学博士后职位—生物活性肽
    SpringBoot+Vue项目篮球竞赛预约平台
  • 原文地址:https://blog.csdn.net/weixin_45593271/article/details/133717425