数据结构--图

文章目录

图结构:多对多

无论多么复杂的图都是由顶点和边构成的,采用形式化的定义。G由两个集合V(vertex)和E(edge)组成记为G=(V,E).其中V是顶点的有限集合,记为V(G),E是连接V中两个不同顶点(顶点对)的边的有限集合.记为E(G)。

可以用字母或自然数来标识图中的顶点.这里约定用i(0≤i≤n- 1)表示第i个顶点的编号,其中n为图中顶点的个数。当E(G)为空集时,则图G只有顶点,没有边。

在图G中,如果表示边的顶点对(或序偶)是有序的,则称G为有向图(digraph)。在有向图中代表边的顶点对用尖括号括起来,用于表示条有向边,如<i,j>表示从顶点i到顶点j的一条边,可见<i,j>和<j,i>是两条不同的边。

如果在图G中,若<i,j>∈E(G必有<j,i>∈E(G).即E(G)是对称的则用(i,j)代替这两个顶点对,表示顶点i和顶点j的一条无向边,称G为无向图。

无向图可以看成是有向图的特例。
数据结构--图

图的基本术语

1、邻接点,相关边
对于无向图G=(V,E),若边(Vi,Vj)∈E,则称Vi和Vj互为
邻接点(Adjacetnt)而边(Vi,Vj)则是与顶点Vi和Vj相关联的边。
对于有向图G=(V,E),若弧<Vi,,Vj>∈A,则称顶点Vi邻接到顶点Vj,顶点Vj
邻接自顶点Vi,,而弧<Vi,Vj>和顶点Vi,,Vj相关联。
2、 完全图
在无向图中,若每对顶点之间都连有一条边,
则称该图为无向完全图。n个顶点的图具有n(n-1)
条弧的有向图称为有向完全图。
3、
子图
对于图G=(V,E),G’=(V’,E’),若有V’属于V,E’属于E,则称图G’是G的子图。
4、
顶点的度

顶点的度是图中和Vi相关联的边的数目,记为TD(Vi)
有向图:
入度(indegree)指以Vi为头的弧的数目,记为ID(Vi):
出度(outdegree)指以Vi为尾的弧的数目,记为OD(Vi);
故顶点的度TD(Vi)=ID(Vi)+0D(Vi)
有n个顶点,
e条边的弧的图中,有2e=ΣTD(Vi)

5、
路径,回路
无向图G=(V,E)中,路径是从顶点V到顶点V’间的一个顶点序列
(V=ViO,Vi1,Vi2,Vi3,……Vim=V’)其中,(Vij-1,Vij)
E 属于(1≤j≤m)
若是有向图,路径也是有向的。
路径的起点和终点相同(即V=V)
则称此路径为回路或环(cycle)
简单路径:
序列中顶点不重复出现的路径。
6、连通 强连通
若从顶点Vi到Vj(i≠j)有路径,则称Vi和Vj是连通的。
如果无向图中任意两个顶点Vi和Vj都是连通的,则称该无向图是连通图。
无向图中极大连通子图称为连通分量。
在有向图中,,若任意两个顶点Vi和Vj都连通,即从Vi到Vj和Vj到Vi都有路径,则称该有向图为强连通图。
有向图中的极大连通子图称为该有向图的连通分量。

7、
权、网
在一个图的每条边或弧上,标上具有某种含义的数值,这种与图的边相关的数值称为权(weight)
这种边或弧上带权的图称为网(network)

图的存储结构

邻接矩阵表示法

定义:
设G=(V,E)是N个顶点的图(顶点序号依次为0,1,2,3,……n-1)。
G的邻接矩阵是表示图中顶点之间相邻关系的n阶方阵。
适用于有向图和无向图。

性质

对于无向图:
1.邻接矩阵:一定是对称的
2.第i行(或第i列)非0元素个数正好是第i个顶点的度TD(Vi)
对于有向图:
1.邻接矩阵不一定对称
2.第i行非0元素的个数是顶点i的出度OD(Vi)
第i列非0元素的个数是顶点i的入度ID(Vi)

#define VEXTYPE int
#define ADJTYPE int
#define MAXLEN 40
typedef struct
{LOXTYPE
vex[MAXLEN] ;
//顶点信息
ADJTYPE
arc[MAXLEN][MAXLEN] //邻接矩阵相邻关系
int vexnum , arcnum ;//顶点数,边数
int kind ;
MGRAPH

邻接表表示法

邻接链表是图的一种链式存储结构。适用于无向图,也适于有向图。在邻接链表中,对图中的每个顶点建立一个单链表。
单链表中的结点称为表结点。单链表有一个表头结点。
结构为:Vertex + Link
★其中,Vertex域存放图中顶点Vi的信息,Link域为指针,指向对应的单链表中的结点。
邻接链表将所有表头结点组成一个二维数组

#define MAXLEN 40
typedef struct node3
{int adjvex;
struct node3 *next;
}EDGENODE;
typedef struct
{ VEXTYPE vertex;
EDGENODE *link;
}VEXNODE;
typedef struct
{VEXNODE adjlist[MAXLEN];
int vexnum,arcnum;
int kind;
}ADJGRAPH;

图的遍历

图的遍历:
从图中某顶点出发对图中每个顶点访问一次,而且只访问一次,这一过程称为图的遍历。
图的遍历方法有:深度优先搜索遍历和广度优先搜索遍历。

DFS

深度优先搜索属于图算法的一种,英文缩写为DFS。其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
过程:
a.访问顶点v;
b.依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
c.若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。

int visited[MAX]={0};
void DFS(AdjGraph *G,int v)
{
   ArcNode *p;
   visited[v]=1;
   printf("%d",v);
   p=G->adjlist[v].firstarc;
   while(p!=NULL)
   {       
        if(visited[p->adjvex]==0)
                DFS(G,p->adjvex);
        p=p->nextarc;
   }
}

BFS

广度优先算法则是从根节点开始一层一层的进行遍历,只有完全遍历完一层所有的节点后才会进入下一层的遍历。
一般过程:
创建一个队列并将根将节点插入到个队列中,此时根节点作为第一层,总共有一个节点。
在每层遍历开始前,队列的长度就是这一层的节点总数,我们记录下这个数目然后不断地将节点出队进行遍历并将其子节点插入到队列中,同时每遍历一个节点就将前面记录的数字减一。
当数字为零时,表明这一层的所有节点已经遍历完了,返回第二步进行迭代遍历直到队列为空为止。

void BFS(AdjGraph *G,int v)
{
      int w,j;ArcNode *p;
      SqQueue *qu;
      InitQueue(qu);
      int visited[MAX];
      for(i=0;i<G->n;i++)
      visited[i]=0;
      cout<<v;
      visited[v]=1;
      enQueue(qu,v);
      while(!QueueEmpty(qu))
      {      deQueue(qu,w);
               p=G->adjlist[w].firstarc;
               while(p!=NULL)
               {
                       if(visited[p->adjvex]==0)
                       {
                               cout<<p->adjvex;
                               visited[p->adjvex]=1;
                               enQueue(qu,p->adjvex);
                        }
                        p=p->nextarc;
                }
      }
       cout<<endl;
}
上一篇:threeJS-geo加载地形的实际应用


下一篇:epoll学习代码