c + + algorithm notes (under update)

Posted by gtal3x on Tue, 28 Dec 2021 23:51:32 +0100

algorithm

Sorting algorithm

There are basically eight sorting algorithms

  • Bubble sorting
  • Insert sort
  • Heap sort
  • Select sort
  • Quick sort
  • Merge sort
  • Cardinality sort
  • Shell Sort

Of course, it is not required to fully master all sorting methods. Nevertheless, it is necessary to understand the implementation principle. This provides ideas for us to encounter similar problems

When you encounter sorting problems, you can use sort () and stable in the header file algorthm_ sort() function to sort

The implementation of sort() uses quick sorting, which is not stable. Stable can be used when stable sorting is required_ sort(), which is merge sort.

The complexity of both sorts is O(nlogn), but generally fast sort is faster than merge sort, so sort() is used without stable sort

sort() usage

Two parameters sort (start address, end address + 1);

The default is ascending sort.

Code example:

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	int a[10]={2,5,1,7,3,9,0,4,8,6};
	sort(a,a+10);
	for(int i = 0; i < 10; i++){
		cout<<a[i]<<' ';
	}
} 
/*
Output:
0 1 2 3 4 5 6 7 8 9 
*/

Three parameters sort (start address, end address + 1, sorting function address);

Example code:

#include<iostream>
#include<algorithm>
bool cmp(int v1,int v2){
	return v1>v2;
}
using namespace std;
int main(){
	int a[10]={2,5,1,7,3,9,0,4,8,6};
	sort(a,a+10,cmp);
	for(int i = 0; i < 10; i++){
		cout<<a[i]<<' ';
	}
} 
/*
Output:
9 8 7 6 5 4 3 2 1 0
*/

Joint search set

Joint search is an uncommon algorithm, but it must be learned because it plays a great role.

effect:

It is to divide into sets to see whether two objects belong to the same set.

Principle:

  1. Implement with an array f[i], and initialize the array f[i] = i
  2. Build a relationship
  3. A find() function is required to find

Example code:

#include<iostream>
using namespace std;
//Join set array 
int f[10];
//Find function 
int find(int value){
	if(value!=f[value])return f[value]=find(f[value]);
	return value;
}
int main(){
	//Initialize f[i] array 
	for(int i = 0; i < 10; i++){
		f[i]=i;
	} 
	//Let's build the set {0}, {1,2,3,4}, {5}, {6,7,8,9}
	f[find(1)]=find(2);
	f[find(1)]=find(3);
	f[find(1)]=find(4);
	f[find(6)]=find(7);
	f[find(6)]=find(8);
	f[find(6)]=find(9);
	//Print understanding
	for(int i = 0; i < 10; i++){
		cout<<i<<" Belong to collection "<<find(i)<<endl; 
	} 
} 
/*
Output:
0 Belongs to collection 0
1 Belongs to set 4
2 Belongs to set 4
3 Belongs to set 4
4 Belongs to set 4
5 Belong to set 5
6 Belongs to set 9
7 Belongs to set 9
8 Belongs to set 9
9 Belongs to set 9
*/

search

Binary search

Binary search is very suitable for linear search, that is, the problem has certain increment or decrement. For example, finding a number in 0-1000000000 will cause huge time overhead if it is checked one by one in the ordinary order. The time complexity of binary search is O(logn), which greatly reduces the time overhead

Principle:

  1. Take three values, left = minimum range - 1, right = maximum range + 1,middle = (left + right)/2;
  2. If the middle value is larger than the ideal value, make right = middle + 1, and left = middle - 1;
  3. Repeat step 2 until middle = = ideal value;

(Note: the above is the usage of searching integer)

Example:

Search 1 number from 0x80000000+1 to 0x7fffff-1

Example code:

#include<iostream>
using namespace std;
int main(){
	cout<<"Please enter a "<<(int)0x80000000+1<<" reach "<<0x7fffffff-1<<" Number of"<<endl;
	int value;
	cin>>value;
	int l= (int)0x80000000;
	int r= (int)0x7fffffff;
	int ans=0;
	while(1){
		ans++;
		int m=(l+r)/2;
		if(m==value){
			cout<<m<<endl<<"Search times: "<<ans;
			break;
		}
		if(m>value){
			r=m+1;
		}else{
			l=m-1;
		}
	}
}

/*
Output:
Please enter a number from - 2147483648 to 2147483646
5
5
 Number of searches: 32
*/

Three point search

The trisection search is suitable for the minimization of parabola like curves

Principle:

  1. Take four values, left = minimum range, right = maximum range, middle1 = left + (left - right)/3, middle2 = right - (left + right)/3
  2. On the premise, you need to know whether the parabola like opening is up or down. If the opening is up, that is, find the minimum value. If middle1 > middle2, make left=middle1, and conversely, right=middle2
  3. Repeat step 2 until right - left = = certain accuracy

Depth first search

It is often called dfs(Depth first search), which searches for all possible solutions to a problem

Principle:

  1. Implement the recursive function dfs(), and take the parameters according to the actual situation

Example:

On the map
.s.#.
..#..
.#...
.#...
...e.
in s It's the entrance,e It's an exit,#It's an obstacle. Only one step at a time (up, down, left and right)
Find the shortest number of steps

Example code:

#include<iostream>
using namespace std;
//Minimum steps 
int minStep=0x7fffffff;
//Map 
char map[5][5]={'.','s','.','#','.','.','.','#','.','.','.','#','.','.','.','.','#','.','.','.','.','.','.','e','.'};
//Tag array for backtracking 
int sign[5][5]={0};
//dfs function 
void dfs(int step,int x,int y){
	if(map[y][x]=='e'){
		minStep=min(minStep,step);
	}
	//Up, down, left and right 
	int m[4][2]{0,1,0,-1,-1,0,1,0};
	for(int i = 0; i < 4; i++){
		int x1=x+m[i][0];
		int y1=y+m[i][1];
		if(x1>=0&&x1<5&&y1>=0&&y1<5&&map[x1][y1]!='#'&&sign[y1][x1]==0){
			sign[y1][x1]=1;
			dfs(step+1,x+m[i][0],y+m[i][1]);
			//to flash back 
			sign[y1][x1]=0;
		}
	}
}
int main(){
	int x,y;
	//Find the starting point 
	for(int i = 0; i < 5; i++){
		for(int j = 0; j < 5; j++){
			if(map[i][j]=='s'){
				x=j;
				y=i;
			}
		}
	}
	//dfs 
	dfs(0,x,y); 
	cout<<minStep<<endl;
}
/*
Output:
8

*/

Width first search

Often called bfs(Width first search), it is generally used for the shortest path problem

principle

  1. Implementation with data structure queue
  2. Search step by step and find the shortest path

Examples

Same question as above

Example code:

#include<iostream>
#include<queue>
using namespace std;
class node{
	public:
	int x,y,step;
};
int main(){
	//Map 
	char map[5][5]={'.','s','.','#','.','.','.','#','.','.','.','#','.','.','.','.','#','.','.','.','.','.','.','e','.'};
	//Tag array 
	int sign[5][5]={0};
	queue<node> q;
	node p;
	//Find the starting point 
	for(int i = 0; i < 5; i++){
		for(int j = 0; j < 5; j++){
			if(map[i][j]=='s'){
				p.x=j;
				p.y=i;
				p.step=0;
			}
		}
	}
	q.push(p);
	sign[p.y][p.x]=1; 
	//bfs
	while(!q.empty()){
		//Up, down, left and right 
		int m[4][2]{0,1,0,-1,-1,0,1,0};
		node d=q.front();
		q.pop();
		if(map[d.y][d.x]=='e'){
			cout<<d.step<<endl;
			break;
		}
		for(int i = 0; i < 4; i++){
			int x1=d.x+m[i][0];
			int y1=d.y+m[i][1];
			if(x1>=0&&x1<5&&y1>=0&&y1<5&&map[x1][y1]!='#'&&sign[y1][x1]==0){
				sign[y1][x1]=1;
				node e;
				e.x=x1;
				e.y=y1;
				e.step=d.step+1;
				q.push(e);
			}
		}
	}
	
}
/*
Output:
8

*/


dynamic programming

Dynamic programming, referred to as dp, reduces the calculation of repeated steps and greatly reduces the time complexity by maintaining a memorized dp array

Typical example:

Find the length of the longest increasing substring, such as f[8]={1, 4, 2, 3, 5, 8, 6, 7}. The answer is 6, {1, 2, 3, 5, 6, 7}

understand:

  1. Use dp[n] to store the maximum continuous substring length between 0 and n
  2. If dp[0]=1, because f [1] > F [0], dp[1]=max(dp[1],dp[0]+1)
  3. Continue with step 2 until you traverse the array

Example code:

#include<iostream>
#include<string> 
using namespace std;
int main(){
	int f[8]={1,4,2,3,5,8,6,7};
	int dp[8];
	string s[8];
	//Initialize dp[],s []
	for(int i=0;i<8;i++){
		dp[i]=1;
		s[i]+=to_string(f[i]);
	}
    //dp
	for(int i=0;i<8;i++){
		for(int j=0;j<i;j++){
			if(f[i]>f[j]){
				if(dp[i]<dp[j]+1){
					dp[i]=dp[j]+1;
					s[i]=s[j]+to_string(f[i]);
				}
			}
		}
	}
    int ma=0;
    for(int i=1;i<8;i++){
        if(dp[ma]<dp[i]){
            ma=i;
        }
    }
    cout<<dp[ma]<<endl;
    cout<<"{";
    for(int i=0;i<s[ma].size();i++){
        if(i!=0){
            cout<<',';
        }
        cout<<s[ma][i];
    }
    cout<<'}';
}

/*
Output:
6
{1,2,3,5,6,7}
*/

graph theory

minimum spanning tree

Minimum cost

sliding window

Topics: C++ Algorithm data structure