[C++] Detailed explanation of STL

Table of contents

One: Generic programming          

Two: What is STL

Three: STL development

Four: STL components

Five: container

Six: Type members

Seven: Adapter

Eight: Iterator

Nine: Algorithms

Ten: Sequential Containers

Eleven: vector vector

Twelve: double-ended queue queue

Thirteen: list list

Fourteen: Associative Containers

Fifteen: map

Sixteen: multimap

Seventeen: set

Eighteen: multiset

Nineteen: Iterators

Twenty: Function Object

Twenty-one: Function objects that have been integrated

Twenty-two: Custom function objects

Twenty-three: Algorithms in the standard C++ library

Twenty-four: Header file of STL algorithm

Twenty-five: standard functions

Twenty-six: Examples of generic algorithms

Twenty-seven: Custom functions as algorithm parameters                


One: Generic programming          

1. Make the program as general as possible  

2. Abstract the algorithm from a specific data structure and become a general

3. C++ templates lay a key foundation for generic programming

Two: What is STL

STL (Standard Template Library), the standard template library, is an efficient C++ library

    It is contained in the C++ Standard Library (C++ Standard Library), which is the latest and revolutionary part of the ANSI/ISO C++ standard

    Contains many basic data structures and basic algorithms commonly used in the field of computer science. Provides an extensible application framework for the majority of C++ programmers, which highly reflects the reusability of the software

From the logical level, the idea of ​​generic programming is embodied in STL (generic programming)

     In this idea, most of the basic algorithms are abstracted, generalized, independent of the corresponding data structures, and used to deal with various situations in the same or similar way

From the implementation level, the entire STL is implemented in a type parameterized way

    Based on template

Three: STL development

1971 : David R. Musser started to advocate the concept of Generic Programming

1979 : Alexander Stepanov creates STL

1987 : Alex and Musser developed an Ada library

???? : Alex has experimented with a large number of architectural and algorithmic forms in C and C++ in AT&T and HP laboratories.

1992 : Meng Lee joined as another major contributor

1993/11 : Alex presented at the ANSI/ISO C++ conference

Summer 1994: STL is included in the C++ standard

Four: STL components

Container (container) various basic data structures

Adapter (adapter) A component that can change the interface of containers or function object

Algorithm (algorithm) various basic algorithms such as sort, search...etc.

Iterator (iterator)* connect containers and algorithms

Function object (function object) *

Allocator*

Five: container

A container class is an object that holds, contains, a set of elements or collections of elements

Heterogeneous container classes vs homogeneous container classes

Sequential and associative containers

Seven basic containers: vector, deque, list, set, multiset, map, and multimap

The members of a standard container mostly share the same name

Six: Type members

Seven: Adapter

Adapter is an interface class

    Provide new interfaces for existing classes

    The purpose is to simplify, constrain, make it safe, hide or change the set of services provided by the modified class

Three types of adapters:

    Container adapter: used to expand 7 basic containers, which are combined with sequence containers to form stack, queue and priority queue containers

    iterator adapter

    function object adapter 

Eight: Iterator

Iterators are object-oriented versions of pointers that provide access to each element in a container, sequence

Nine: Algorithms

The C++ Standard Template Library includes more than 70 algorithms

    These include search algorithms, sorting algorithms, elimination algorithms, counting algorithms, comparison algorithms, transformation algorithms, replacement algorithms, and container management, etc.

One of the most important properties of these algorithms is that they are uniform and can be widely used with different objects and built-in data types

Ten: Sequential Containers

interface for sequence containers

insert method

push_front(), push_back(), insert(), operator "="

delete method

pop() ,erase(),clear()

iterative access method

use iterator

Other sequential container access methods (without modifying access methods)

front(), back(), subscript[] operators

Eleven: vector vector

1. The vector is a sequential container, which is used to accommodate a linear sequence of indefinite length (ie, a linear group), and provides fast random access to the sequence (also known as direct access)

2. The data structure is very similar to an array, so compared with other containers, vector can access a single element very conveniently and efficiently, and supports random access iterators

3. The vector is a dynamic structure, its size is not fixed, it can be increased or decreased when the program is running

    Unlike an array, when the memory of a vector is exhausted , the vector automatically allocates a larger continuous memory area , copies the original elements to the new memory area , and releases the old memory area ; this is the advantage of the vector class

Header file: #include <vector>

Vector basic operations

(1) Header file

#include<vector>

(2) Create a vector object

vector<int> vec;

(3) Insert numbers at the end

vec.push_back(a);

(4) Use subscripts to access elements

cout<<vec[0]<<endl; remember that the subscript starts from 0

(5) Use iterators to access elements

vector<int>::iterator it;

for(it=vec.begin();it!=vec.end();it++)

cout<<*it<<endl;

(6) Insert elements

vec.insert(vec.begin()+i,a); Insert a in front of the i+1th element;

(7) Delete elements   

vec.erase(vec.begin()+2); delete the third element

vec.erase(vec.begin()+i, vec.end()+j); delete interval [i, j-1]; interval starts from 0

(8) Vector size

vec.size();

vec.resize; change size

(9) Empty

vec.clear();

vector, the usage example is as follows

#include <iostream>
#include <iomanip>
#include <vector>	//包含向量容器头文件
using namespace std ;
void main(){    
	vector<int>  A(10);	  //创建vector对象
	int n;	
	int primecount = 0, i, j;
	cout<<"Enter a value>=2 as upper limit: ";
	cin >> n;
	A[primecount++] = 2;//下标法访问元素
	for(i = 3; i < n; i++){ 
		if (primecount == A.size())	
			A.resize(primecount + 10); //改变容器大小
        if (i % 2 == 0)
			continue;
		j = 3;
 		while (j <= i/2 && i % j != 0)
			j += 2;        
		if (j > i/2) A[primecount++] = i;
	}
	for (i = 0; i<primecount; i++){//输出质数
		cout<<setw(5)<<A[i]; 
		if ((i+1) % 10 == 0) //每输出10个数换行一次
			cout << endl;
	} 
	cout<<endl;
}

Twelve: double-ended queue queue

A double-ended queue is a queue with relaxed access rights

Elements can enter and exit the queue from both ends of the queue, and also support direct access through the subscript operator "[]"

Contrast with vectors:

    Functionally: not much different from vectors,

    In terms of performance: the insertion and deletion operations at the start of the double-ended queue are fast

Header file: #include <deque>

Thirteen: list list

The linked list is mainly used to store the doubly linked list, which can be traversed from any end. Linked lists also provide a splice operation, which inserts elements from one sequence into another

Compared:

Element insertion and deletion operations are particularly efficient for lists

Compared with vector and deque, the inefficiency of subscript access operations on elements cannot be tolerated, so list does not provide such operations

Header files: #include <list>

list, the usage example is as follows

#include <iostream>
#include <list>
using namespace std ;
int main(){
	list<int> Link;	//构造一个列表用于存放整数链表
	int i, key, item;    
	for(i=0;i < 10;i++)// 输入10个整数依次向表头插入{
		cin>>item;
		Link.push_front(item);
	}
	cout<<“List: ”; // 输出链表
	list<int>::iterator p=Link.begin();
    while(p!=Link.end()){ //输出各节点数据,直到链表尾
		cout <<*p << "  ";
		p++;  //使P指向下一个节点
	}
	cout << endl;
	cout << "请输入一个需要删除的整数: ";
	cin >> key;
	Link.remove(key);   
	cout << "List: "; // 输出链表
	p=Link.begin();	// 使P重新指向表头
	while(p!=Link.end()){ 
		cout <<*p << "  ";
		p++; // 使P指向下一个节点
	}
	cout << endl;
}

Fourteen: Associative Containers

Retrieve data items as fast as possible by indexing items stored in the data item

The STL standard library only contains ordered associative containers set, multiset, map, and multimap

     set, multiset: data items are index items; multiset allows duplicate index items

      map, multimap: A data item is a pair of data consisting of an index item and some other type of data; multimap allows duplicate index items

Fifteen: map

1. Adding and deleting nodes has little effect on the iterator. For iterators, real values ​​can be modified, but keys cannot be modified

2. Automatically establish Key-value correspondence. key and value can be any type you need

3. Quickly find records according to the key value. The complexity of searching is basically Log(N). If there are 1000 records, you can search up to 10 times, and if you have 1,000,000 records, you can search up to 20 times.

constructor of map

1. Use map to include the header file where the map class is located
     #include <map>

2. The map object is a template class, which requires two template parameters: keyword and storage object:
      map<int, string> personnel;//Use int as index to store string object

member function of map

1. The map class has overloaded the [] operator

2. When inserting 2, first look for the item whose primary key is 2 in the enumMap, if it is not found, then insert a new object into the enumMap, the key is 2, and the value is an empty string. After the insertion is completed, assign the string to " Two";

3. However, this method assigns each value to the default value, and then assigns it to the displayed value. If the element is a class object, the overhead is relatively large. The overhead can be avoided with the following insert()

4. The subscript operator gives the easiest way to get a value:

     CString tmp = enumMap[2];

     However, it is only true when there is an instance of this key in the map, otherwise an instance will be automatically inserted, and the value will be the initialization value

5. We can use the Find() and Count() methods to find out if a key exists

6. Use the find() method to find whether a certain keyword entry is contained in the map, and the parameter passed in is the key to be searched

7. The iterator data type obtained by the method of the map object is a std::pair object, including two data iterator->first and iterator->second, representing keywords and stored data respectively

remove an element from the map

1. To remove an entry in a map use erase()

2. The member method is defined as follows

iterator erase(iterator it);              //通过一个条目对象删除
iterator erase(iterator first, iterator last);//删除一个范围

size_type erase(const Key& key);   //通过关键字删除

For example:

enumMap.erase(1);//删掉关键字“1”对应的条目
enumMap.erase(enumMap.begin());//删掉第一个条目
enumMap.erase(enumMap.begin(), enumMap.begin() + 2);//删掉起始的两个条目

3. clear() is equivalent to

 enumMap.erase(enumMap.begin(), enumMap.end()); 

map, the usage example is as follows

#include <map>
#include <iostream>
#include <string>
using namespace std;
void main(){
	map< string, string > trans_map;
	typedef map< string, string >::value_type valType;
	trans_map.insert( valType( "001", "grateful" ));
	trans_map.insert( valType( "002", "them" ));
	trans_map.insert( valType( "003", "because" ));
	trans_map.insert( valType( "004", "no" ));
	trans_map.insert( valType( "005", "says" ));
	trans_map.insert( valType( "006", "thanks" ));
	trans_map.insert( valType( "007", "was" ));
    trans_map.insert( valType( "008", "suppose" ));	
	map< string,string >::iterator it;
	cout << "Here is our transformation map: \n\n";
	for(it=trans_map.begin();it!=trans_map.end();++it)
		cout<<"key: "<<(*it).first<<"\t"<<"value: " <<(*it).second<<"\n";
	cout<<"Find Key:005"<<endl;
	it=trans_map.find("105");
	if (it==trans_map.end()){
		cout<<"not found"<<endl;
	}
	else{
		cout<<"key: "<<(*it).first <<"\t"<<"value: " <<(*it).second<<"\n";
	}
}

Sixteen: multimap

multimap is similar to map except that the key of the element pair is not unique

Header file: #include <map>

Seventeen: set

A set can be thought of as a map with only keys and no associated element values, so the user interface of the set has also changed slightly: there are no in the member types:

     typedef Key value_type;

     typedef Cmp value_compare

     Subscript access operation with no elements in the operation

Header files: #include <set>

Eighteen: multiset

multiset is similar to set except the key is not unique

Header files: #include <set>

Nineteen: Iterators

Iterators are object-oriented versions of pointers

     A pointer can point to an address in memory

     An iterator can point to a position in a container

Each container class template of STL defines a set of corresponding iterator classes. Using an iterator, the algorithm function can access the element at the specified position in the container without caring about the specific type of the element

iterator type

1. Input iterator

Can be used to read data from a sequence

2. output iterator

Allows writing data to a sequence

3. Forward iterator

It is both an input iterator and an output iterator, and can traverse the sequence in one direction

4. Bidirectional iterator

Similar to a forward iterator, but traverses data in both directions

5. Random access iterators

Also a bidirectional iterator, but able to jump between any two positions in the sequence

iterator type list

Iterator, example usage

#include <list>
#include <iostream>
using namespace std;
int main(){
	int i,key;
	list<int> intList;	
	list<int>::iterator it;
	cout<<"input 5 digit:";
	for(i=0;i<5;i++){
		cin>>key;
		intList.push_front(key);
	}	
    cout<<"data list:"<<endl; 	
	it=intList.end();
	while(1){
		cout.width(6);
		cout<<*(--it);
		if(it==intList.begin())
			break;
	}
	return 0;
}

Twenty: Function Object

1. An object that behaves like a function, it can have no parameters, or it can have several parameters, its function is to get a value, or change the state of the operation

2. Any ordinary function and any object of a class that overloads the call operator operator() satisfies the characteristics of a function object

3. Some standard function objects are also defined in STL. If divided by function, they can be divided into three categories: arithmetic operations, relational operations, and logic operations; in order to call these standard function objects, the header file <functional> needs to be included

Twenty-one: Function objects that have been integrated

Twenty-two: Custom function objects

#include <iostream>
using namespace std;
class CFunObj{
public:
	void operator()(){
		cout<<"hello,function object!"<<endl;
	}
	int operator()(int i){
		cout<<"hello, function object other!"<<endl;
		return i+1;
	}
private:
	int dat;
};

void main(){
	CFunObj fo;
	fo();
	cout<<fo(1)<<endl;
	//CFunObj()();
}	

Twenty-three: Algorithms in the standard C++ library

1. The algorithm itself is a function template

2. Non-mutating algorithms

       Algorithms that do not directly modify the contents of the container being manipulated

3. Mutating algorithms

       can modify the elements of the container they operate on

4. The algorithm part is mainly composed of header files <algorithm>, <numeric> and <functional>

Twenty-four: Header file of STL algorithm

<algorithm> is the largest of all STL header files. It is composed of a large number of template functions. It can be considered that each function is largely independent, and the commonly used functions involve comparison and exchange. , find, traverse operations, copy, modify, remove, reverse, sort, merge, etc.

<numeric> is small in size and only includes a few template functions for simple mathematical operations on sequences, including some operations of addition and multiplication on sequences

Some template classes are defined in <functional> to declare function objects

Twenty-five: standard functions

Twenty-six: Examples of generic algorithms

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <numeric>
#include <functional>
using namespace std;
int main(){
	int ia[] = { 1, 2, 3, 4, 5, 7, 9, 11 };
	vector<int> iv(ia, ia+8);
	//累加,52
	cout<<accumulate(iv.begin(),iv.end(),10)<<endl; //相邻差值
	adjacent_difference(iv.begin(),iv.end(),iv.begin());
	//复制到ostream_iterator 去, 每列印一个元素, 即加上一个空格
    	copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”));
	// 1 1 1 1 1 2 2 2 	
	//计算元素值为2 的个数
	cout << count(iv.begin(), iv.end(), 2) << endl; // 3
	//计算奇数元素的个数
	cout << count_if(iv.begin(), iv.end(),
	bind2nd(modulus<int>(),2)) << endl; // 5
	//从头开始填入新值7, 填3 次
	fill_n(iv.begin(), 3, 7);
	copy(iv.begin(), iv.end(), ostream_iterator<int>(cout,“ ”));
	// 7 7 7 1 1 2 2 2
	//内积, 7*7 + 7*7 + 7*7 + 1*1 + 1*1 + 2*2 + 2*2 + 2*2
	cout << inner_product(iv.begin(), iv.end(), iv.begin(),0) << endl; 
	//161
    	//排序
	sort(iv.begin(), iv.end());
	copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”));
	// 1 1 2 2 2 7 7 7
	//顛倒元素次序
	reverse(iv.begin(), iv.end());
	copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”));
	// 7 7 7 2 2 2 1 1
	//旋转, 交换[first, middle)和[middle, last)
	rotate(iv.begin(), iv.begin()+3, iv.begin()+6);
	copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”));
	// 2 2 2 7 7 7 1 1
}

Twenty-seven: Custom functions as algorithm parameters                

#ifndef CMYCLASS_H
#define CMYCLASS_H
#include <string.h>
class CMyClass{
public:
	CMyClass();
	CMyClass(string name,int age);
	friend bool Less(const CMyClass &num,const CMyClass &myclass);
	bool operator==(const CMyClass &myclass);
	string &GetName();
	int GetAge();
private:
	string m_name;
	int m_age;};
#endif
CMyClass::CMyClass(){
	m_name="";
	m_age=12;
}
CMyClass::CMyClass(string name,int age)
{	m_name=name;
	m_age=age;
}
bool CMyClass::operator==(const CMyClass &myclass){
	return m_name==myclass.m_name;
}
string & CMyClass::GetName(){
	return m_name;}
int CMyClass::GetAge(){
	return m_age;}
#include "MyClass.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
#include <numeric>
using namespace std;
bool Less(const CMyClass &num,const CMyClass &myclass){
	return num.m_name<myclass.m_name;
}
void PrintMyClass(CMyClass &myclass){
	cout<<"name:"<<myclass.GetName()<<"\t age:"<<myclass.GetAge()<<endl;
}
bool SearchByName(CMyClass &myclass){
	return myclass.GetName()=="AAAAZ";
}
void  main(){
	CMyClass myclass;
	vector<CMyClass> vec;
	vec.push_back(CMyClass("AAAA",12));
	vec.push_back(CMyClass("DFKASDF",12));
	vec.push_back(CMyClass("ASDFSAFA",12));
	vec.push_back(CMyClass("Z",12));
	vec.push_back(CMyClass("AAAAZ",12));
	vec.push_back(CMyClass("DFKSADFZ",12));
	sort(vec.begin(),vec.end(),Less);
//	for (vector<CMyClass>::iterator it=vec.begin();it!=vec.end();it++){
//		cout<<it->GetName()<<endl;}
	for_each(vec.begin(),vec.end(),PrintMyClass);
	vector<CMyClass>::iterator r=find_if(vec.begin(),vec.end(),SearchByName);
	cout<<(*r).GetName()<<endl;
}

Guess you like

Origin blog.csdn.net/m0_56051805/article/details/127131897