图的概念与遍历

图是一种较为复杂的数据结构,图中任意两个数据之间都有可能关联。

1.图的相关术语定义

图中的数据元素称为顶点,V是顶点的集合。从顶点a到顶点b有一条弧,a称为弧尾,b称为弧头,此时弧是有方向的,这样的图称为有向图。如果以无序对(a,b)代替这两个有序对,称a,b之间的一条边,而不是弧,这样的图称为无向图

用n表示图中的顶点个数,用e表示边或弧的数目。对无向图来说,n个顶点最多有n*(n-1) / 2条边,所以e的取值范围在0 - n*(n-1) / 2。当e取最大值时,此时的图称为完全图

同理,当e = n*(n - 1),称为有向完全图。e < nlogn称为稀疏图,否则称为稠密图

顶点的是以顶点v的相关连的边或弧的数目,入度是一顶点v为弧头的弧的个数,出度是以顶点v为弧尾的弧的个数。

从顶点a到顶点b的路径就是a到b的顶点序列,起点和重点相同的路径称为回路。序列中不重复出现顶点的路径称为简单路径

在无向图中,如果从顶点a到顶点b有路径,称a和b是连通的。如果图中任意两个顶点都是连通的,称为连通图连通分量指的是无向图中的极大连通子图。

在有向图中,如果任意两个顶点a,b有a到b的路径和b到a的路径,称为强连通图强连通分量是有向图中的极大强连通子图。

一个连通图的生成树是一个极小连通子图,包括所有顶点和n-1条边。如果一个有n个顶点的图,边e < n-1,则图是非连通的;如果e > n-1肯定有环,但是有n-1条边的图不一定有生成树。

2.图的存储结构

  • 数组表示法(邻接矩阵),通过一个n*n的二维数组来存放边,一个数组存放顶点。
  • 邻接表,一种链式存储方式,为每一个顶点建立一个单链表,用来表示依附于顶点v的边或以v为弧尾的弧。每个节点有3个域,邻接点域adjvex表示与v邻接的顶点在图中的位置,链域nextarc只想下一条边或弧的节点(依然是v的邻接点),数据域存储边或弧的信息info。每个链表上附上一个头结点,包括一个数据域data,存放顶点信息,和链域firstarc。表头结点一般用顺序存储,以达到随机访问。表节点 adjvex,nextarc,info;头结点 data,firstarc
  • 十字链表,为有向图的另一种存储方式,基于邻接表,在其基础做了下改造。首先是头结点 data,firstin,firstout。data同邻接表,firstin指向以顶点v为弧头的弧节点,firstout指向以v为弧尾的弧节点。弧节点 tailvex,headvex,hlink,tlink,info。info域表示弧的信息,尾域tailvex和头域headvex指向弧节点所关联的头结点位置。hlink指向弧头相同的下一个弧节点,tlink指向弧尾相同的下一个弧节点。
  • 邻接多重表,是无向图的另一种形式存储结构,由于邻接表中每一条边(a,b)都有两个顶点,分别在第a和第b个链表中,这个操作上带来不便。邻接多重表把边改了一下 mark,ivex,ilink,jvex,jlink,info。mark用来标记边是否被访问过,ivex表示顶点i的位置,ilink表示依附于顶点i的下一条边,jvex和jlink同理。

3.图的遍历

图的遍历有两种算法,DFS和BFS

DFS(深度优先搜索)

从图中选出一个顶点v出发,如果v的邻接点未被访问,设邻接点为w,访问w,然后再以w为起点做同样的方式访问。如果w的邻接点都被访问了,则返回上一顶点,也就是v,继续访问。

void DFSall(Graph *G){     //考虑到图不一定是连通的,所以需要一个函数来遍历每个节点,且初始化
    for(int i = 0; i < G -> vexnum; i++)
        visit[i] = 0;    
    for(int i = 0; i < G -> vexnum; i++)
        if(!visit[i]) DFS(G, i);
}

void DFS(Graph *G, int i){   //采用邻接表
    arcnode * p = G -> firstarc;
    visit[i] = 1;
    cout << i; //visit node i;
    while(p != NULL){
        if(!visit[p -> data])
            DFS(G, p -> data);
        p = p -> nextarc;
    }
}
邻接表有e条边,按边查询节点只需要遍历e次就可以找到所有节点,所以时间复杂度是O(n + e)。如果使用邻接矩阵,查询节点需要O(n^2)。

BFS(广度优先搜索)

从任一顶点v出发,如果v的邻接点未被访问,就访问该顶点。依次将顶点v的邻接点访问完后,将访问的几点存储起来,在取集合中的第一个顶点,按上述方式继续访问。

void BFS(Graph *G){    
    for(int i = 0; i < G -> vexnum; i++)
        visit[i] = 0; 
        queue q;
    for(int i = 0; i < G -> vexnum; i++){
        if(!visit[i]){
            visit[i] = 1;
            cout << i;
            q.push(i);
        while(!q.empty()){
            int t = q.top();
            for(arcnode *p = G -> head[t] -> firstarc; p != NULL; p = p -> nextarc){
                if(!visit[p -> data]){
                    visit[p -> data] = 1;
                    q.push(p -> data);
                    cout << p -> data;
                }
            }
            q.pop();
        }
    }
}

 时间复杂度同DFS 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对任意给定的(顶点数不小于20,边数不少于30,的类型可以是有向、无向、有向网、无向网),能够输入的顶点和边(或弧)的信息,并存储到相应存储结构(邻接矩阵、邻接表、十字链表、邻接多重表,任选其中两种类型),对自己所创建的完成以下操作: 对无向求每个顶点的度,或对有向求每个顶点的入度和出度(5分) 完成插入顶点和边(或弧)的功能(5分) 完成删除顶点和边(或弧)的功能(5分) 两种存储结构的转换(5分),如果其中一种存储结构为十字链表或邻接多重表则增加5分。 输出的深度优先遍历序列或广度优先遍历序列(5分) 求的深度优先或广度优先的生成树(或生成森林)(存储结构为孩子-兄弟链表),并对生成树进行遍历(15分) 判断的连通性,输出连通分量的个数(5分) 判断中是否存在环,无向5分,有向10分 给出顶点u和v,判断u到v是否存在路径(5分) 10、求顶点u到v的一条简单路径(10分) 11、求顶点u到v的所有简单路径(15分) 12、求顶点u到v的最短路径(10分) 13、求顶点u到其余各顶点的最短路径(15分) 14、求任两个顶点之间的最短路径(15分) 15、求最小生成树(15分) 16、对于有一个源点和一个汇点的有向网,求关键路径(20分) 编程环境可以是C、VC++、JAVA,每位同学从上述题目中选择100分的题目,注意,必须选择第1-6题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值