关于这个是不是叫链式前向星的东西
链式前向星?
先拿这个最简单的题来说吧 (明白代码核心怎么来的就好)
题目
模拟链表。在图论题编程中,通常要运用邻接链表数据结构。由于动态指针比静态的数组的存取慢,很多OI选手就用数组模拟指针。现在就来学习一下这种方法的编程。 有N个点,编号从1到N。有M条边,每条边用连接的2个顶点表示,如:(3,8),表示顶点3和8之间的边(无向边)。请输出每个顶点通过边相邻的顶点。
输入格式:
第1行,N和M两个整数,N范围在[1…5000],M范围在[1…100000];下面有M行,每行两个整数,表示一条边。
输出格式:
N行,第i行的第1个数k表示有多少边和i号顶点相连,后面有k个数,表示哪k个顶点和i连接为一条边。
样例
输入样例:
5 6
1 3
2 4
1 4
2 3
3 5
2 5
输出样例:
2 4 3
3 5 3 4
3 5 2 1
2 1 2
2 2 3
过程推理
核心代码:
1 struct node{ 2 int u,v,nxt; 3 }e[maxn]; 4 int cnt,head[maxn],k[maxn]; 5 void add(int u,int v){ 6 ++cnt; 7 e[cnt].u=u; 8 e[cnt].v=v; 9 e[cnt].nxt=head[u]; 10 head[u]=cnt; 11 k[u]++; 12 }
for(int i=1,u,v;i<=m;i++){ cin>>u>>v; add(u,v); add(v,u); }
上面是核心代码和代码实现的过程,现在我们来推一下:
- 1.用e[cnt].u和e[cnt].v来表示互相连接的两个点,如果在for循环里只打add(u,v),那么就是个有向图,即由u指向v,再反过来一下就是无向图啦;
-
2.那么e[cnt].nxt和head[u]指的是什么呢?如果head[u]记录的是这个点出现的位置(即cnt),e[cnt].nxt就可以表示为这个点上一次出现的位置,以便查找,因为e[cnt].nxt是等于head[u]=cnt(上一次出现时的cnt),再看代码:
1 for(int j=head[i];j;j=e[j].nxt){ 2 cout<<e[j].v<<" "; 3 }
这是什么意思呢?就拿题目样例中的第二个点(2)说,一开始j=head[2]=11;j;j=e[j].nxt=e[11].nxt=7(上一次head[2]出现的地方);这个时候就把这次与2连接的点输出(输出e[11].v=5),那然后呢,最后j=e[11].nxt=7了呀,在进行下一次循环,j=7;j;j=e[7].nxt=3;这个时候输出e[7].v=3,这次完了之后j=e[7].nxt=3;j;j=e[3].nxt=0;输出e[3].v=4.那这就完成了。你问我为啥完成了?因为j等于0啦
- 3.再提一句,k[u]是来记录u出现了多少次的,每次出现就加一嘛(貌似不太用)。
代码实现
1 #include<bits/stdc++.h> 2 #define maxn 2100010 3 using namespace std; 4 struct node{ 5 int u,v,nxt;//先不要看注释(侦(zhu)探(shi)已死) 6 }e[maxn]; 7 int cnt,head[maxn],k[maxn]; 8 void add(int u,int v){ 9 ++cnt; //记录编号 10 e[cnt].u=u; //u,v为两个端点,e[cnt].u表示这个点 11 e[cnt].v=v; //e[cnt].v表示与这个点相连的点 12 e[cnt].nxt=head[u]; //e[cnt].nxt记录端点,即上一次出现的地方 13 head[u]=cnt; //head[u]记录这个点出现的位置 14 k[u]++; //k[u]记录这个点出现的次数,即这个点连接的点数 15 } 16 int main(){ 17 int n,m; 18 cin>>n>>m; 19 for(int i=1,u,v;i<=m;i++){ 20 cin>>u>>v; 21 add(u,v); 22 add(v,u); //无向图 23 } 24 for(int i=1;i<=n;i++){ 25 cout<<k[i]<<" "; //输出每个点出现的次数,即连接的点数 26 for(int j=head[i];j;j=e[j].nxt){ 27 /*j从这个点最后出现的位置head[i]开始,输出这次与这个点相连的点,然后j=e[j].nxt 28 是上一次出现的位置,而一直循环,直到j等于零*/ 29 cout<<e[j].v<<" "; 30 } 31 cout<<endl; 32 } 33 return 0; 34 }
哎呀wc,这么多了!害,就到这吧,有漏洞以后刷刷题再补漏洞吧(~~本人已废~~)……
插一句题外话
结构体比较大小可以用快速排序(sort),具体如下:
1 struct node{ 2 string s; 3 int a; 4 }e[maxn]; 5 bool cmp(node x,node y){ 6 return x.a>y.a; 7 }
1 sort(e+1,e+n+1,cmp);
这只是其中一种排序方法,这个cmp有多种写法,也可以直接写到结构体里面去,但格式不太一样.
1 bool cmp(node x,node y){ 2 return x.a>y.a; 3 }
如上面的代码,如果要从大到小,就写x.a>y.a;从小到大就<. (具体过程本宝宝也不是很清楚,以后了解再补充)