c/c++常用板子(持续更新)

目录

输入汇总

 实现空格输入

文件读取

GCD+LCM+矩阵快速幂+素数大表

GCD 最大公约数 (logn)

 LCM最小公倍数

素数

素数打表

素数判断:6倍法

素数判断普通法

快速幂 

二分

 vector+set+map+string

vector

set (logn)

map(logn)

string

队列栈

 普通队列

 优先队列

sort+结构图

同余定理+逆元

逆元 

费马小定理 

 扩展欧几里得求逆元

递推求逆元(打表)

大数取模

大数输入输出及定义:__int128  b=p-1;   prin(b);  scan(t);

背包

 并查集 

 拓扑排序

 KMP

最短路

矩阵快速幂 

快读 

LCA

tarjan算法 




输入汇总

 实现空格输入

 
    //c语言
     int i=0;
	while(scanf("%c",&s[i])!=EOF){//多组输入
		if(s[i]!='\n')	++i;
        else {
            int len=i;
            i=0;
        }
    }
    
	int i=0;
	while(scanf("%c",&s[i])&&s[i]!='\n'){//单组输入
		++i;
	}
	int len=i;
	i=0;
	printf("%s\n",s);

	//c++实现string
    string t;
	getline(cin,t);
	cout<<t<<endl;
	//c++实现char 数组
    char s[N]
    cin.getline(s,N); 
	puts(s);
	printf("%d\n",strlen(s));

文件读取

freopen("A.txt","w",stdout);
fclose(stdout);
freopen("A.txt","r",stdin);
fclose(stdin);

GCD+LCM+矩阵快速幂+素数大表

GCD 最大公约数 (logn)

gcd(a,0) = a;

gcd (a,b) = gcd(b,a%b)

//gcd  
//gcd(a,0)=a;
int gcd(int a,int b){
	return b?gcd(b,a%b):a;
} 

 LCM最小公倍数

  lcm   (a,b) =      \frac{|a*b|}{gcd(a,b))}

素数

素数打表

比埃拉托斯特尼筛法

基本思想:素数的倍数一定不是素数 

​
//素数打表
prim[1]=1;
for(int i=2;i*i<TOP;++i)
	if(!prim[i])
		for(int j=i*i;j<TOP;j+=i)
			prim[j]=1; 

​

素数判断:6倍法

bool check(long long  n){
	if(n<=3) return n>1;
	if(n%6!=1&&n%6!=5) return false;	
	int t=sqrt(n);
	for(long long i=5;i<=t;i+=6){
		if(n%i==0||n%(i+2)==0) return false;
	}
	return true;
}

素数判断普通法

bool check isPrime(int n) {
    if (n <= 3) {
        return n > 1;
    }
    int sqrt = (int)sqrt(n);
    for (int i = 2; i <= sqrt; i++) {
        if(n % i == 0) {
            return false;
        }
    }
    return true;
}

快速幂 

typedef long long LL
//快速幂
LL pow_mod(LL a,LL n){
	LL res=1;
	while(n){
		if(n&1) res=res*a%mod;
		a=a*a%mod;
		n>>=1;
	}
	return res;
} 

二分

int l=1,r=n;
while (l <=r){
    int mid =(l+r )/2;
    if(a[mid ]== x){
        return mid ;
    } else if(a[mid]>x){
        r=mid -1;
    } else {
        l=mid +1;
    }
}
return -1;
upper_bound lower_bound

 vector+set+map+string

vector

vector <int >ve;
vector <node > ve;
vector <char > ve;
vector <int > V[ MAXN ]
ve. clear () 移除容器中所有数据。
ve. push_back (i) 存入数据i.
ve. seiz () 返回数组的大小。
ve. begin () 返回迭代器的第一个数据。
ve.end () 返回迭代器的最后一个数据。

set (logn)

set <int >se;
set <char > se;
set <int >S[ MAXN ]
se. begin () 返回指向第一个元素的迭代器
se. clear () 清除所有元素
se. count () 返回某个值元素的个数
se. empty () 如果集合为空,返回true
se.end () 返回指向最后一个元素之后的迭代器,不是最后一个元素
se. erase () 删除集合中的元素
se. find () 返回一个指向被查找到元素的迭代器
se. insert () 在集合中插入元素
se. max_size () 返回集合能容纳的元素的最大限值
se. size () 集合中元素的数目
se. swap () 交换两个集合变量
跌代器
for(set <int >:: iterator z = se. begin (); z != se.end ();
{ }

map(logn)

 map<int,int>mp;
 map<int,int>::iterator it;
for(it= mp.begin();it!=mp.end();++it)
it->first;
it->second;
----------
map<string,map<string,int> > mp;
mp[ss][s]+=x;
map<string,map<string,int> >::iterator it;
map<string,int>::iterator is;
for(it=mp.begin();it!=mp.end();++it){
	cout<<it->first<<endl;
	for(is= it->second.begin();is!=it->second.end();++is){
		cout<<is->first<<"("<<is->second<<")"<<endl;
	}		
}

string

队列栈

//代码实现(以int为例)
stack <int > sta ; 
sta . push ();
sta . pop ();
sta . top ();
sta . empty ();
//栈和队列的清空
while (! sta . empty ()) sta . pop ();

 普通队列

queue <int > que ;
que . push ();
//元素出栈(队列) 
que . pop ();
//查询栈顶元素  查询队列顶端元素
que . front ();
//判断栈(队列)是否为空
que . empty ();
//栈和队列的清空
while (! que . empty ()) que . pop ();

 优先队列

//代码实现
priority_queue <int > que ;
que . push ();
que . pop ();
que . top ();
que . empty ();
//优先级的设置
//结构体(和cmp类似)
struct node
{
    int x,y;
    friend bool operator<(node a , node b)//排序放在里面要写friend; 
    {
    if(a.x == b.x) return a.y>b.y;//Y从大到小       //排序与题意要相反 
    return a.x<b.x;//X从小到大; 
    }
};


priority_queue < node > que ;
----------------------------------------------
priority_queue <int , vector <int > , greater <int > > que ;// 小到大
priority_queue <int , vector <int > , less <int > > que ;

sort+结构体

//定义结构体
struct student {
    char name [20];
    int score ;
    int age ;
    int id ;
} s1 , s2 ;
--------------------------------------
struct node {
    int x , y ; char c [100];
    node & operator = ( const node & b ){
    y = b .y , x = b . x ;
    strcpy (c , b . c );
    return * this ; }
} a ;
node b ; b = a ;
 
------------------------------------
bool cmp ( node a , node b ){
    if ( a . x == b . x ){
        if ( a . y == b . y )
             return strcmp ( a .c , b . c ) <0;//字典序升序
        else return a . y < b . y ;//y升序
    } 
    return a . x < b . x ;//x升序
}
bool cmp (int a ,int b ){
    return a > b ;//降序
}
 
sort (a , a +n , cmp );

同余定理+逆元

逆元 

费马小定理 

/*
费马小定理:p是质数且gcd(a,p)==1
-> a^(p-1)%p=1
->a的逆元为 a^(p-2)
*/
long long quickpow(long long a,long long b){
	if(b<0) return 0;
	long long res=1;
	a%=mod;
	while(b){
		if(b&1) res=(res*a)%mod;
		a=(a*a)%mod;
		b>=1;
	}
	return res;
}
long long inv(long long a){
	return quickpow(a,mod-2);
}

 扩展欧几里得求逆元

/*
a*x%mod==1  ->a*x+m*y==1
(x+mod)%mod 即为a的逆元 
*/
long long exgcd(long long  a,long long b,long long &x,long long &y){
	if(!b){
		x=1;
		y=0;
		return a;
	}
	else{

		long long r=exgcd(b,a%b,y,x);
		y-=x*(a/b);
		return r;
	}
}
long long inv(long long a){
	long long x,y;
	long long d=exgcd(a,mod,x,y);
	return x=(x+mod)%mod;
}

递推求逆元(打表)

long long inv[N];
void prepare_inv(int n,int M){
	inv[1]=1;
	for(int i=2;i<=n;++i){
		inv[i]=(long long)(M-M/i)*inv[M%i]%M;
	}	
} 

大数取模

int len = a. length ();
int ans = 0;
for (int i = 0; i < len; i ++){
ans = (ans * 10 + a[i] - ’0’) mod b;
}

大数输入输出及定义:__int128  b=p-1;   prin(b);  scan(t);

void scan(__int128 &x)
{
	int f = 1;
	char ch;
	x = 0;
	if (ch = getchar() == '-') f = -1;
	else x += ch - '0';
	while ((ch == getchar()) >= '0' && ch <= '9')
		x = x * 10 + ch - '0';
	x *= f;
}
void print(__int128 x)
{
	if (!x) return ;
	if (x < 0) putchar('-'),x = -x;
	print(x / 10);
	putchar(x % 10 + '0');
}
__int128 vi(__int128  a,__int128  b){
	__int128 mod=b+2;
	__int128 res=1;
	while(b){
		if(b&1) res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}

背包

//01
int dp[MAXN];
for(int i=0;i<n;i++)
    for(int j=W;j>=w[i];j--)
        dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("%d\n",dp[W]);

//完全
int dp[MAXN];
for(int i=0;i<n;i++)
    for(int j=w[i];j<=W;j++)
        dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("%d\n",dp[W]);

//多重背包
for(int i=0;i<n;i++){
    int num=m[i];// 用来找a
    for(int k=1;num >0;k< <=1){
        int mul=min(k,num);
        for(int j=W;j>=w[i]*mul;j--){
            dp[j]=max(dp[j],dp[j-w[i]*mul]+v[i]*mul);
        }
        num -=mul;
    }
}
printf("%d\n",dp[W]);
//分组背包
这个问题变成了每组物品有若干种策略:是选择本组的某一件,还是一件都不选。
也就是说设F[k; v] 表示前k 组物品花费费用v 能取得的最大权值,则有:
F[k; v] = maxfF[k ? 1; v]; F[k ? 1; v ? Ci] +Wi j item i 2 group kg
使用一维数组的伪代码如下:
for k   1 to K
    for v   V to 0
        for all item i in group k
            F[v]   maxfF[v]; F[v ? Ci] +Wig
这里三层循环的顺序保证了每一组内的物品最多只有一个会被添加到背包中。

 并查集 

int find (int x)
{
    int r=x;
    while (pre[r ]!=r)
    r=pre[r ] ;
    return r ;
}


//路径压缩
int find (int x){
    int r=x;
    while ( pre[r ] != r )
        r=pre[r ];
    int i=x , j ;
    while ( i != r ){
        j = pre[ i ];
        pre [ i ]= r ;
        i=j;
    }
    return r ;
}

 拓扑排序

        queue<int>que;
        int inDegree[200000];
        int count = 0;
        int len = prerequisites.size();
        int u,v;
        memset(inDegree,0,sizeof(int)*numCourses);
        for(int i=0;i<len ; ++ i){
            // u= prerequisites[i][1];
            v = prerequisites[i][0];
            inDegree[v]++;//统计入度
        }
        for(int i=0;i<numCourses; ++i){
            if(inDegree[i]==0){
                que.push(i);//入度为0放在队列
            }
        }
        while(!que.empty()){
            u = que.front();//入度为0的节点U
            que.pop();
            count++;//用于计算最后有没有环
            for(int i=0;i<len;++i){
                if(prerequisites[i][1]==u){
                    v=prerequisites[i][0];//存在u->v的边,v的入度--
                    inDegree[v]--;
                    if(inDegree[v]==0){
                        que.push(v);
                    }
                }
            }
        }
        if(count<numCourses) return false;//有环
        return true;

 KMP


//n=strlen(s);
//m=strlen(t);
void getnex(){///nex[]数组获取 
	int i=1,j=0;
	nex[0]=0;
	while(i<n){
		if(t[i]==t[j])
		nex[i++]=++j;
		else if(!j)
		++i;
		else 
		j=nex[j-1];	
	}
}
int kmp(){//KMP函数 
	int i=0,j=0,ans=0;
	nex[0]=0;
	while(i<n){
		if(s[i]==t[j]){
			++i;
			++j;
		}
		else if(!j)
		++i;
		else
		j=nex[j-1];
		if(j==m){
			ans++;//记录循环次数 
			j=nex[j-1];//nex[]数组失配总是要返回最近的循环节,若返回j=0会超时 
			
		} 
	}
	return ans;
}
​
if(!nex[n-1]) //若nex[n-1] 为0,则说明没有循环,需要补充跟原串一样长度
	printf("%d\n",n);
else if(n%(n-nex[n-1])==0&&nex[n-1]!=0)//nex[n-1]回溯到最近的循环节,即跟【循环节后面不再循环的多余的串】一样的 最近位置
	printf("%d\n",0) ;       //n-nex[n-1]即为循环的串的长度,n/(n-nex[n-1]为循环几次,
else
	printf("%d\n",n-nex[n-1]-n%(n-nex[n-1]));//循环串长度-总长%循环串长度

​

最短路

const int M=3000;
const int N=508;
const int inf=100000008;
int head[N],d[N],top,vis[N],num[M<<1];
int  dis[N];
struct Edge{
	int to,val,next;
	Edge(){}
	Edge(int _to,int _val,int _next){
		to=_to;
		val=_val;
		next=_next;
	}
}edge[M<<1];
void inif(int n){
	for(int i=0;i<=n;++i) dis[i]=inf;
	memset(head,-1,sizeof(int)*(n+1));
	top=0;
	memset(vis,0,sizeof(int)*(n+1));
	memset(num,0,sizeof(num));
}
void add(int u,int v,int w){//建图
	edge[top]=Edge(v,w,head[u]);
	head[u]=top++;
}
int spfa(int st,int ed){
	dis[st]=0;
	queue<int>que;
	while(!que.empty() ) que.pop();
	que.push(st);
	num[st]++;
	vis[st]=1;
	bool fg=false;
	while(!que.empty() ){
		int u=que.front() ;
		que.pop() ;
		vis[u]=0;
		for(int i=head[u];~i;i=edge[i].next ){
			Edge e=edge[i];
			if(dis[e.to ]>dis[u]+e.val ){
				dis[e.to ]=dis[u]+e.val ;
				if(!vis[e.to ]){
					vis[e.to ]=1;
					que.push(e.to ); 
					num[e.to ]++;//记录节点跑的次数
					if(num[e.to ]>n){
						return 1;
					}
				}
			}	
		}		
	} 
	return 0;
}

矩阵快速幂 

矩阵快速幂
int f=2;
long long n,mod=1024;
struct node{
	LL materix[3][3];
};	
node mul(node a,node b){
	node res;
	memset(res.materix,0,sizeof(res.materix));
	for(int i=1;i<=f;++i){
		for(int j=1;j<=f;++j){
			for(int k=1;k<=f;++k){
				res.materix[i][j]=(res.materix[i][j]+a.materix[i][k]*b.materix[k][j])%mod;
			}
		}
	}
	return res;
}
node ksm(node a,long long b){
	node ans;
	memset(ans.materix,0,sizeof(ans.materix));
	for(int i=1;i<=f;++i) ans.materix[i][i]=1;
	while(b){
		if(b&1LL) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1LL;
	}
	return ans;
}

重载版
struct node{
	LL materix[7][7];
	void init(){
		memset(materix ,0,sizeof(materix ));
	}
	void init1(){
		memset(materix,0,sizeof(materix));
		for(int i=1;i<=ff;++i ) materix[i][i]=1;
	}
	node operator *(const node B) const{
			node C;
		C.init();
		for(int i=1;i<=ff;++i){
			for(int j=1;j<=ff;++j){
				for(int k=1;k<=ff;++k){
					C.materix[i][j]=(materix[i][k]*B.materix[k][j]+C.materix[i][j])%mod;
				}
			}
		}
		return C;
	}	
node ksm(node a,long long b){
	node ans;
	ans.init1() ;
	while(b){
		if(b&1LL) ans=ans*a;
		a=a*a;
		b>>=1;
	} 
	return ans;
}


快读 

//快读(数字)

int read()
{
	int ans = 0;
	char c;
	c = getchar();
	while (c >= '0' && c <= '9') ans= ans * 10 + c-'0',c=getchar();
	return ans;
}

LCA

//倍增法  
int n,m,root,h;//n个点,m次查询,root根节点,h最多跳h次
const int N=1000000,D=30;
int parent[D][N],depth[N];
int head[N],top;
struct Edge{
	int v,nex;
	Edge(){	};
	Edge(int _v,int _nex){
		v=_v;
		nex=_nex;
	}
}edge[N];
void add(int u,int v){
	edge[top]=Edge(v,head[u]);
	head[u]=top++;
}
void dfs(int v,int p,int d){
	parent[0][v]=p;
	depth[v]=d;
	for(int i=head[v] ;~i;i=edge[i].nex ){
		if(edge[i].v !=p) 
			dfs(edge[i].v ,v,d+1);
	}
}
void init(int V){
	dfs(root,-1,0);
	for(int k=0;k+1<h;++k){
		for(int v=1;v<=V;++v){
			if(parent[k][v]<0)
				parent[k+1][v]=-1;
			else
				parent[k+1][v]=parent[k][parent[k][v]];
		}
	}
}
int lca(int u,int v){
	if(depth[u]>depth[v]) swap(u,v);
	for(int k=0;k<h;++k){
		if((depth[v]-depth[u])>>k&1){
			v=parent[k][v];
		}
	}
	if(u==v) return u;
	for(int k=h-1;k>=0;--k){
		if(parent[k][u]!=parent[k][v]){
			u=parent[k][u];
			v=parent[k][v];
		}
	}
	return parent[0][u];
}
int main(){
	int u,v;
		while(~scanf("%d%d%d",&n,&m,&root)){
			memset(head,-1,sizeof(int)*(n+1));
		top=0;
		for(int i=1;i<n;++i){
			scanf("%d%d",&u,&v);
			add(u,v);
			add(v,u);
		}
		h=(int)log2(n);
		init(n);
		for(int i=0;i<m;++i){
			scanf("%d%d",&u,&v);
			printf("%d\n",lca(u,v));
		}	
		}
		
	
	return 0;
}
//tarjan求LCA
#include<cstdio>
#define N 1000050
struct hehe{
    int next;
    int to;
    int lca;
};
hehe edge[N];//树的链表
hehe qedge[N];//需要查询LCA的两节点的链表
int n,m,p,x,y;
int num_edge,num_qedge,head[N],qhead[N];
int father[N];
int visit[N];//判断是否被找过
void add_edge(int from,int to){//建立树的链表
    edge[++num_edge].next=head[from];
    edge[num_edge].to=to;
    head[from]=num_edge;
}
void add_qedge(int from,int to){//建立需要查询LCA的两节点的链表
    qedge[++num_qedge].next=qhead[from];
    qedge[num_qedge].to=to;
    qhead[from]=num_qedge;
}
int find(int z){//找爹函数
    if(father[z]!=z)
        father[z]=find(father[z]);
    return father[z];
}
void dfs(int x){//把整棵树的一部分看作以节点x为根节点的小树
    father[x]=x;//由于节点x被看作是根节点,所以把x的father设为它自己
    visit[x]=1;//标记为已被搜索过
    for(int k=head[x];k;k=edge[k].next)//遍历所有与x相连的节点
        if(!visit[edge[k].to]){//若未被搜索
            dfs(edge[k].to);//以该节点为根节点搞小树
            father[edge[k].to]=x;//把x的孩子节点的father重新设为x
        }
    for(int k=qhead[x];k;k=qedge[k].next)//搜索包含节点x的所有询问
        if(visit[qedge[k].to]){//如果另一节点已被搜索过
            qedge[k].lca=find(qedge[k].to);//把另一节点的祖先设为这两个节点的最近公共祖先
            if(k%2)//由于将每一组查询变为两组,所以2n-1和2n的结果是一样的
                qedge[k+1].lca=qedge[k].lca;
            else
                qedge[k-1].lca=qedge[k].lca;
        }
}
int main(){
    scanf("%d%d%d",&n,&m,&p);//输入节点数,查询数和根节点
    for(int i=1;i<n;++i){
        scanf("%d%d",&x,&y);//输入每条边
        add_edge(x,y);
        add_edge(y,x);
    }
    for(int i=1;i<=m;++i){
        scanf("%d%d",&x,&y);//输入每次查询,考虑(u,v)时若查找到u但v未被查找,所以将(u,v)(v,u)全部记录
        add_qedge(x,y);
        add_qedge(y,x);
    }
    
    dfs(p);//进入以p为根节点的树的深搜
    for(int i=1;i<=m;i++)
        printf("%d\n",qedge[i*2].lca);//两者结果一样,只输出一组即可
    return 0;
}

tarjan算法 

//tarjan

#define N 30100
//N为最大点数
#define M 150100
//M为最大边数
int n, m;//n m 为点数和边数
 
struct Edge{
	int from, to, nex;
	bool sign;//是否为桥
}edge[M<<1];
int head[N], edgenum;
void add(int u, int v){//边的起点和终点
	Edge E={u, v, head[u], false};
	edge[edgenum] = E;
	head[u] = edgenum++;
}
 
int DFN[N], Low[N], Stack[N], top, Time; 
//Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳)
int taj;//连通分支标号,从1开始
int Belong[N];//Belong[i] 表示i点属于的连通分支
bool Instack[N];
vector<int> bcc[N]; //标号从1开始
 
void tarjan(int u ,int fa){  
	DFN[u] = Low[u] = ++ Time ;  
	Stack[top ++ ] = u ;  
	Instack[u] = 1 ;  
	for (int i = head[u] ; ~i ; i = edge[i].nex ){  
		int v = edge[i].to ;  
		if(DFN[v] == -1)
		{  
			tarjan(v , u) ;  
			Low[u] = min(Low[u] ,Low[v]) ;
			if(DFN[u] < Low[v])
			{
				edge[i].sign = 1;//为割桥
			}
		}  
		else if(Instack[v]) Low[u] = min(Low[u] ,DFN[v]) ; 		
	}  
	if(Low[u] == DFN[u]){  
		int now;
		taj ++ ; bcc[taj].clear();
		do{
			now = Stack[-- top] ;  
			Instack[now] = 0 ; 
			Belong [now] = taj ;
			bcc[taj].push_back(now);
		}while(now != u) ;
	}
}
 
void tarjan_init(int all){
	memset(DFN, -1, sizeof(DFN));
	memset(Instack, 0, sizeof(Instack));
	top = Time = taj = 0;
	for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意开始点标!!!
}
vector<int>G[N];
int du[N];
void suodian(){
	memset(du, 0, sizeof(du));
	for(int i = 1; i <= taj; i++)G[i].clear();
	for(int i = 0; i < edgenum; i++){
		int u = Belong[edge[i].from], v = Belong[edge[i].to];
		if(u!=v) G[u].push_back(v), du[v]++;
	}
}
void init(){memset(head, -1, sizeof(head)); edgenum=0;}

  • 7
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: C/C++算法常用手册是程序员日常工作中不可或缺的工具书之一。该手册主要收录了程序员在开发过程中常用的算法,以及相应的代码实现。该手册涵盖了诸如数据结构、排序、查找、递归、贪心、动态规划、字符串等算法,帮助程序员快速掌握这些算法的基本原理和实现方式。简单地说,该手册将算法的核心原理和实现细节集中在了一起,兼顾了易懂性和实用性。 随着程序员需求的不断增加,该手册逐渐扩充了更多的算法类型。同时,该手册还根据算法的不同应用场景进行分类,方便程序员快速查找和使用。例如,程序员可以通过该手册快速了解不同数据结构的原理和实现方法,了解常见算法的时间复杂度和空间复杂度,还可以查找常见的实际问题中的算法实现方式。 总的来说,C/C++算法常用手册是程序员必备的工具之一,帮助程序员提高算法的实现能力和解决实际问题的能力,提高程序的效率和质量。 ### 回答2: C/C++常用算法手册是一本介绍计算机算法的参考手册,主要面向C/C++语言程序员。该手册总结了各种常用的算法,包括排序、查找、图论、字符串等。通过该手册的学习,可以让程序员更好地掌握C/C++编程的技巧和方法。 该手册中介绍了排序算法,包括冒泡排序、插入排序、选择排序、快速排序、归并排序等。对于不同的排序算法,手册详细介绍了它们的思路和实现方法,同时也对它们的时间复杂度和效率进行了分析和比较。 在查找方面,手册介绍了常用的顺序查找和二分查找算法,它们可以帮助程序员快速地定位和查找数据。 在图论和字符串方面,手册介绍了很多有用的算法,如最短路径算法、最小生成树算法、字符串匹配算法等。这些算法可以帮助程序员更好地解决实际问题。 总之,C/C++常用算法手册是一本非常实用和有价值的参考书,它可以让程序员掌握更多的C/C++算法技巧,提高程序员的编程能力和开发效率。 ### 回答3: C/C++ 常用算法手册是一本总结了 C/C++ 编程语言中常用的算法、数据结构、设计模式等知识的参考书籍。 相对于其他语言,C 和 C++ 语言有着更高的执行效率和更多的编程自由度,也因此被广泛应用于开发高性能、底层的软件程序。在这样的应用场景下,对算法和数据结构的掌握显得尤为重要。 C/C++ 常用算法手册涵盖了各种基础的算法和数据结构,比如排序、查找、链表、树等。同时,它也介绍了一些常用的高级算法,比如动态规划、贪心算法和回溯算法。 此外,该手册还详细说明了面向对象编程领域中常用的设计模式和其实现方式,例如工厂模式、装饰器模式等。 阅读 C/C++ 常用算法手册不但能够让读者掌握常用算法的实现方法,更能提高编程思维和技巧。另外,在实际应用中,编写高效的程序不仅需要算法的巧妙运用,更需要细致、严谨的代码风格和设计思路。此时,该手册中丰富的示例代码和编码规范性的讲解也能为读者提供很大的帮助。 总之,C/C++ 常用算法手册是一本既实用又深入的参考书,适合广大 C/C++ 开发者和算法学习者阅读。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值