邻接表怎么写

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

 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]);
}

  

 

 

posted @ 2014-12-25 23:24  UsedRose  阅读(1350)  评论(0编辑  收藏  举报