Graph theory 0x02 【连通性】

无向图的连通性

割点 桥

POJ1144 Network 判断割点

#include<iostream>
#include<stdio.h>
#include<set>
#include<cstdio>
#include<string.h>
#include<cstdlib>  
#include<stack>  
#include<queue>  
#include<algorithm>  
#include<cstring>  
#include<string>  
#include<cmath>  
#include<vector>  
#include<bitset>  
#include<list>  
#include<sstream>   
#include<map>
#include<functional> 
using namespace std;
#define fi first
#define se second
#define U unsigned
#define P std::pair<int,int>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl
const int N=103;
int ans,dfn,low[N],num[N];
bool iscut[N];
vector<int>G[N];

void init(int n){
	ans=dfn=0;
	memset(low,0,sizeof(low));
	memset(num,0,sizeof(num));
	memset(iscut,0,sizeof(iscut));
	FOR(i,1,n) G[i].clear();
}

void dfs(int u,int fa){
	low[u]=++dfn;num[u]=dfn;
	int child=0;
	for(int v=0;v<G[u].size();++v){      //用auto会CE
		int i=G[u][v];
		if(!num[i]){
			child++,dfs(i,u),low[u]=min(low[u],low[i]);
			if(low[i]>=num[u]&&u!=1) iscut[u]=1;
		}else if(num[i]<num[u]&&i!=fa) low[u]=min(low[u],num[i]);
	}
	if(u==1&&child>=2) iscut[u]=1;
}

int main(){
	int n;
	while(~scanf("%d",&n)&&n){
		init(n);
		int u,v;char ch;
		while(~scanf("%d",&u)&&u){
			ch=getchar();
			while(ch!='\n'){
				scanf("%d",&v);
				G[u].pb(v);G[v].pb(u);
				ch=getchar();
			}
		}
		dfs(1,-1);
		FOR(i,1,n) if(iscut[i]) ans++;
		printf("%d\n",ans);
	}
} 

双连通分量

POJ1523 SPF 判断割点+计算每个割点所分的点双连通分量个数

#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
const int N = 1e3+4;
int x,y,cnt,low[N],num[N],dfn,bcc[N];
bool iscut[N];
int rt=1;

vector<int>G[N];

void dfs(int u,int fa){
    bcc[u]=1;
    low[u]=num[u] = ++dfn;
    int child = 0;
    for(int i=0;i<G[u].size();++i){
        int v = G[u][i];
        if(!num[v]){
            child++;
            dfs(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v]>=num[u]&&u!=rt) {
                bcc[u]++;
                iscut[u]=1;
            }
        }else if(num[v]<num[u]&&v!=fa) low[u] = min(low[u],num[v]);
    }
    if(u==rt&&child>=2) {
            bcc[u] = child;
            iscut[1]=1;
    }
}

int main(){
    int c=0;
    while(~scanf("%d",&x)&&x){
        for(int i=1;i<N;++i) G[i].clear();
        memset(iscut,0,sizeof(iscut));
        memset(low,0,sizeof(low));
        memset(num,0,sizeof(num));
        dfn=0;
        cnt=0;
        scanf("%d",&y);
        G[x].push_back(y);
        G[y].push_back(x);
        while(~scanf("%d",&x)&&x){
            scanf("%d",&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        dfs(1,-1);
        for(int i=1;i<N;++i) if(iscut[i]) cnt++;
        printf("Network #%d\n",++c);
        if(cnt==0) {puts("  No SPF nodes\n");continue;}
        for(int i=1;i<=N;++i) if(iscut[i]){
            printf("  SPF node %d leaves %d subnets\n",i,bcc[i]);
        }
        puts("");
    }
}

POJ3352 Road Construction 边双连通分量

#include <cstdio>
#include <string.h>
#include <vector>
#include <iostream>
int n,r;
using namespace std;
const int N = 1e3+5;
int low[N],dfn;

vector<int> G[N];
int ans;

void init(){
    for(int i=1;i<=n;++i) G[i].clear();
    memset(low,0,sizeof(low));
    ans = 0;dfn=0;
}

void dfs(int u,int fa){
    low[u]=++dfn;
    for(int i=0;i<G[u].size();++i){
        int v = G[u][i];
        if(v==fa) continue;
        if(!low[v]) dfs(v,u);
        low[u] = min(low[u],low[v]);
    }
}

void tarjan(){
    int degree[N];
    memset(degree,0,sizeof(degree));
    for(int i=1;i<=n;++i)
        for(int j=0;j<G[i].size();++j)
            if(low[i]!=low[G[i][j]]) degree[low[i]]++;
    for(int i=1;i<=n;++i) if(degree[i]==1) ans++;
    ans=(ans+1)/2;
}

int main(){
    string str;
    int c = 0;
    while(~scanf("%d%d",&n,&r)){
        init();
        for(int i=1;i<=r;++i){
            int x,y;scanf("%d%d",&x,&y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        dfs(1,-1);
        tarjan();
        printf("%d\n",ans);
    }
}

HDU3394 Railway 得到点双连通分量+判断桥

/*
 *  分析可知,
 *  no need to build railways 必然是 bridge
 *  而 railways where clash might happen 必然存在于 点双连通分量 之中。
 *  为什么?因为BELONGS TO MORE THAN ONE TOURIST ROUTES。
 *  即,这条边是两个环的公共边。
 *  那么,这两个环构成一个BCC,(?)也构成一个边双连通分量啊?
 *  且,这个BCC的所有边都为railways where clash might happen。
 *  那么,反过来,怎样的BCC满足条件呢?
 *  发现,是边数目大于点数目的BCC满足条件。
 *  BCC只有两种:(1)边数目 == 点数目(即简单环);(2)边数目大于点数目。
 *  只用寻找所有BCC中,除开简单环的BCC的边的数目。
 *  找BCC使用tarjan算法。
 *
 */
#include <iostream>
#include <string.h>
#include <algorithm>
#include <vector>
#include <stack>

const int N = 1e4+5;
const int M = 2e5+6;
using namespace std;
int n,m,dfn;
int low[N],num[N],instack[N],inbcc[N];
vector<int>G[N];
stack<int>s;
vector<int>bcc;
int ans,ans2;

void solve(){
    // 处理当前得到的bcc。
    memset(inbcc,0,sizeof(inbcc));
    for(int i=0;i<bcc.size();++i) inbcc[bcc[i]] = 1;
    int cnt = 0;
    for(int i=0;i<bcc.size();++i){
        int u = bcc[i];
        for(int j=0;j<G[u].size();++j){
            int v = G[u][j];      // 处理bcc中所有点的所有的边
            if(inbcc[v]) cnt++;   // 在这个bcc内部的边
        }
    }
    cnt/=2;  // 两个点之间只有一条边,之前进行了两次运算
    if(cnt>bcc.size()) ans2+=cnt;
}

// 奇怪,没有考虑起点是割点的情况?
int tarjan(int u,int fa){
    // 记录边数
    low[u] = num[u] = ++dfn;
    s.push(u); instack[u] = 1;
    // 栈里放的是点
    for(int i=0;i<G[u].size();++i){
        int v = G[u][i];
        if(v==fa) continue;
        if(!low[v]) {
            tarjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v]>num[u]) ans++;   // 找到桥
            if(low[v]>=num[u]) {  // 找到割点,意即找到了BCC
                bcc.clear();  // 先清空
                while(1){
                    int x = s.top();s.pop(),instack[x] = 0;
                    bcc.push_back(x);
                    if(x==v) break;
                }
                bcc.push_back(u);
                solve();      // 处理当前BCC
            }
        }else if(instack[v]) low[u] = min(low[u],num[v]);  // 回退边
    }
}

void init(){
    memset(num,0,sizeof(num));
    memset(low,0,sizeof(low));
    memset(instack,0,sizeof(instack));
    dfn = ans = ans2 = 0;
    while(!s.empty()) s.pop();
    for(int i=0;i<=n;++i) G[i].clear();
}

int main() {
    while(~scanf("%d%d",&n,&m),n||m){
        init();
        for(int i=1;i<=m;++i){
            int u,v;scanf("%d%d",&u,&v);
            G[u].push_back(v),G[v].push_back(u);
        }
        // 把每一个连通块都dfs一遍。
        for(int i=0;i<n;++i) if(!num[i]) tarjan(i,-1);
        printf("%d %d\n",ans,ans2);
    }
}

HDU3749 Financial Crisis 判断连通性+点双连通分量

#include<bits/stdc++.h>
using namespace std;
const int N = 5004;
int n,m,q;
vector<int>G[N];
/*
 * 从每个点出发查找所在BCC,如果没有另一个点,但可达,即1.如果不可达,0.如果构成bcc,2
 * 这样显然会TLE. 于是我们考虑一次tarjan,储存每个点属于的bcc。 暴力u的bcc和v的bcc,如果有一样的,再判断这个bcc的size。
 * 连通性用并查集判断。
 */
int cnt;  // bcc 的编号
int dfn,low[N],num[N],fa[N],instk[N];

stack<int>s;
vector<int>bcc[N],in[N];
// 每一个点在哪几个bcc之中
// bcc有编号

void init(){
    while(!s.empty()) s.pop();
    cnt=dfn=0;
    for(int i=0;i<=n;++i)
        G[i].clear(),bcc[i].clear(),in[i].clear(),fa[i]=i,num[i]=0,low[i]=0,instk[i]=0;
}

int find(int x){
    return fa[x]=(fa[x]==x)?x:find(fa[x]);
}

void unite(int x,int y){
    x = find(x),y = find(y);
    if(x==y) return;
    fa[x] = y;
}

void tarjan(int u,int fa){
    low[u] = num[u] = ++dfn;
    s.push(u); instk[u] = 1;
    for(auto v:G[u]){
        if(v==fa) continue;
        if(!low[v]){
            tarjan(v,u);
            low[u] = min(low[u],low[v]);
            if(low[v]>=num[u]){
                cnt++;
                while(1){
                    int x = s.top();s.pop();instk[x] = 0;
                    bcc[cnt].push_back(x);
                    in[x].push_back(cnt);
                    if(x==v) break;
                }
                bcc[cnt].push_back(u);
                in[u].push_back(cnt);
            }
        }else if(instk[v]) low[u] = min(low[u],num[v]);
    }
}

int main(){
    int c = 0;
    while(~scanf("%d%d%d",&n,&m,&q),(n||m||q)){
        init();
        for(int i=1;i<=m;++i){
            int v,u;scanf("%d%d",&u,&v);
            unite(u,v);
            G[u].push_back(v),G[v].push_back(u);
        }
        for(int i=0;i<n;++i) if(i==fa[i]) tarjan(i,-1);
        printf("Case %d:\n",++c);
        for(int i=1;i<=q;++i){
            int u,v;scanf("%d%d",&u,&v);
            if(find(u)!=find(v)) puts("zero");
            else {
                int flg=0;
                for(auto i:in[u]){
                    for(auto j:in[v]){
                        if(i==j&&bcc[i].size()>2) {puts("two or more");flg=1;break;}
                    }
                    if(flg) break;
                }
                if(!flg) puts("one");
            }
        }
    }
}

HDU2460 Network 加边,多次询问桥的数目
给一张连通无向图。q次加边,求每次加边之后的桥的数目。

  • 思路:题目的意思是要求在原图中加边后桥的数量,首先我们可以通过Tarjan求边双连通分量,对于边(u,v),如果满足
    low[v]>dfn[u],则为桥,这样我们就可以知道图中桥的数目了。对于每一次query,可以考虑dfs树,树边肯定是桥,然后连
    上u,v这条边之后,就会形成一个环,这样环内的边就不是割边了,所以只要找到u,v的LCA,把这个路径上的桥标记为否就可以了。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+6;
int num[N],low[N],f[N],dfn,bridges,m,n,q,isbridge[N],mark[N];
vector<int>G[N]; // is bridge
void tarjan(int u,int fa){
    num[u] = low[u] = ++dfn;
    int first = 1;
    for(auto v:G[u]){
        if(v==fa&&first) {first = 0;continue;}  // multiple edges between two nodes
        if(!low[v]) f[v]=u,tarjan(v,u);
        low[u] = min(low[v],low[u]);
        if(low[v]>num[u]) {
            if(!isbridge[v]) bridges++;
            isbridge[v] = 1; // tree edge is bridge
        }
    }
}

void lca(int a,int b){
    while(num[a]>num[b]) {
        if(isbridge[a]) bridges--;
        isbridge[a] = 0,a=f[a];
    }
    while(num[b]>num[a]) {
        if(isbridge[b]) bridges--;
        isbridge[b] = 0,b=f[b];
    }
    while(a!=b) {
        if(isbridge[a]) bridges--;
        if(isbridge[b]) bridges--;
        isbridge[a] = isbridge[b] = 0;
        a=f[a],b=f[b];
    }
}
void init(){
    for(int i=1;i<=n;++i) isbridge[i]=low[i]=0,G[i].clear(),f[i]=i,mark[i]=0,num[i]=-1;
    bridges = 0,dfn = 0;
}
int main(){
    int c = 0;
    while(~scanf("%d%d",&n,&m),n||m){
        init();
        printf("Case %d:\n",++c);
        for(int i=1;i<=m;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        tarjan(1,-1);  // any two computers are connected in the initial network
        scanf("%d",&q);
        while(q--){
            int a,b;scanf("%d%d",&a,&b);
            lca(a,b);
            printf("%d\n",bridges);
        }
        printf("\n");
    }
}

HDU 4597 TWO NODES 无向图删两个点求最大连通分量数
思路:暴力枚举第一个删掉的点,重新建图,再对新图进行tarjan求每个点删去后的连通分量,注意,答案要加上删掉第一个点后图中的连通分量数目-1。

//
// Created by Lenovo on 2021/1/20.
//
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn = 5004;
int low[maxn],num[maxn],dfn,bcc[maxn],edgex[maxn],edgey[maxn];
bitset<maxn> iscut;
int rt;
vector<int> G[maxn];

void dfs(int u,int fa){
    bcc[u]=1;
    low[u]=num[u]=++dfn;
    int child = 0;
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(!num[v]){
            child++;
            dfs(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=num[u]&&u!=rt)
                bcc[u]++,iscut[u]=1;
        }else if(num[v]<num[u]&&v!=fa) low[u]=min(low[u],num[v]);
    }
    if(u==rt&&child>=2) bcc[u]=child,iscut[1]=1;
}

void init(){
    for(int i=1;i<=n;++i) G[i].clear();
    iscut.reset();
    for(int i=1;i<=n;++i) num[i]=0;
    for(int i=1;i<=n;++i) low[i]=0;
    for(int i=1;i<=n;++i) bcc[i]=0;
    dfn=0;
}

int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=m;++i){
            scanf("%d%d",&edgex[i],&edgey[i]);
            edgex[i]++,edgey[i]++;
        }

        for(int j=1;j<=m;++j){
            if(edgex[j]==1||edgey[j]==1) continue;
            G[edgex[j]].push_back(edgey[j]);
            G[edgey[j]].push_back(edgex[j]);
        }
        int ans=0;
        for(int i=1;i<=n;++i){
            // 枚举第一个点
            init();
            for(int j=1;j<=m;++j){
            // 重新建图
                if(edgex[j]==i||edgey[j]==i) continue;
                G[edgex[j]].push_back(edgey[j]);
                G[edgey[j]].push_back(edgex[j]);
            }
            int cnt=0;
            // 找bcc数目
            for(int j=1;j<=n;++j){
                if(j==i) continue;
                if(num[j]) continue;
                cnt++;
                rt=j;
                dfs(j,-1);
            }
            int cur=0;
            for(int j=1;j<=n;++j)
                if(iscut[j])
                    cur=max(bcc[j],cur);
           // cout<<"i == "<<i<<" cur == "<<cur<<" cnt== "<<cnt<<endl;
            ans=max(ans,cur+cnt-1);
        }
        if(ans==0) ans=1;
        cout<<ans<<endl;
    }
}

有向图的连通性

Kosaraju算法

求强连通分量的算法。用到了反图技术。
HDU 1269 迷宫城堡 求强连通分量是否=1

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10005;
// kosaraju
vector<int>G[maxn],rG[maxn];
vector<int>S;   // 存一次dfs1的结果:标记点的先后顺序
int vis[maxn],sccno[maxn],cnt;
void dfs1(int u){
    if(vis[u]) return;
    vis[u]=1;
    for(int i=0;i<G[u].size();++i) dfs1(G[u][i]);
    S.push_back(u);
}

void dfs2(int u){
    if(sccno[u]) return;
    sccno[u]=cnt;
    for(int i=0;i<rG[u].size();++i) dfs2(rG[u][i]);
}

void Kosaraju(int n){
    cnt=0;
    S.clear();
    memset(sccno,0,sizeof(sccno));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;++i) dfs1(i);  // 点的编号
    for(int i=n-1;i>=0;--i) if(!sccno[S[i]]){cnt++;dfs2(S[i]);}
}

int main(){
    int n,m,u,v;
    while(scanf("%d%d",&n,&m),n!=0||m!=0){
        for(int i=0;i<n;++i) {G[i].clear();rG[i].clear();}
        for(int i=0;i<m;++i){
            scanf("%d%d",&u,&v);
            G[u].push_back(v);    // 原图
            rG[v].push_back(u);    // 反图
        }
        Kosaraju(n);
        printf("%s\n",cnt==1?"Yes":"No");
    }
}

Tarjan算法

同上题


#include<bits/stdc++.h>
using namespace std;

const int N = 10003;
int cnt;
int low[N],num[N],dfn;
int sccno[N],top;
vector<int>G[N];
stack<int> s;

void dfs(int u){
    s.push(u);
    low[u]=num[u]=++dfn;
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(!num[v]){
            dfs(v);
            low[u]=min(low[v],low[u]);
        }
        else if(!sccno[v]) low[u]=min(low[u],num[v]);
    }
    if(low[u]==num[u]){
        cnt++;
        while(1){
            int v=s.top();
            s.pop();
            sccno[v]=cnt;
            if(u==v) break;
        }
    }
}

void Tarjan(int n){
    cnt=dfn=0;
    while(!s.empty()) s.pop();
    memset(sccno,0,sizeof(sccno));
    memset(num,0,sizeof(num));
    memset(low,0,sizeof(low));
    for(int i=1;i<=n;++i) if(!num[i]) dfs(i);
}

int main(){
    int n,m,u,v;
    while(scanf("%d%d",&n,&m),n!=0||m!=0){
        for(int i=1;i<=n;++i) G[i].clear();
        for(int i=0;i<m;++i){
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
        }
        Tarjan(n);
        printf("%s",cnt==1?"Yes":"No");
    }
}

HDU 1827 Summer Holiday tarjan缩点
tarjan算法自带缩点到一个个scc中,所以不用dsu。
分为一个个scc后,如果开始是连通图,那么现在便成为一棵树。

#include<bits/stdc++.h>
using namespace std;
// 先缩点,再找in为0的scc。
const int maxn = 2003;
int fee[maxn],cnt,dfn,low[maxn],num[maxn],sccno[maxn],mn[maxn];
vector<int> G[maxn];
stack<int> s;

void dfs(int u){
    s.push(u);
    low[u]=num[u]=++dfn;
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(!num[v]){
            dfs(v);
            low[u]=min(low[v],low[u]);
        }else if(!sccno[v])
            low[u]=min(low[u],num[v]);
    }
    if(low[u]==num[u]){
        cnt++;
        while(1){
            int v=s.top();s.pop();
            sccno[v]=cnt;
            mn[cnt]=min(mn[cnt],fee[v]);
            if(u==v) break;
        }
    }
}

void Tarjan(int n){
    cnt=dfn=0;
    memset(sccno,0,sizeof(sccno));
    memset(num,0,sizeof(num));
    memset(mn,0x7f7f7f7f,sizeof(mn));
    for(int i=1;i<=n;++i) if(!num[i]) dfs(i);
}
int in[maxn];
int ans,res;
void Toposort(int n){
    memset(in,0,sizeof(in));
    for(int i=1;i<=n;++i){
        for(int j=0;j<G[i].size();++j){
            int v=G[i][j];
            int si=sccno[i],sv=sccno[v];
            if(si==sv) continue;
            in[sv]++;
        }
    }
    ans=0,res=0;
    for(int i=1;i<=cnt;++i) if(!in[i]){
        ans+=mn[i];
        res++;
    }
}

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;++i) G[i].clear();
        for(int i=1;i<=n;++i) scanf("%d",&fee[i]);
        for(int i=1;i<=m;++i) {
            int a,b;scanf("%d%d",&a,&b);
            G[a].push_back(b);
        }
        Tarjan(n);
        Toposort(n);
        cout<<res<<" "<<ans<<endl;
    }
}

HDU 3072 Intelligence System tarjan缩点+贪心
选最小cost的路径,走遍所有点。scc内部cost不计。
每个点一定会被访问到。那么选择每个点入度中最小cost的那条入度,父亲一定也会被访问到。

//
// Created by Artis on 2021/1/21.
//
#include<bits/stdc++.h>
using namespace std;
const int maxn = 50003;
vector<pair<int,int> >G[maxn];
int fee[maxn],cnt,dfn,low[maxn],num[maxn],sccno[maxn];
stack<int>s;

void dfs(int u){
    s.push(u);
    low[u]=num[u]=++dfn;
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i].first;
        if(!num[v]){
            dfs(v);
            low[u]=min(low[v],low[u]);
        }else if(!sccno[v])
            low[u]=min(low[u],num[v]);
    }
    if(low[u]==num[u]){
        cnt++;
        while(1){
            int v=s.top();s.pop();
            sccno[v]=cnt;
            if(u==v) break;
        }
    }
}

void Tarjan(int n){
    memset(num,0,sizeof(num));
    memset(sccno,0,sizeof(sccno));
    memset(fee,0x7f7f7f7f,sizeof(fee));
    dfn=cnt=0;
    dfs(1);
    for(int i=1;i<=n;++i){
        for(int j=0;j<G[i].size();++j){
            int v=G[i][j].first,val=G[i][j].second;
            if(sccno[i]==sccno[v]) continue;
            fee[sccno[v]]=min(fee[sccno[v]],val);
        }
    }
    int ans=0;
    for(int i=1;i<=cnt;++i) {
        if(i==sccno[1]) continue;
        ans+=fee[i];
    }
    cout<<ans<<endl;
}


int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        for(int i=1;i<=n;++i) G[i].clear();
        for(int i=1;i<=m;++i){
            int u,v,val;scanf("%d%d%d",&u,&v,&val);
            G[++u].push_back(make_pair(++v,val));
        }
        Tarjan(n);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值