关于这个是不是叫链式前向星的东西

链式前向星?

先拿这个最简单的题来说吧  (明白代码核心怎么来的就好)

题目

模拟链表。在图论题编程中,通常要运用邻接链表数据结构。由于动态指针比静态的数组的存取慢,很多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;从小到大就<. (具体过程本宝宝也不是很清楚,以后了解再补充)

 

posted @ 2021-09-12 10:53  ツキユレ  阅读(35)  评论(0编辑  收藏  举报