C + + improve programming

C + + improve programming

Mainly for C + + generic programming and STL technology

Template 1

1. Concept

Template is to establish a general mold, which greatly improves the reusability of code

Template features

  • The template cannot be used directly. It is just a framework
  • The universality of templates is not everything

2. Function template

  • Another programming idea of C + + is generic programming, which mainly uses template technology
  • C + + provides two template mechanisms: function template and class template

2.1 function template syntax

Function template function: establish a general function whose function return value type and formal parameter type can not be specifically determined, but can be represented by a virtual type

grammar

template<typename T>
Function declaration or definition

parameter

  • Template: declares the creation of a template
  • typename: indicates that the symbol behind it is a data type, which can be replaced by class
  • T: A generic data type whose name can be replaced, usually in uppercase letters
// Two integer exchange functions
void swap(int& a, int& b)
{
	int temp = a;
	a = b; 
	b = temp;
}
// Swap floating point functions
void swap(double& a, double& b)
{
	double temp = a;
	a = b;
	b = temp;
}
// Function template
template <typename T>  // Declare the template and tell the compiler that the following code is followed by T. don't report errors. T is a general data type
void m_swap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}
void test()
{
	int a = 1;
	int b = 3;
	double a1 = 4;
	double b1 = 5;
	/* swap(a, b);
	cout << a << b << endl;
	swap(a1, b1);
	cout << a1 << b1 << endl; */
	// Using function templates
	// 1. Automatic derivation
	m_swap(a, b);
	cout << a << b << endl;
	// 2. Displays the specified type
	m_swap<int>(a, b);
	cout << a << b << endl;
}

Templates can parameterize data types

How to use the template

  • Automatic derivation
  • Displays the specified type

2.2 precautions

matters needing attention

  • Automatically deduce the data type. You must deduce the consistent data type T before you can use it
  • The template can be used only after the data type of T is determined

2.3 differences between ordinary functions and function templates

  • Automatic type conversion (implicit type replacement) can occur when calling ordinary functions
  • When a function template is called, if automatic type derivation is used, implicit type replacement will not occur
  • If you use the method of displaying the specified type, implicit type conversion can occur

2.4 call rules for ordinary functions and function templates

The calling rules are as follows

  1. If both function templates and ordinary functions can be implemented, ordinary functions will be called first

  2. The function template can be forcibly called through the empty template parameter list

    void myPrint(int a, int b)
    {
    	cout << a << b << endl;
    	cout << "Ordinary function" << endl;
    }
    template<typename T>
    void myPrint(T a, T b)
    {
    	cout << a << b << endl;
    	cout << "template function" << endl;
    }
    
    void test()
    {
    	int a = 10;
    	int b = 20;
    	myPrint<>(a, b);  // Calling template function with empty template parameter list
    }
    
  3. Function templates can also be overloaded

  4. If the function template can produce a better matching pattern, call the function template first

    void myPrint(int a, int b)
    {
    	cout << a << b << endl;
    	cout << "Ordinary function" << endl;
    }
    template<typename T>
    void myPrint(T a, T b)
    {
    	cout << a << b << endl;
    	cout << "template function" << endl;
    }
    
    void test()
    {
    	char a = 'a';
    	char b = 'b';
    	myPrint(a, b);  // Function templates can produce better matches 
    }
    

    Since the function template is provided, it is better not to provide ordinary functions, otherwise ambiguity is likely to occur

2.5 limitations of formwork

  • The versatility of templates is not everything

If a tuple and custom data type are passed in, it cannot be implemented

Therefore, in order to solve this problem, C + + provides template overloading, which can provide concrete templates for these specific types

// Template overload
// Compare whether the two data are equal
class Person
{
public:
	Person(string name, int age)
	{
		m_Age = age;
		m_Name = name;
	}
	string m_Name;
	int m_Age;
};
template<class T>
bool myCompare(T& a, T& b)  // What if a custom data type is passed in
{
	if (a == b)
	{
		return true;
	}
	else
	{
		return false;
	}
}
// Use the version of materialized Person to realize the code, and materialization takes priority to call
// You can also use operator overloading
template<>bool myCompare(Person& p1, Person& p2)
{
	if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)
	{
		return true;
	}
	else
	{
		return false;
	}
}
void test()
{
	Person p1("Tom", 10);
	Person p2("Tom", 10);
	cout << myCompare(p1, p2) << endl;
}

Learning templates is not to write templates, but to use the templates provided by the system in STL

3. Class template

3.1 class template syntax

Class template function

  • Establish a general class. The data types of members in the class can be represented by a virtual type without specific formulation

grammar

template<typename T>
class

parameter

  • Template: declares the creation of a template
  • typename: indicates that the symbol behind it is a data type, which can be replaced by class
  • T: A generic data type whose name can be replaced, usually in uppercase letters
template<typename NameT, typename AgeT>
class Person
{
public:
	Person(NameT name, AgeT age)
	{
		m_Age = age;
		m_Name = name;
	}
	NameT m_Name;
	AgeT m_Age;
};
void test()
{
	Person<string, int>("Tom", 30);  // Call - there is only one way to call
}

3.2 difference between class template and function template

There are two main differences between class template and function template

  1. Class templates do not use automatic type derivation

  2. The default template class can have parameters in the template list

    template<typename NameT, typename AgeT = int>  // Default parameters
    class Person
    {
    public:
    	Person(NameT name, AgeT age)
    	{
    		m_Age = age;
    		m_Name = name;
    	}
    	NameT m_Name;
    	AgeT m_Age;
    };
    void test()
    {
    	Person<string>("Tom", 30);
    }
    

3.3 use timing

The creation time of member functions in class templates is different from that in ordinary classes

  • Member functions in ordinary classes can be created from the beginning
  • Member functions in class templates are created only when called
class Person1
{
public:
	void show()
	{
		cout << "Person1" << endl;
	}

};

template<typename T>
class Person
{
public:
    // If not called, it will not compile because the data type of T cannot be determined
	T p1;
	void func1()
	{
		p1.show();
	}
	
};
void test()
{
	Person<Person1> p;
	p.func1();
}

3.4 type template object function as parameter

Class template instance to pass parameters to the function

There are three ways of transmission

  • Specify the incoming data type: directly display the data type of the object

    • // Specify incoming type
      void printPerson1(Person<string, int> &p); 
      
  • Parameter templating: change the parameters in the object into templates for transfer

    • // Parameter Templating
      template<class T1, class T2>
      void printPerson2(Person<T1, T2>& p);
      
  • Whole class templating: pass this object type templating

    • // Whole class Templating
      template<class T>
      void printPerson3(T &p);
      
// Class template as function parameters
template<class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age)
	{
		m_Name = name;
		m_Age = age;
	}
	T1 m_Name;
	T2 m_Age;
	void showPerson()
	{
		cout << "name:" << m_Name << " age:" << m_Age << endl;
	}
};
// Specify incoming type
void printPerson1(Person<string, int> &p)  
{
	p.showPerson();
}
// Parameter Templating
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{
	p.showPerson();
	cout << "T1 The types of are:" << typeid(T1).name() << endl;
	cout << "T2 The types of are:" << typeid(T2).name() << endl;
}
// Whole class Templating
template<class T>
void printPerson3(T &p)
{
	p.showPerson();
}
void test()
{
	Person<string, int> p("Tom", 12);
	printPerson1(p);
	printPerson2(p);
	printPerson3(p);
}

How to view data types

typeid(T2).name()

Class 3.5 template and inheritance

When a class template encounters inheritance, you need to pay attention to the following points

  • When the parent class inherited by the subclass is a class template, the data type of T in the parent class shall be specified when the subclass is declared
  • If not specified, the compiler cannot allocate memory to subclasses
  • If you want to flexibly specify the type of T of the parent class, the child class also needs to be changed into a template
// Class template and inheritance
template<class T>
class Base
{
public:
	T m_M;
};
// When the parent class inherited by the subclass is a class template, the data type of T in the parent class shall be specified when the subclass is declared
class Son : public Base<string> {};
// If you want to flexibly use the T type in the parent class, the child class also needs to be changed into a class template
template<class T1, class T2>
class Son1 : public Base<T2> {};

3.6 implementation outside class of class template member function

Be able to master the out of class implementation of member functions in class templates

// Out of class implementation
template<class T1, class T2>
class Person
{
public:
	Person(T1 age, T2 name);
	void shouPerson();
	T1 m_Age;
	T2 m_Name;
};
template <class T1, class T2>
Person<T1, T2>::Person(T1 age, T2 name)
{
	this->m_Name = name;
	m_Age = age;
}
// To reflect the class function as a class template, add it without parameters
template <class T1, class T2>
void Person<T1, T2>::shouPerson()
{
	cout << "name:" << m_Name << " age:" << m_Age << endl;
}

Preparation of class 3.7 template documents

Master the problems and solutions arising from the preparation of class template member function sub files

problem

  • The creation time of the member function in the class template is in the calling stage, resulting in the file writing is not linked

solve

  1. Direct inclusion cpp source file
  2. Write the declaration and implementation to the same file and change the suffix to hpp, hpp is the agreed name, not mandatory

person. Code in HPP

#pragma once
#include <iostream>
using namespace std;


template<class T1, class T2>
class Person
{
public:
	Person(T1 age, T2 name);
	void shouPerson();
	T1 m_Age;
	T2 m_Name;
};
template <class T1, class T2>
Person<T1, T2>::Person(T1 age, T2 name)
{
	this->m_Name = name;
	m_Age = age;
}
template <class T1, class T2>
void Person<T1, T2>::shouPerson()
{
	cout << "name:" << m_Name << " age:" << m_Age << endl;
}

Program entry code

#include <iostream>
using namespace std;
#include <fstream>
// The first solution includes cpp source file
// #include"Person.cpp"

// The second solution will be h and The contents of cpp are written to In hpp file
#include "Person.hpp"

void test()
{
	Person<string, int> p("Tom", 132);
	p.shouPerson();
}
int main() {
	test();

	system("pause");
	return 0;
}

The second solution is to write the class template member functions together and change the suffix to hpp

Class 3.8 templates and friends

Master the in class and out of class implementation of class template and friend function

  • Implementation of global function in class: directly declare friends in class
  • Out of class implementation of global functions: the compiler needs to know the existence of global functions in advance
// Print global information through global function
 // Let the compiler know the existence of the Person class in advance
template<class T1, class T2>
class Person;

// If it is implemented outside the class, the compiler needs to know the existence of the function in advance
template<class T1, class T2>
void printPerson1(Person<T1, T2>& p);

template<class T1, class T2>
class Person
{
	// Global function, implemented in class
	friend void printPerson(Person<T1, T2>& p)
	{
		cout << "full name:" << p.m_Name << " Age:" << p.m_Age << endl;
 	}
	// Global function, out of class implementation
	friend void printPerson1<>(Person<T1, T2>& p);  // < > it is a function template declaration
public:
	Person(T1 name, T2 age)
	{
		m_Name = name;
		m_Age = age;
	}
private:
	T1 m_Name;
	T2 m_Age;
};
template<class T1, class T2>
void printPerson1(Person<T1, T2>& p)
{
	cout << "full name:" << p.m_Name << " Age:" << p.m_Age << endl;
	cout << "Out of class implementation" << endl;
}

It is recommended to implement the global function in class, which is simple to use and can be directly recognized by the compiler

3.9 array class encapsulation

Case description: implement a general array class. The requirements are as follows

  • Data of built-in data type and user-defined data type can be stored
  • Store the data in the array in the heap
  • The capacity of the array that can be passed in the constructor
  • Provide the corresponding copy constructor and opertator = to prevent shallow copy problems
  • The elements in the array can be accessed by subscript
  • You can get the current number of elements in the array and the number of arrays

myArray. Code in HPP

#pragma once
#include<iostream>
using namespace std;

template<class T1>  // Output function
void printArray();
template<class T1>
class MyArray
{
public:
	MyArray(int capacity);  // Parametric structure
	MyArray(const MyArray& arr);  // copy construction 
	MyArray& operator=(const MyArray& arr);  // Overload of assignment operators to prevent shallow copy problems
	void pushBack(const T1& val);  //  Inserting data by tail interpolation
	void delBack();  // Tail deletion method to delete data
	T1& operator[](int index);  // Overload [], so that the array can be accessed by index, and the value can be assigned at the same time
	int getCapacity();// Returns the capacity of the array
	int getSize();// Returns the size of the array
	~MyArray();  // Clear heap data
private:
	T1* pAddress;  // The pointer points to the real array opened to the heap
	int m_Capacity; // Array capacity
	int m_Size;  // Array size
};

template<class T1>
MyArray<T1>::MyArray(int capacity)
{
	this->m_Capacity = capacity;
	this->m_Size = 0;
	this->pAddress = new T1[this->m_Capacity];  // Open up array space
}
template<class T1>
MyArray<T1>::~MyArray()
{
	if (this->pAddress)
	{
		delete[] pAddress;
		pAddress = NULL;
	}
}
template<class T1>
MyArray<T1>::MyArray(const MyArray& arr)
{
	this->m_Capacity = arr.m_Capacity;
	this->m_Size = arr.m_Size;
	// This - > paddress = arr.paddress / / shallow copy
	this->pAddress = new T1[arr.m_Capacity];  // Deep copy
	// The data in arr is copied
	for (int i = 0; i < this->m_Size; i++)
	{
		this->pAddress[i] = arr.pAddress[i];
	}
}
template<class T1>
MyArray<T1>& MyArray<T1>::operator=(const MyArray& arr)
{
	// First judge whether there is data in the original heap area. If so, release it first
	if (this->pAddress)
	{
		delete[] pAddress;
		this->pAddress = NULL;
		this->m_Size = 0;
		this->m_Capacity = 0;
	}
	// Deep copy
	this->m_Capacity = arr.m_Capacity;
	this->m_Size = arr.m_Size;
	this->pAddress = new T1[this->m_Capacity];
	for (int i = 0; i < this->m_Size; i++)
	{
		this->pAddress[i] = arr.pAddress[i];
	}
	return *this;
}
template<class T1>
void MyArray<T1>::pushBack(const T1& val)
{
	// Judge whether the capacity is equal to the size
	if (this->m_Capacity == this->m_Size)
	{
		cout << "Array capacity reached, unable to insert" << endl;
		return;
	}
	this->pAddress[this->m_Size] = val;
	this->m_Size++;  // Update array size
}
template<class T1>
void MyArray<T1>::delBack()
{
	// Let users not access the last element, that is, tail deletion, logical deletion
	if (!this->m_Size)
	{
		cout << "There are no elements in the array" << endl;
		return;
	}
	this->m_Size--;  // Cannot access that element
}
template<class T1>
T1& MyArray<T1>::operator[](int index)
{
	return this->pAddress[index];
}
template<class T1>
int MyArray<T1>::getCapacity()
{
	return this->m_Capacity;
}
template<class T1>
int MyArray<T1>::getSize()
{
	return this->m_Size;
}
template<class T1>
void printArray(MyArray<T1>& arr)
{
	for (int i = 0; i < arr.getSize(); i++)
	{
		cout << arr[i] << endl;
	}
}

Main function call

#include <iostream>
using namespace std;
#include <fstream>
#include "Person.hpp"

void test()
{
	MyArray<int> arr(5);
	for (int i = 0; i < 5; i++)
	{
		arr.pushBack(i);
	}
	cout << "Start output array" << endl;
	printArray(arr);
}
int main() {
	test();

	system("pause");
	return 0;
}

The array can also store custom data types

2, STL acquaintance

1. Basic concepts

  • STL basic template library
  • STL is broadly divided into container, algorithm and iterator
  • Container and algorithm events are seamlessly connected through iterators
  • Almost all STL codes adopt template classes or template functions

2. STL six components

STL is generally divided into six components: container, algorithm, iterator, imitation function, adapter (adapter) and space configurator

  • Container: various data structures: vector, list, deque, set, map, etc. are used to store data
  • Algorithm: various commonly used algorithms, such as sort, find, copy and for_each et al
  • Iterator: acts as the glue between the container and the algorithm
  • Imitation function: a function with similar behavior, which can be used as a strategy of the algorithm
  • Adapter: something used to decorate a container or an interface to an emulator or iterator
  • Space configurator: responsible for space configuration and management

2.1 containers, algorithms, iterators

Container: a place to put things

STL container is to implement some of the most widely used data structures

Common data structures: array, list, tree, stack, queue, set, mapping table, etc

These containers are divided into sequential containers and associative containers

  • Sequential container: it emphasizes the sorting of values. Each element in the sequential container has a fixed position
  • Associative container: a binary tree structure in which there is no strict physical order between the elements

Algorithm: the solution of the problem

Limited steps to solve logical or mathematical problems are called algorithms

Algorithms are divided into: qualitative algorithm and non qualitative algorithm

  • Qualitative change algorithm: refers to the content of elements in the interval that will be changed during operation, such as copy, replacement, deletion, etc
  • Non qualitative algorithm: it means that the element content in the interval will not be changed during the operation, such as searching, counting, traversing, searching for extreme values, etc

Iterators: glue between containers and algorithms

A method is provided to search the elements contained in a container in order without exposing the internal representation of the container

Each container has its own iterator

Iterators use much like pointers

Iterator Categories

typejurisdictionSupport operation
Input iteratorread-only++,==,!=
Output iteratorWrite only++
Forward iteratorRead and write, and push the iterator++,==,!=
Bidirectional iteratorRead and write, which can be operated forward or backward++,–
Random access iteratorRead and write. Can jump to access any data++,–,[n],-n,<,>

The commonly used types of iterators in containers are bidirectional iterators and random access iterators

3. Iterator initialization

3.1 vector stores built-in data types

Containers: vector

Algorithm: for_each

Iterator: vector < int >:: iterator

#Include < vector > / / vector header file
#Include < algorithm > / / standard algorithm header file

void printVector(int value)
{
	cout << value << endl;
}
// vector stores built-in data types
void test()
{
	// Create a vector container - array
	vector<int> v;

	// Insert data into container
	v.push_back(10);  // Tail interpolation data
	v.push_back(11);
	v.push_back(12);

	// Accessing data in a container through iterators
	vector<int>::iterator itBegin = v.begin(); // The starting iterator points to the first element in the container and is used as a pointer
	vector<int>::iterator itEnd = v.end();  // Ends the iterator and points to the next position of the last element of the container

	// The first traversal method
	while (itBegin != itEnd)
	{
		cout << *itBegin << endl;
		itBegin++;
	}
	// The second traversal method
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << endl;
	}
	// The third traversal method
	for_each(v.begin(), v.end(), printVector);  // Callback function
}

3.2 vector stores user-defined data types

The user-defined data type is stored in the vector and printed out

// Store custom data types
class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}
	int m_Age;
	string m_Name;
};

void test()
{
	vector<Person> v;
	Person p1("a", 20);
	Person p2("b", 34);
	Person p3("c", 20);
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);

	// Traversal data
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "name:" << it->m_Name  
			<< " age:" << it->m_Age << endl;  // it is a pointer
	}

	// Pointer for storing custom data type
	vector<Person*> v1;
	v1.push_back(&p1);
	v1.push_back(&p2);
	v1.push_back(&p3);
	// Traversal data
	for (vector<Person*>::iterator its = v1.begin(); its != v1.end(); its++)
	{
		cout << "name:" << (*its)->m_Name
			<< " age:" << (*its)->m_Age << endl;  // it is a pointer
	}
}

3.3 nested containers in vector

The container is nested in the container, and we traverse all the data through the output

// Container nested container
void test()
{
	vector<vector<int>> V;
	// Create a small container
	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	vector<int> v4;

	// Adding data to a small container
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
		v2.push_back(10 - i);
		v3.push_back(20 - i);
		v4.push_back(i + 10);
	}
	// Insert the small container into the large container
	V.push_back(v1);
	V.push_back(v2);
	V.push_back(v3);
	V.push_back(v4);

	// Traverse large containers
	for (vector<vector<int>>::iterator i = V.begin(); i != V.end(); i++)
	{
		// *i is a container
		for (vector<int>::iterator j = (*i).begin(); j != (*i).end(); j++)
		{
			cout << *j << "\t";
		}
		cout << endl;
	}
}

3, STL common containers

Header files should be added to each container

1. string container

Basic concept of string 1.1

essence

  • String is a C + + style string, and string is essentially a class

The difference between string and char *

  • char * is a pointer
  • String is a class, which encapsulates char * inside. Managing this string is a char * container

characteristic

  1. string class encapsulates many member methods
    • For example: find, copy, delete, replace, insert
  2. string manages the memory allocated by char * without worrying about copying and value crossing. It is the responsibility of the class

1.2 string constructor

Constructor prototype

  • string(); Create an empty string

    string(const char* s); Initialize with string s

  • string(const string& str); Initializing another string object with one string object

  • string(int, char c); Initialize with n characters C

/*
- string();							Create an empty string
  string(const char* s);			Initialize with string s
- string(const string& str);		Initializing another string object with one string object
- string(int, char c);              Initialize with n characters c
*/
void test()
{
	string s1;  // Default construction
	const char* str = "hello world";
	string s2(str);  // Parametric structure
	cout << "s2:" << s2 << endl;
	string s3(s2);  // copy construction 
	cout << "s3:" << s3 << endl;
	string s4(10, 'a');  // 10 a structures
	cout << "s4:" << s4 << endl;
}

The various construction methods of string are not comparable and have high flexibility

1.3 string assignment

Function description

  • Assign a value to a string

Prototype of assignment function

string& operator=(const char* s);  // char * type string is assigned to the current string
string& operator=(const string &s);  // Assign the string s to the current string
string& operator=(char c);  // Assigns a character to the current string
string& assign(const char* s);  // Assign the string s to the current string
string& assign(const char* s, int n);  // Assign the first n characters of the current string
string& assign(const string &s);  // Assign the string s to the current string
string& assign(int n, char c);  // Assign n characters c to the current string

1.4 string splicing

Function description

  • Implements splicing strings at the end of a string

Function prototype

string& operator+=(const char* str);  // Overload + = operator
string& operator+=(const char c);  // Overload + = operator
string& operator+=(const string& str);  // Overload + = operator
string& append(const char* s);  // Concatenates the string s to the end of the current string
string& append(const char* s, int n);  // Connect the first n characters of string s to the end of the string
string& append(const string& s);  // Same as operator + = (const string & STR);
string& append(const string& s, int pos, int n);  // String s connects n characters from pos to the end of the string

1.5 string find and replace

Function description

  • Find: finds whether the specified character exists
  • Replace: replaces the string at the specified position

Function prototype

int find(const string& str, int pos = 0) const;  // Find the location where str first appears, starting from pos
int find(const char* s, int pos = 0) const;  // Find the location where s first appears, starting from pos
int find(const char* s, int pos, int n) const;  // Find the position where the first n characters of s appear for the first time from the pos position
int find(const char c, int pos = 0) const;  // Find the position where the character c first appears
int rfind(const string& str, int pos = npos) const;  // Find the last position of str, starting from pos
int rfind(const char* s, int pos = npos) const;  // Find the location where s last appeared, starting from pos
int rfind(const char* s, int pos, int n) const;  // Find the position of the last occurrence of the first n characters of s from pos
int rfind(const char c, int pos = 0) const;  // Finds the last occurrence of the character c
string& replace(int pos, int n, const string& str);  // Replace n characters starting from pos with string str
string& replace(int pos, int n, const char* s);  // Replace the n characters starting from pos with the string s

summary

  • find is from left to right and rfind is from right to left
  • find returns the position of the first character after finding the string. If not, it returns - 1
  • When replacing, you need to specify where to start, how many characters to replace and what kind of string to replace

1.6 string comparison

Function description

  • Comparison between strings

Comparison mode

  • String comparison is based on the ASCII code of characters
  • =Return 0
  • < return 1
  • >Return - 1

Function prototype

int compare(const string& s) const;  // Compare with string s
int compare(const char* s) const;  // Compare with string s

It mainly compares whether the two strings are equal

1.7 string character access

There are two ways to access a single character in a string

char& operator[](int n);  // Get characters through [] method
char& at(int n);  // Get characters through at method
str.size();  // Returns the length of the string 

Characters can be modified, STR [int n] ='c '

1.8 string insertion and deletion

Function description

  • Insert and delete characters on string string

Function prototype

string& insert(int pos, const char* s);  // Insert string
string& insert(int pos, const string& str);  // Insert string
string& insert(int pos, int n, char c);  // Insert n characters in the specified position c
string& erase(int pos, int n = npos);  // Delete n characters starting from pos

1.9 substring in string

Function description

  • Get the desired substring from the string

Function principle

string substr(int pos = 0, int n = npos) const;  // Returns a string of n characters starting with pos

2. vector container

2.1 basic concept of vector

function

  • vector data structure is very similar to array, also known as single ended array

The difference between vector and ordinary array

  • The difference is that the array is a static space, while the vector can be extended dynamically

    Dynamic expansion

    • Instead of connecting a new space after the original space, find a larger memory space, and then copy the original data to the new space to release the original space

    • The iteration of the vector container is an iterator that supports random access

2.2 vector constructor

Function description

  • Create vector container

Function prototype

vector<T> v;  // Using template implementation class implementation, default constructor
vector v2(v.begin(), v.end());  // Copy the elements in the v[begin(), end()] interval to itself, closing on the left and opening on the right
vector v3(n, elem);  // The constructor copies n elem s to itself
vector v4(const vector& vec);  // copy constructor 

Many construction methods of vector are not comparable and can be used flexibly

2.3 vector assignment

Function description

  • Assign a value to the vector container

Function principle

vector& operator=(const vector &vec);  // Overload assignment operator
assign(v.begin(), v.end());  // Assign the data copy in the v[begin, end] interval to itself
assign(n, elem);  // Assign n elem copies to itself

2.4 vector size operation

Function description

  • Operation on the capacity and size of the vector container

Function prototype

empty();  // Determine whether the container is empty
capacity();  // Capacity of container
size();  // Number of elements returned in the container
resize(int num);  // Reassign the length of the container to num. if the container becomes longer, fill the new position with the default value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted (0 by default)
resize(int num, elem);  // Reassign the length of the container to num. if the side of the container is long, fill the new position with elem value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted
void printVector(vector<int>& v)
{
	for (vector<int>::iterator i = v.begin(); i != v.end(); i++)
	{
		cout << *i << " ";
	}
	cout << endl;
}
void test()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	cout << v.capacity() << endl;
	cout << v.size() << endl;
	v.resize(20);  // Fill with 0 by default
	cout << v.size() << endl;
	cout << v.capacity() << endl;
	printVector(v);
}

Capacity greater than or equal to size

2.5 vector insertion and deletion

Function description

  • Insert and delete the vector container

Function prototype

push_back(elem);  // Tail insert elem ent
pop_back();  // Delete last element
insert(const_iterator pos, elem);  // The iterator points to the position pos to insert the element elem
insert(const_iterator pos, int n, elem);  // The iterator points to the position pos and inserts n elements
erase(const_iterator pos);  // Deletes the length pointed to by the iterator
erase(const_iterator start, const_iterator end);  // Delete the elements from start to end of the iterator, close left and open right
clear();  // Delete all elements in the container

​ v1.insert(v1.begin(), 100); // The first parameter is the iterator

2.6 vector data access

Function description

  • Access to data in vector

Data prototype

at(int idx);  // Returns the object that the index idx refers to
operator[](int idx);  // Returns the data indicated by the index idx
fornt();  // Returns the first data element in the container
back();  // Returns the last data element in the container

2.7 vector interchange container

Function description

  • Realize the exchange of elements in two containers

Function prototype

swap(v);  // Swap vec with its own elements
void test()
{
	vector<int> v;
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v.insert(v.begin(), i);
		v1.push_back(i + 100);
	}
	cout << "Before exchange" << endl;
	printVector(v);
	printVector(v1);
	v.swap(v1);
	cout << "After exchange" << endl;
	printVector(v);
	printVector(v1);
}

Function: using swap skillfully can shrink the memory space vector < int > (V) swap(v); // Use anonymous objects

2.8 reserved space for vector

Function description

  • Reduce the expansion times of vector when dynamically expanding capacity

Function principle

reserve(int len);  // The container reserves len lengths, the reserved positions are not initialized, and the elements are inaccessible
void test()
{
	vector<int> v;

	int num = 0;  // Statistics of development times
	v.reserve(1000000);  // When this code is not added, 35 memory spaces are opened up
	int* p = NULL;  
	for (int i = 0; i < 1000000; i++)
	{
		v.push_back(i);
		if (p != &v[0])  // Once the memory is opened, its first address will change
		{
			p = &v[0];
			num++;
		}
	}
	cout << num << endl;
}

If the reserved space is large, the reserved data can be used

3. deque container

3.1 deque basic concept

function

  • Double ended array: the header can be inserted or deleted

The difference between deque and vector

  • vector has low efficiency in inserting and deleting header, large amount of data and low efficiency
  • deque relatively speaking, the insertion and deletion speed of the head will be faster than that of the vector
  • vector accesses elements faster than deque, which is related to the implementation of both

deque internal working principle

deque has a central controller inside, which maintains the contents of each buffer and stores real data in the buffer

The central controller maintains the address of each buffer, making deque like a continuous memory space

The iterator of deque container also supports random access

3.2 deque constructor

Function description

  • deque vessel construction

Function principle

deque<T> deq;  // Default construction form
deque d2(deq.begin(), deq.end());  // The constructor copies the elements in the [beg, end] interval to itself
deque d3(n, elem);  // The constructor copies n elem s to itself
deque d4(const deque &deq);  // copy constructor 

3.3 deque assignment

Function description

  • Assign a value to the deque container

Function principle

deque& operator=(const deque& d);  // Overload assignment operator
assign(beg, end);  // Assign the data copy in the [beg, end] interval to itself
assign(n, elem);  // Assign n elem copies to itself

3.4 deque size operation

Function description

  • Operate on the size of the deque container

Function principle

empty();  // Determine whether the container is empty
size();  // Returns the number of elements in the container
resize(int num);  // Reassign the length of the container to num. if the container becomes longer, fill the new position with the default value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted (0 by default)
resize(int num, elem);  // Reassign the length of the container to num. if the side of the container is long, fill the new position with elem value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted

deque has no concept of capacity

3.5 deque insertion and deletion

Function description

  • Inserting and deleting data into the deque container

Function prototype

// Two end operation
push_back(elem);  // Add a data at the end of the container
push_front(elem);  // Insert a data in the head of the container
pop_back();  // Delete the last data in the container
pop_front();  // Delete the first element of the container

// Specify location operation
insert(pos, elem);  // Insert a copy of the elem element in the pos position and return the location of the data
insert(pos, n, elem);  // Insert n elem data in pos position, no return value
insert(pos, beg, end);  // Insert (D1. Begin()) at the pos position End()) data, no return value
clear();  // Empty all data in the container
erase(beg, end);  // Delete the data in the [beg, end] interval and return the position of the next data
erase(pos);  // Delete the data in pos position and return to the position of the next data

The pos inside is the position of the iterator pointer

3.6 deque data access

Function description

  • Access to data in deque

Function prototype

at(int idx);  // Returns the data indicated by the index idx
operator[])(int idx);  // Returns the value of index idx
front();  // Returns the first data element of the container
back();  // Returns the last data element of the container

3.7 deque sorting

Function description

  • Use the deque algorithm to sort the data

Function prototype

sort(iterator beg, iterator end);  // Sort the elements in the [beg, end] interval

Note that the header file #include < algorithm > should be included when using

For containers that support random access iterators, they can be sorted directly by sort algorithm

vector can also be sorted using sort

4. Case - judges' scoring

4.1 case description

There are five contestants: contestant ABCDE, and 10 judges will score each contestant respectively, removing the highest score and the lowest score among the judges, and taking the average score

4.2 implementation steps

  1. Create five players and put them in the vector container
  2. Traverse the vector container, take out each player, execute the for loop, and save 10 scores into the deque container
  3. sort algorithm sorts the scores in deque container to remove the highest and lowest scores
  4. The deque container is traversed and the total score is accumulated
  5. Get average score
// Player category
class Person
{
public:
	Person(string name, int score)
	{
		m_Name = name;
		m_Score = score;
	}
	string m_Name;
	int m_Score;  // average
};
void createPerson(vector<Person>& v)
{
	// Create five players
	for (int i = 0; i < 5; i++)
	{
		char nameSeed[] = { 'A', 'B', 'C', 'D', 'E' };
		string name = "player";
		name += nameSeed[i];
		int score = 0;  // The default is 0
		Person p(name, score);
		v.push_back(p);
	}
}
void setScore(vector<Person>& v)
{
	// Score
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		// Put the judges' scores into the deque container
		deque<int> d;
		for (int i = 0; i < 10; i++)
		{
			int score = rand() % 41 + 60;  // Score between 60 and 100, random
			d.push_back(score);  // Put the score into the container
		}
		// sort
		sort(d.begin(), d.end());

		// Remove the highest score and the lowest score
		d.pop_front();
		d.pop_back();
		// Average score
		int sum = 0;
		for (deque<int>::iterator dit = d.begin(); dit != d.end(); dit++)
		{
			sum += *dit;  // Cumulative score
		}
		int avr = sum / d.size();
		it->m_Score = avr;
	}
}
void showScore(vector<Person> v)
{
	for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "The name is:" << it->m_Name << "  The average score is:" << it->m_Score << endl;
	}
}
void test()
{
	// Random number seed
	srand((unsigned int)time(NULL));

	vector<Person> v;  // Store contestants
	v.reserve(5);

	createPerson(v);

	setScore(v);

	showScore(v);
}

5. stack container

5.1 basic concept of stack

Concept: stack is a data structure with first in and last out. It has only one exit

Elements entering the stack are called push();

Pop up elements in the stack are called out of stack: pop();

5.2 stack common interfaces

Function Description:

  • Common external interface of stack container
5.2.1 constructor
stack<T> stk;  // Stack is implemented by template, and the default construction form of stack object
stack stk1(const stack& stk);  // copy constructor 
5.2.2 assignment operation
stack& operator=(const stack& stk);  // Overload assignment operator
5.2.3 size operation
empty();  // Determine whether the stack is empty
size();  // Returns the size of the stack
5.2.4 data access
push(elem);  // Add an element to the top of the stack
pop();  // Remove the first element from the top of the stack
top();  // Return stack top element

6. queue container

6.1 basic concept of queue

Concept:

  • queue is a first in first out data structure with two exits

Queue containers allow you to add elements from one end and remove elements from the other

Only the head and tail of the queue can be used by the outside world, so the queue is not allowed to traverse

Incoming data in the queue is called incoming: push();

Out of queue data is called out of queue: pop();

6.2 common interfaces of queue

Function description

  • Common external interface of stack container
6.2.1 constructor
queue<T> q;  // Queue is implemented by template class, and the default constructor of queue object
queue(const queue& que);  // copy constructor 
6.2.2 assignment operation
queue& operator=(const queue& q);  // Overload assignment operator
6.2.3 size operation
empty();  // Determine whether the stack is empty
size();  // Return stack size
6.2.4 data access
push(elem);  // Add elements to the end of the queue
pop();  // Remove the first element from the team head
back();  // Returns the last element
front();  // Returns the first element of the queue header

7. list container

7.1 basic concepts

Function: chain storage of data

Linked list is a discontinuous storage structure on physical storage unit. The logical order of data elements is realized through pointer links in the linked list

Composition of linked list: linked list is composed of a series of nodes

Composition of nodes: one is the data field for storing data elements, and the other is the pointer field for storing the address of the next node

The linked list in STL is a two-way circular linked list

Because the storage mode of the linked list is not a continuous memory space, the iterator in the linked list only supports forward or backward, which belongs to a two-way iterator

list advantages

  • Dynamic memory allocation is adopted, which will not cause memory waste and overflow
  • It is very convenient to insert and delete the linked list. You can modify the pointer without moving a large amount of data

list disadvantages

  • The linked list is flexible, but the additional cost of space (pointer field) and time (traversal) is large

List has an important property. Neither insert nor delete will invalidate the original list iterator, which is not true in vector

Summary: list and vector are the most commonly used containers in STL, with their own advantages and disadvantages

7.2 list constructor

Function description

  • Create a list container

Function prototype

list<T> l;  // list is implemented by template class, and the default construction form of object
list(beg, end);  // The constructor copies the elements in the [beg, end] interval to itself
list(n, elem);  // The constructor copies n elem s to itself
list(const list& l);  // copy constructor 

7.3 list assignment and exchange

Function description

  • Assign values to the list container and exchange list containers

Function prototype

assign(beg, end);  // Assign the data copy in the [beg, end] interval to itself
assign(n, elem);  // Assign n elem copies to itself
list& operator=(const list& l);  // Overload assignment operator
swap(l);  // Swap the list with its own elements

7.4 list size operation

Function description

  • Operate on the size of the list container

Function prototype

size();  // Number of elements returned in the container
empty();  // Determine whether the container is empty
resize(int num);  // Reassign the length of the container to num. if the container becomes longer, fill the new position with the default value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted (0 by default)
resize(int num, elem);  // Reassign the length of the container to num. if the side of the container is long, fill the new position with elem value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted

7.5 list insertion and deletion

Function description

  • Insert and delete data from the list container

Function prototype

push_back(elem);  // Add a data at the end of the container
push_front(elem);  // Insert a data in the head of the container
pop_back();  // Delete the last data in the container
pop_front();  // Delete the first element of the container
insert(pos, elem);  // Insert a copy of the elem element in the pos position and return the location of the data
insert(pos, n, elem);  // Insert n elem data in pos position, no return value
insert(pos, beg, end);  // Insert (l.begin(), l.end()) data in pos position, no return value
clear();  // Empty all data in the container
erase(beg, end);  // Delete the data in the [beg, end] interval and return the position of the next data
erase(pos);  // Delete the data in pos position and return to the position of the next data
remove(elem);  // Delete all elements in the container that match the element value

7.6 list data access

Function description

  • Access the data in the list container

Function prototype

front();  // Returns the first element
back();  // Returns the last element

Note that you cannot access elements in a container using at and []

The reason is that the list is essentially a linked list, rather than using continuous linear space to store data, and the iterator does not support random access

Iterators do not support random access and support two-way access

7.7 list inversion and sorting

Function description

  • Invert the elements in the container and sort the data in the container

Function prototype

reverse();  // Reverse linked list
sort();  // Linked list sorting, which is a member function

All containers that do not support random access iterators cannot use standard algorithms

Containers that do not support random access iterators will provide corresponding algorithms internally

For custom data types, sort() brackets can add a collation

Advanced sorting is just another logical rule formulation on the sorting rules, which is not complicated

bool comparePerson(Person& p1, Person& p2)
{
    // Ascending by age
    if (p1.m_Age == p2.m_Name)
    {
        // Same age, ascending height
        return p1.Height > p2.Height;
    }
    else
    {
        return p1.m_Age < p2.m_Age;
    }
}
l.sort(comparePerson);  // Sorting algorithm

8. set / multiset container

8.1 basic concepts

Introduction:

  • All elements are automatically sorted on insertion

essence

  • set is an associative container, and the underlying structure is implemented by binary tree

Difference between set and multiset

  • set does not allow duplicate elements in the container
  • multiset allows duplicate elements in a container

8.2 set construction and assignment

Function description

  • Create set container and assign values

Function prototype

set<T> s;  // Default constructor 
set(const set& s);  // copy constructor 

set& operator=(const set& s);  // Overload assignment operator
inset(elem);  // insert data

8.3 set size and swap

Function description

  • Count the size of set container and exchange set container

Function prototype

size();  // Returns the number of elements in the container
empty();  // Determine whether the container is empty
swap(s);  // Swap two collection containers 

8.4 set insertion and deletion

Function description

  • set container to insert and delete

Function prototype

insert(elem);  // Insert element in container
clear();  // Empty all elements
erase(pos);  // Delete the element referred to by the pos iterator and return the iterator of the next element
erase(beg, end);  // Delete all elements of the interval [beg, end], and return the iterator of the next element
erase(elem);  // Delete the element with element in the container

8.5 set search and statistics

Function description

  • Find data and make data statistics for the set container

Function prototype

find(key);  // Find out whether the key exists. If so, return the iterator of the element of the key; If it does not exist, return set end();
count(key);  // Count the number of key elements

8.6 differences between set and multiset

Master the difference between set and multiset

difference

  • set cannot insert duplicate data, while multiset can

  • set will return the insertion result when inserting data, indicating whether the insertion is successful

    ret.second is used to check whether the insertion is successful

  • multiset does not detect data, so you can insert data repeatedly

8.7 pair group creation

Function description

  • For the data that appears successfully, two data can be returned by using the pair group

Two creation methods

pair<type1, type2> p (value1, value2);  // The two types correspond to the data type of value respectively
pair<type1, type2> p = make_pair(value1, value2);

There are two creation methods. Just remember one

Mode of use

pair<string, int> p ("Tom", 20);
cout << "name:" << p.first << "  age:" << p.second;

8.8 set sorting

The default sorting rule of set container is from small to large. Master how to change the sorting rule

  • Using the imitation function, the sorting rules can be changed
#include <set>
class MyCompare
{
public:
	bool operator()(int v1, int v2) const  
	{
		return v1 > v2;  // Descending sort
	}
};

void test()
{
	// Store built-in data types and change sorting rules
	set<int, MyCompare> s1;  // The essence of affine function is a class
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);
	for (set<int, MyCompare>::iterator it = s1.begin(); it != s1.end(); it++)
	{
		cout << *it << endl;
	}
}

For custom data types, to create a collation, you must specify a collation

class MyCompare
{
public:	  
    bool operator()(const Person& p1, const Person& p2)
    {
        // In descending order of age
        return p1.m_Age > p2.m_Age;
    }
};

9. map / multimap container

9.1 basic concepts

Introduction:

  • All elements in the map are pair
  • The first element in pair is key (key value), which serves as an index, and the second element is value (real value)
  • All elements are automatically sorted according to the key value of the element

Essence:

  • map/ multimap is an associative container, and its underlying structure is realized by binary tree

advantage:

  • You can quickly find the value value according to the key value

map/ multimap differences

  • map does not allow duplicate key value elements in the container
  • multimap allows duplicate key value elements in the container

9.2 map construction and assignment

Function Description:

  • Construct and assign the map container

Function prototype

map<T1, T2> mp;  // map default constructor
map (const map& mp);  // copy construction 

map& operator=(const map& mp);  // Overload assignment operator

All elements in the map container appear in pairs, and pairs should be used when inserting data

9.3 map size and swap

Function Description:

  • Map container size and exchange map values

Function prototype

size();  // Returns the number of elements in the container
empty();  // Judge whether the capacity is empty
swap(mp);  // Swap two collection containers

9.4 map insertion and deletion

Function Description:

  • map container to insert and delete data

Function prototype

insert(elem);  // Insert element in container
clear();  // Empty all elements
erase(pos);  // Delete the element referred to by the pos iterator and return the iterator of the next element
erase(beg, end);  // Delete all elements of the interval [beg, end], and return the iterator of the next element
erase(key);  // Delete the element whose container key is key

Note that you are inserting a pair of groups

// First kind
m.insert(pair<int, int>(1, 10));
// Second
m.insert(make_pair(2, 20));
// Third
m.insert(map<int, int>::value_type(3, 30));
// Fourth
m[4] = 40;  // It is not recommended. You can use [] to access the value

9.5 map search and statistics

Function Description:

  • Search data and statistics of map container

Function prototype

find();  // Find out whether the key exists and return the iteration value of the element that changed the key; If it does not exist, return m.end();
count();  // Count the number of key elements

Map. 6 sorting

The default collation of the map container is to sort in ascending order by key

  • The sorting rules can be changed by using the imitation function

It is similar to [set sort] (#8.8 set sort)

10. Case - employee grouping

10.1 case description

  • The company recruits 10 employees every day. After 10 employees enter the company, which department should they be assigned to work in
  • Employee information: name and salary composition; The departments are divided into: planning, art and R & D
  • Randomly assign department and salary to 10 employees
  • Insert information through multimap. key: department number, value: employee
  • Show employees by segment

10.2 implementation steps

  1. Create 10 employees and put them into the vector
  2. Traverse the vector container, take out each employee and group them randomly
  3. After grouping, put the employee department number as the key and the specific employee as the value into the multimap container
  4. Display employee information by Department

10.3 code demonstration

class Worker
{
	// Create employee
public:
	string m_Name;
	int m_Salary;
};
void createWorker(vector<Worker>& v)
{
	// Create 10 employees
	for (int i = 0; i < 10; i++)
	{
		Worker worker;
		string nameSeed = "ABCDEFGHIJ";
		worker.m_Name = "staff";
		worker.m_Name += nameSeed[i];
		worker.m_Salary = rand() % 10000 + 10000;  // 10000~19999
		v.push_back(worker);  // Put employees into groups
	}
}
void printWorker(const vector<Worker>& v)
{
	for (vector<Worker>::const_iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "name: " << it->m_Name << "   salary: " << it->m_Salary << endl;
	}
}
void printWorker(multimap<string, Worker>& mp, string* arr)
{
	string s0(20, '-');
	for (int i = 0; i < 3; i++)
	{
		string s = arr[i];
		s += "Department information";
		cout << s << endl;
		multimap<string, Worker>::iterator pos = mp.find(arr[i]);  // Returns the iterator object
		int count = mp.count(arr[i]);
		for (int index = 0; pos != mp.end() && index < count; pos++, index++)
		{
			cout << "full name:" << pos->second.m_Name << "   Salary:" << pos->second.m_Salary << endl;
		}
		cout << s0 << endl;
	}
}
void setGroup(vector<Worker>& v, multimap<string, Worker>& mp, string* arr)
{
	for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++)
	{
		// Generate random department number
		int depId = rand() % 3;  // 0 1 2 random number
		// Insert the employee into the group, key number, value employee
		mp.insert(pair<string, Worker>(arr[depId], *it));
	}
}
void test()
{
	// Add random seed
	srand((unsigned int)time(NULL));
	string dep[] = { "plan", "Fine Arts", "research and development" };
	vector<Worker> v;
	createWorker(v);
	printWorker(v);

	// Employee grouping
	multimap<string, Worker> mp;
	setGroup(v, mp, dep);
	printWorker(mp, dep);
}

4, STL function object

1. Function object

1.1 basic concepts

Concept:

  • A class that overloads the function call operator. Its object is often called a function object
  • When a function object uses overloaded (), its behavior is similar to that of a function call, which is also called an imitation function

Essence:

  • A function object is a class, not a function

1.2 application method

characteristic:

  • When a function object is used, it can be called like an ordinary function, with parameters and return values
  • Function objects go beyond the concept of ordinary functions. Function objects can have their own states
  • Function objects can be passed as arguments
// Function object
class MyAdd
{
public:
	MyAdd()
	{
		this->count = 0;
	}
	int operator()(int v1, int v2)
	{
		this->count++;
		return v1 + v2;
	}
	int count;  // Function objects can have their own internal state
};
void test()
{
	MyAdd ma;
	cout << ma(1, 2) << endl;
	cout << ma(1, 2) << endl;
	cout << ma(1, 2) << endl;
	cout << ma(1, 2) << endl;
	cout << "The number of calls is:" << ma.count << endl;
}

2. Predicate

2.1 predicate concept

concept

  • Functions that return bool types are called predicates
  • If operator() accepts a parameter, it is called a unary predicate
  • If operator() accepts two parameters, it is called a binary predicate

2.2 unary predicate

class CreateFive
{
public:
	bool operator()(int val)
	{
		return val > 5 ? true : false;
	}  // one-element predicate

};

void test()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	// Find out if there is a number greater than 5 in the container
	vector<int>::iterator it = find_if(v.begin(), v.end(), CreateFive());  // It is an anonymous function object, find_ The return value of if is an iteration object
	if (it == v.end())
	{
		cout << "Can't find" << endl;
	}
	else
	{
		cout << "Numbers greater than five are:" << *it << endl;
	}
}

2.3 binary predicate

// two-place predicate
class MySort
{
public:
	bool operator()(int a, int b)
	{
		return a > b ? true : false;
	}
};
void test()
{
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);
	// sort(v.begin(), v.end());  //  Ascending arrangement
	// Use the function object to change the algorithm strategy into descending arrangement of sorting rules
	sort(v.begin(), v.end(), MySort());
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

3. Built in function object

3.1 significance

Concept:

  • STL has built-in function objects

Classification:

  • Arithmetic imitation function
  • Relational affine function
  • Logical imitation function

Usage:

  • The usage of the objects generated by these imitation functions is exactly the same as that of general functions
  • When using built-in function objects, the header file #include < functional > needs to be introduced

3.2 arithmetic imitation function

Function Description:

  • Realize four operations
  • Among them, negate is a unary operation, and others are binary operations

Function imitating principle

template<class T> T plus<T>;  // Addition operation
template<class T> T minus<T>;  // Subtraction operation
template<class T> T multiplies<T>;  // Multiplication
template<class T> T divides<T>;  // Division operation
template<class T> T modulus<T>;  // Modular operation
template<class T> T negate<T>;  // Inverse operation, and the inverse of 10 is - 10
plus<int> p;
cout << p(10, 20) << endl;
negate<int> n;
cout << n(20) << endl; 

3.3 relation imitation function

Function description

  • Implement relationship comparison

Function imitating principle

template<class T> bool equal_to<T>;  // =
template<class T> bool not_equal_to<T>;  // !=
template<class T> bool greater<T>;  // >
template<class T> bool greater_equal<T>;  // >=
template<class T> bool less<T>;  // <
template<class T> bool less_equal<T>;  // <=

3.4 logic imitation function

Function description

  • Realize logical operation

Imitative function principle

template<typename T> bool logical_and<T>;  // And
template<typename T> bool logical_or<T>;  // or
template<typename T> bool logical_not<T>;  // wrong

5, STL common algorithms

Description:

  • The algorithm is mainly composed of header file < algorithm > < functional > < numeric >
  • < algorithm > is the largest of all STL header files, covering comparison, exchange, search, traversal, assignment, etc
  • < numeric > is small in size and only includes several module functions that perform simple mathematical operations on the sequence
  • < functional > defines some modular classes to declare function objects

1. Common traversal algorithms

Learning objectives:

  • Master common traversal algorithms

Algorithm Introduction:

for_each();  // Traversal container
transform();  // Transport container to another container

1.1 for_each

Function Description:

  • Implement traversal container

Function prototype

for_each(iterator beg, iterator end, _func);

Traversal algorithm: traversal of container elements

Parameters:

  • beg: start iterator
  • End: end iterator
  • _ func: function or function object, which is generally a function of output content and a callback function

1.2 transform

Function Description:

  • Transport container to another container

Function prototype

transform(iterator beg1, iterator end1, iterator beg2, _func);

The target container should open up space in advance, otherwise an error will be reported

Parameters:

  • beg1: source container start iterator
  • end1: source container end iterator
  • beg2: target container start iterator
  • _ func: function or function object

2. Common search algorithms

Learning objectives:

  • Master common search algorithms

Algorithm Introduction:

find();  // Find element
find_if();  // Find elements by criteria
adjacent_find();  // Find adjacent duplicate elements
binary_search();  // Binary search method
count();  // Number of statistical elements
count_if();  // Count the number of elements by condition

2.1 find

Function Description:

  • Finds the specified element, finds the iterator that returns the specified element, and cannot find the return end iterator

Function prototype

find(iterator beg, iterator end, value);

Parameters:

  • beg: start iterator
  • End: end iterator
  • value: the element to find

If it is a custom data type, the equal sign operator should be overloaded when searching

2.2 find_if

Function Description:

  • Find elements by criteria

Function prototype

find_if(iterator beg, iterator end, _Pred);

Parameters:

  • beg: start iterator
  • End: end iterator
  • _ Pred: function or predicate (return bool type imitation function)

2.3 adjacent_find

Function Description:

  • Find adjacent duplicate elements

Function prototype

adjacent_find(iterator beg, iterator end);

Parameters:

  • beg: start iterator
  • End: end iterator

2.4 binary_search

Function Description:

  • Finds whether the specified element exists

Function prototype

bool binary_search(iterator beg, iterator end, value);

Note: not available in unordered sequences

Parameters:

  • beg: start iterator
  • End: end iterator
  • value: the element to find

2.5 count

Function Description:

  • Number of statistical elements

Function prototype

count(iterator beg, iterator end, value);

beg: start iterator

End: end iterator

value: statistical element

When making statistics on user-defined data types, you should use imitation functions

class Person
{
public:
    Person(string name, int age)  
    {
        this->m_Name = name;
        this->m_Age = age;
    }
    bool operator==(const Person& p)  // You need to overload the equal sign operator before you can count
    {
        return this->m_Age == p.m_Age && this->m_Name = p.m_Name? true : flase;
    }
    int m_Age;
    string m_Name;
};

When counting user-defined data types, you need to overload the operator==

2.6 count_if

Function Description:

  • Count the number of elements by condition

Function prototype

count_if(iterator beg, iterator end, _Pred);

Parameters:

  • beg: start iterator
  • Iterator: end
  • _ Pred: predicate

3. Common sorting algorithms

Learning objectives

  • Master common sorting algorithms

Algorithm Introduction:

sort();  // Sort the elements in the container
random_shuffle();  // Shuffle, randomly adjust the order of elements within the specified range
merge();  // Container elements are merged and stored in another container
reverse();  // Inverts the elements in the specified range

3.1 sort

Function description

  • Sort the elements in the container

Function prototype

sort(iterator beg, iterator end, _Pred);

Parameters:

  • beg: start iterator
  • End: end iterator
  • _ Pred: predicate

3.2 random_shuffle

Function description

  • Shuffle, randomly adjust the order of elements within the specified range

Function prototype

random_shuffle(iterator beg, iterator end);

Remember to add random seeds when using

srand((unsigned int)time(NULL));

Parameters:

  • beg: start iterator
  • End: end iterator

3.3 merge

Function Description:

  • The two container elements are merged and stored in another container

Function prototype

merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

be careful:

  • The two containers must be ordered
  • Allocate space to the target container in advance

Parameters:

  • beg1: container 1 start iterator
  • end1: container 1 end iterator
  • beg2: container 2 start iterator
  • end2: container 2 end iterator
  • dest: destination container start iterator

3.4 reverse

Function description

  • Invert the elements in the container

Function prototype

reverse(iterator beg, iterator end);

Parameters:

  • beg: start iterator
  • End: end iterator

4. Common copy and replace algorithms

Learning objectives

  • Master common copy and replacement algorithms

Algorithm Introduction

copy();  // Copy the elements within the specified range in the container to another container
replace();  // Modify the old element of the specified range in the container to a new element
replace_if();  // Replace the elements that meet the conditions of the specified range in the container with new elements
swap();  // Swap elements of two containers

4.1 copy

Function Description:

  • Copies a specified range of elements within a container to another container

Function prototype

copy(iterator beg, iterator end, iterator dest);

Find the element by value, find the iterator that returns the specified position, and the iterator that returns the end cannot be found

You need to book the space of the target container first

Parameters:

  • beg: start iterator
  • End: end iterator
  • dest: destination container start iterator

4.2 replace

Function description

  • Modify the old element in the specified scope of the container to a new element

Function prototype

replace(iterator beg, iterator end, oldvalue, newvalue);

It will replace all qualified elements in the interval

Parameters:

  • beg: start iterator
  • End: end iterator
  • Oldline: Old element
  • newvalue: new element

4.3 replace_if

Functional usage

  • Replace the qualified elements in the interval with specific elements

Function principle

replace_if(iterator beg, iterator end, _Pred, newvalue);

It will replace all qualified elements in the interval

Parameters:

  • beg: start iterator
  • End: end iterator
  • _ Pred: predicate
  • newvalue: new element to replace

4.4 swap

Function Description:

  • Swap elements of two containers

Function prototype

swap(container c1, container c2);

Containers of the same data type can be interchanged

Parameters:

  • c1: container 1
  • c2: container 2

5. Common arithmetic generation algorithms

Learning objectives

  • Master common arithmetic generation algorithms

be careful:

  • The arithmetic generation algorithm is a small algorithm, and the header file to be included when using is #include < numeric >

Algorithm Introduction

accumulate();  // Container summation element
fill();  // Add element to container

5.1 accumulate

Function Description:

  • Calculate the sum of elements in the interval

Function prototype

accumulate(iterator beg, iterator end, firstValue);

Parameters:

  • beg: start iterator
  • End: end iterator
  • firstValue: initial cumulative value

5.2 fill

Function Description:

  • Fills the container with the specified element

Function prototype

fill(iterator beg, iterator end, value);

Parameters:

  • beg: start iterator
  • End: end iterator
  • Value: filled value

6. Common set algorithm

Learning objectives:

  • Master common set algorithms

Algorithm Introduction

set_insersection();  // Find the intersection of two containers
set_union();  // Find the union of two containers
set_different();  // Find the difference set of two containers

6.1 set_insersection

Function Description:

  • Find the intersection of two containers and duplicate elements

Function prototype

iterator itEnd = set_insersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);  // Intersection, an iterator that returns the last value

It is necessary to open up space in advance. In the most special case: large containers include small containers. Open up space and take the size of small containers

dest.resize(c1.size() > c2.size() ? c2.size() : c1.size());

Parameters:

  • beg1: container 1 start iterator
  • end1: container 1 end iterator
  • beg2: container 2 start iterator
  • end2: container 2 end iterator
  • dest: destination container start iterator

6.2 set_union

Function Description:

  • Find the union of two containers

Function prototype

iterator itEnd = set_insersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);  // Union, an iterator that returns the last value

The target container should open up space in advance. The most special case is that the two containers do not intersect

dest.resize(c1.size() + c2.size());

Parameters:

  • beg1: container 1 start iterator
  • end1: container 1 end iterator
  • beg2: container 2 start iterator
  • end2: container 2 end iterator
  • dest: destination container start iterator

6.3 set_difference

Function Description:

  • Find the difference set of two containers

Function prototype

iterator itEnd = set_insersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);  // The difference set of c1 and c2, the iterator that returns the last value, c1 - c2

The target container should open up space in advance. The most special case is that there is no intersection between the two containers, and the larger size is taken as the space of the container

dest.resize(c1.size() > c2.size() ? c1.size() : c2.size());  // You can also use max (C1. Size(), C2 size());

Parameters:

  • beg1: container 1 start iterator
  • end1: container 1 end iterator
  • beg2: container 2 start iterator
  • end2: container 2 end iterator
  • dest: destination container start iterator

Keywords: C++ Back-end

Added by onyx on Fri, 18 Feb 2022 16:40:29 +0200