邻接表怎么写

  数据结构书上表示邻接表比较复杂,一般形式如下:

 1 struct ArcNode{            //边结点
 2     int adjvex;            //有向边的另一个邻接点的序号
 3     ArcNode *nextarc;    //指向下一个边结点的指针
 4 };
 5 
 6 struct VNode {            //顶点
 7     int data;            //顶点信息
 8     ArcNode *head1;        //出边表的表头指针
 9     ArcNode *head2;        //入边表的表头指针
10 };
11 
12 struct LGraph{            //图的邻接表储存结构
13     VNode vertes[MAXN];    //顶点数组
14     int vexnum,arcnum;    //顶点数和边(弧)数
15 };
16 LGraph lg;                //图(邻接表存储)

 输入n,m分别为图的顶点数目和边数

接下来m行输入分表输入一条边的起点和终点

输出每个顶点的出度和入度

  1 #include "iostream"
  2 #include "algorithm"
  3 #include "memory.h"
  4 #include "cmath"
  5 using namespace std;
  6 #define MAXN 111
  7 
  8 
  9 struct ArcNode{            //边结点
 10     int adjvex;            //有向边的另一个邻接点的序号
 11     ArcNode *nextarc;    //指向下一个边结点的指针
 12 };
 13 
 14 struct VNode {            //顶点
 15     int data;            //顶点信息
 16     ArcNode *head1;        //出边表的表头指针
 17     ArcNode *head2;        //入边表的表头指针
 18 };
 19 
 20 struct LGraph{            //图的邻接表储存结构
 21     VNode vertes[MAXN];    //顶点数组
 22     int vexnum,arcnum;    //顶点数和边(弧)数
 23 };
 24 LGraph lg;                //图(邻接表存储)
 25 
 26 
 27 void CreateLG()                                    //采用邻接表存储表示,构造有向图G
 28 {                                                
 29     int i = 0;                                    //循环变量
 30     ArcNode  *pi;                                //用来构造边链表的边结点指针
 31     int v1,v2;                                    //有向边的两个顶点
 32     //lg.vexnum = lg.arcnum = 0;                    
 33     //scanf("%d%d",&lg.vexnum,&lg.arcnum);
 34     for (int i = 0;i < lg.vexnum; ++ i)            //初始化表头指针为空
 35         lg.vertes[i].head1 = lg.vertes[i].head2 = NULL;
 36     for (int i = 0;i < lg.arcnum; ++ i) 
 37     {
 38         scanf("%d%d",&v1,&v2);                    //输入一条边的起点和终点
 39         v1--,v2--;
 40         pi = new ArcNode;
 41         pi -> adjvex = v2;
 42         pi -> nextarc = lg.vertes[v1].head1;    //插入链表
 43         lg.vertes[v1].head1 = pi;
 44         pi = new ArcNode;
 45         pi -> adjvex = v1;
 46         pi -> nextarc = lg.vertes[v2].head2;    //插入链表
 47         lg.vertes[v2].head2 = pi;
 48     }//end of for
 49 }//end of CreateLG
 50 
 51 void DeleteLG()
 52 {
 53     int i;
 54     ArcNode *pi;
 55     for (i = 0;i < lg.vexnum; ++ i)
 56     {
 57         pi = lg.vertes[i].head1;
 58         while (pi != NULL)
 59         {
 60             lg.vertes[i].head1 = pi -> nextarc;
 61             delete pi;
 62             pi = lg.vertes[i].head1;
 63         }
 64         pi = lg.vertes[i].head2;
 65         //释放第i个顶点去边表各边结点所占的存储空间
 66         while( pi != NULL) 
 67         {
 68             lg.vertes[i].head2 = pi->nextarc;
 69             delete pi;
 70             pi = lg.vertes[i].head2;
 71         }
 72     }
 73 }
 74 
 75 
 76 int main()
 77 {
 78     int i;                                        //循环变量
 79     int id,od;                                    //顶点的入度和出度
 80     ArcNode *pi;                                //用来遍历边链表的边结点指针
 81     while (1)
 82     {
 83         lg.vexnum = lg.arcnum = 0;
 84         scanf("%d%d",&lg.vexnum,&lg.arcnum);        
 85         //首先输入顶点个数和边数
 86         if (lg.vexnum == 0) break;                //输入数据结束
 87         CreateLG();                                //构造有向图的邻接表结构
 88         for (i = 0;i < lg.vexnum; ++ i)            //统计各顶点出度并输出
 89         {
 90             od = 0;
 91             pi = lg.vertes[i].head1;
 92             while (pi != NULL) 
 93             {
 94                 od++;
 95                 pi = pi -> nextarc;
 96             }
 97             if (i == 0) printf("%d",od);
 98             else printf(" %d",od);
 99         }
100         puts("");
101         for (i = 0;i < lg.vexnum; ++ i)            //统计各顶点入度并输出
102         {
103             id = 0;
104             pi = lg.vertes[i].head2;
105             while (pi != NULL)
106             {
107                 id++;
108                 pi = pi -> nextarc;
109             }
110             if (i == 0 ) printf("%d",id);
111             else printf(" %d",id);
112         }
113         puts("");
114         DeleteLG();                                //释放
115     }
116     return 0;
117 }
完整程序

 

    其实有种简洁且高效的表示形式:

 

 1 typedef struct
 2 {
 3     int to;
 4     int w;
 5     int next;
 6 }Edge;
 7 Edge e[MAX];
 8 int pre[MAX];
 9 
10 //初始化
11 memset(pre,-1,sizeof(pre));
12 
13 //输入
14 scanf("%d %d %d",&from,&to,&w1);
15 e[i].to = to; e[i].w = w1; e[i].next = pre[from]; pre[from] = i;
16 i++;

 

 

 

    上面这段代码中,边的结构体Edge由三个元素组成:弧头结点序号,边权值,下一条边的序号。e[i]指的是第i条边。pre[i]记录的是从当前输入的情况来看,序号为i的弧尾结点发出的第一条边的序号是pre[i]。

    这样,在操作某个结点发出的边时,可以像这么做:

/*now为弧尾结点序号,i为now所发出的边序号,adj为弧头结点序号,w为now-->adj这条边的权值*/
for(i = pre[now]; i != -1; i = edge[i].next)
{
     int adj = edge[i].to;
     int w = edge

[i].w;
     //do something...
}

  

 

    其实,对于哈希表这类的存储结构(链表法解决冲突),与图的邻接表类似,也可以用类似的表示方法:

 1 typedef struct  
 2 {  
 3     char e[11];    //value  
 4     char f[11];     //key  
 5     int next;        //下一个结果(hash冲突)  
 6 }Entry;  
 7 Entry entry[M];  
 8 int hashIndex[M];   //哈希值为M的结果集的第一个在entry中的序号。  
 9   
10 //输入:对key进行hash,  
11 sscanf(str,"%s %s",entry[i].e,entry[i].f);  
12 int hash = ELFHash(entry[i].f);  
13 entry[i].next = hashIndex[hash];  
14 hashIndex[hash] = i;  
15 i++;  
16   
17 //使用:  
18 for(int k = hashIndex[hash]; k; k = entry[k].next)  
19 {  
20     //do something..  
21 }  

 

以上转自http://yzmduncan.iteye.com/blog/883903

 

vector建立邻接表

建表
vetcor<int> G[maxn];

插入元素
void Insert()
{
	G[a].pushback(b);
}

遍历元素
void dfs()
{
	for (int i = 0;i < G[u].size();++ i)
		dfs(G[u][i]);
}

  

 

 

转载于:https://www.cnblogs.com/usedrosee/p/4185830.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是用邻接表实现的迪杰斯特拉算法模板: ```c++ #include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; // 最大顶点数 const int INF = 0x3f3f3f3f; // 无穷大 struct Edge { int to, w; Edge(int to, int w): to(to), w(w) {} }; vector<Edge> G[MAXN]; // 邻接表存图 int dis[MAXN]; // 从源点到各个顶点的最短距离 bool vis[MAXN]; // 记录每个顶点是否已经被访问过 void dijkstra(int s) { memset(dis, INF, sizeof(dis)); // 初始化最短距离为无穷大 memset(vis, false, sizeof(vis)); // 初始化所有顶点为未访问过 dis[s] = 0; // 源点到自己的距离为0 priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q; q.push(make_pair(0, s)); // 将源点加入到优先队列中 while (!q.empty()) { int u = q.top().second; // 取出当前距离最短的顶点 q.pop(); if (vis[u]) continue; // 如果该顶点已经访问过,则跳过 vis[u] = true; // 标记该顶点为已访问过 // 遍历与该顶点相邻的顶点 for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].to; // 相邻顶点的编号 int w = G[u][i].w; // 该边的权值 // 如果当前路径比已有的路径更短,则更新最短距离 if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; // 更新最短距离 q.push(make_pair(dis[v], v)); // 将更新后的顶点加入到优先队列中 } } } } int main() { int n, m, s; cin >> n >> m >> s; // 读入图的边 for (int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; G[u].push_back(Edge(v, w)); // 添加一条从u到v,权值为w的边 } dijkstra(s); // 进行最短路径计算 // 输出每个顶点到源点的最短距离 for (int i = 1; i <= n; i++) { if (dis[i] == INF) cout << "INF" << endl; else cout << dis[i] << endl; } return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值