数据结构 - 图的存储结构表示及其遍历 (DFS && BFS)

1、邻接矩阵表示的图结构

/* 邻接矩阵表示的图结构 */
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;

typedef char VertexType;                //顶点类型应由用户定义
typedef int EdgeType;                   //边上的权值类型应由用户定义

#define MAXVEX  100             //最大顶点数,应由用户定义
#define INF   0               //用0来代表不存在该边
#define DEBUG

typedef struct
{
    VertexType vexs[MAXVEX];            //顶点表
    EdgeType   arc[MAXVEX][MAXVEX];         //邻接矩阵,可看作边
    int numVertexes, numEdges;      //图中当前的顶点数和边数
}Graph;

//定位
int locates(Graph *g, char ch)
{
    int i = 0;
    for(i = 0; i < g->numVertexes; i++)
    {
        if(g->vexs[i] == ch)
        {
            return i;
        }
    }
    if(i >= g->numVertexes)
    {
        return -1;
    }
}

//建立一个无向网图的邻接矩阵表示
void CreateGraph(Graph *g)
{
    int i, j, k, w;
    printf("输入顶点数和边数:\n");
    scanf("%d %d", &(g->numVertexes), &(g->numEdges));

    #ifdef DEBUG
    printf("%d %d\n", g->numVertexes, g->numEdges);
    #endif

	printf("输入顶点:\n");
    for(i = 0; i < g->numVertexes; i++)
    {
        g->vexs[i] = getchar();
        while(g->vexs[i] == '\n')
        {
            g->vexs[i] = getchar();
        }
    }

    #ifdef DEBUG
    for(i = 0; i < g->numVertexes; i++)
    {
        printf("%c ", g->vexs[i]);
    }
    printf("\n");
    #endif

    for(i = 0; i < g->numVertexes; i++)
    {
        for(j = 0; j < g->numVertexes; j++)
        {
            g->arc[i][j] = INF; //邻接矩阵初始化
        }
    }
    for(k = 0; k < g->numEdges; k++)
    {
        char p, q;
        printf("输入边(vi,vj)上的下标i,下标j和权值:\n");

        p = getchar();
        while(p == '\n')
        {
            p = getchar();
        }
        q = getchar();
        while(q == '\n')
        {
            q = getchar();
        }
        scanf("%d", &w);    

        int m = -1;
        int n = -1;
        m = locates(g, p);
        n = locates(g, q);
        if(n == -1 || m == -1)
        {
            fprintf(stderr, "there is no this vertex.\n");
            return;
        }
        //getchar();
        g->arc[m][n] = w;
        g->arc[n][m] = g->arc[m][n];  //因为是无向图,矩阵对称
    }
}

//打印图
void printGraph(Graph g)
{
    int i, j;
    for(i = 0; i < g.numVertexes; i++)
    {
        for(j = 0; j < g.numVertexes; j++)
        {
            printf("%6d ", g.arc[i][j]);
        }
        printf("\n");
    }
}

#define MAXVEX  100     //最大顶点数
bool visited[MAXVEX];        //访问标志数组
#define TRUE 1
#define FALSE 0

//邻接矩阵的深度优先递归算法
void DFS(Graph g, int i)
{
    int j;
    visited[i] = TRUE;
    printf("%c ", g.vexs[i]);                           //打印顶点,也可以其他操作
    for(j = 0; j < g.numVertexes; j++)
    {
        if(g.arc[i][j]!=0 && !visited[j])
        {
            DFS(g, j);                  //对为访问的邻接顶点递归调用
        }
    }
}

//邻接矩阵的深度遍历操作
void DFSTraverse(Graph g)
{
    int i;
    for(i = 0; i < g.numVertexes; i++)
    {
        visited[i] = FALSE;         //初始化所有顶点状态都是未访问过状态
    }
    for(i = 0; i < g.numVertexes; i++)
    {
        if(!visited[i])             //对未访问的顶点调用DFS,若是连通图,只会执行一次
        {
            DFS(g,i);
        }
    }
    printf("\n");
}

//邻接矩阵的广度遍历算法
void BFSTraverse(Graph g)
{
    int i, j;
    queue<int> q;
    for(i = 0; i < g.numVertexes; i++)
    {
        visited[i] = FALSE;
    }
    for(i = 0; i < g.numVertexes; i++)//对每个顶点做循环
    {
        if(!visited[i])               //若是未访问过
        {
            visited[i] = TRUE;
            printf("%c ", g.vexs[i]); //打印结点,也可以其他操作
            q.push(i);          //将此结点入队列
            while(!q.empty())
            {
                int m = q.front();
                q.pop();
                for(j = 0; j < g.numVertexes; j++)
                {
                    //判断其他顶点若与当前顶点存在边且未访问过
                    if(g.arc[m][j] != 0 && !visited[j])
                    {
                        visited[j] = TRUE;
                        printf("%c ", g.vexs[j]);
                        q.push(j);
                    }
                }
            }
        }
    }
    printf("\n");
}

int main(int argc, char **argv)
{
    Graph g;

    //邻接矩阵创建图
    CreateGraph(&g);
    printGraph(g);
    DFSTraverse(g);
    BFSTraverse(g);

    return 0;
}

2、邻接表表示的图结构

/* 邻接表表示的图结构 */
#include <cstdio>
#include <cstdlib>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;

#define MAXVEX  100     //最大顶点数
bool visited[MAXVEX];        //访问标志数组
#define TRUE 1
#define FALSE 0

#define DEBUG
#define MAXVEX 1000         //最大顶点数
typedef char VertexType;        //顶点类型应由用户定义
typedef int EdgeType;           //边上的权值类型应由用户定义

typedef struct EdgeNode         //边表结点
{
    int adjvex;         //邻接点域,存储该顶点对应的下标
    EdgeType weigth;        //用于存储权值,对于非网图可以不需要
    struct EdgeNode *next;      //链域,指向下一个邻接点
}EdgeNode;

typedef struct VertexNode       //顶点表结构
{
    VertexType data;        //顶点域,存储顶点信息
    EdgeNode *firstedge;        //边表头指针
}VertexNode, AdjList[MAXVEX];

typedef struct
{
    AdjList adjList;
    int numVertexes, numEdges;  //图中当前顶点数和边数
}GraphList;

int Locate(GraphList *g, char ch)
{
    int i;
    for(i = 0; i < MAXVEX; i++)
    {
        if(ch == g->adjList[i].data)
        {
            break;
        }
    }
    if(i >= MAXVEX)
    {
        fprintf(stderr,"there is no vertex.\n");
        return -1;
    }
    return i;
}

//建立图的邻接表结构
void CreateGraph(GraphList *g)
{
    int i, j, k;
    EdgeNode *e;
    EdgeNode *f;
    printf("输入顶点数和边数:\n");
    scanf("%d %d", &g->numVertexes, &g->numEdges);

    #ifdef DEBUG
    printf("%d %d\n", g->numVertexes, g->numEdges);
    #endif

    for(i = 0; i < g->numVertexes; i++)
    {
        printf("请输入顶点%d:\n", i);
        g->adjList[i].data = getchar();          //输入顶点信息
        g->adjList[i].firstedge = NULL;          //将边表置为空表
        while(g->adjList[i].data == '\n')
        {
            g->adjList[i].data = getchar();
        }
    }
    //建立边表
    for(k = 0; k < g->numEdges; k++)
    {
        printf("输入边(vi,vj)上的顶点序号:\n");
        char p, q;
        p = getchar();
        while(p == '\n')
        {
            p = getchar();
        }
        q = getchar();
        while(q == '\n')
        {
            q = getchar();
        }
        int m, n;
        m = Locate(g, p);
        n = Locate(g, q);
        if(m == -1 || n == -1)
        {
            return;
        }
        #ifdef DEBUG
        printf("p = %c\n", p);
        printf("q = %c\n", q);
        printf("m = %d\n", m);
        printf("n = %d\n", n);
        #endif

        //向内存申请空间,生成边表结点
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        if(e == NULL)
        {
            fprintf(stderr, "malloc() error.\n");
            return;
        }
        //邻接序号为j
        e->adjvex = n;
        //将e指针指向当前顶点指向的结构
        e->next = g->adjList[m].firstedge;
        //将当前顶点的指针指向e
        g->adjList[m].firstedge = e;

        f = (EdgeNode *)malloc(sizeof(EdgeNode));
        if(f == NULL)
        {
            fprintf(stderr, "malloc() error.\n");
            return;
        }
        f->adjvex = m;
        f->next = g->adjList[n].firstedge;
        g->adjList[n].firstedge = f;
    }
}

void printGraph(GraphList *g)
{
    int i = 0;
    #ifdef DEBUG
    printf("printGraph() start.\n");
    #endif

    while(g->adjList[i].firstedge != NULL && i < MAXVEX)
    {
        printf("顶点:%c  ", g->adjList[i].data);
        EdgeNode *e = NULL;
        e = g->adjList[i].firstedge;
        while(e != NULL)
        {
            printf("%d  ", e->adjvex);
            e = e->next;
        }
        i++;
        printf("\n");
    }
}

//邻接表的深度递归算法
void DFS(GraphList g, int i)
{
    EdgeNode *p;
    visited[i] = TRUE;
    printf("%c ", g.adjList[i].data);   //打印顶点,也可以其他操作
    p = g.adjList[i].firstedge;
    while(p)
    {
        if(!visited[p->adjvex])
        {
            DFS(g, p->adjvex);           //对访问的邻接顶点递归调用
        }
        p = p->next;
    }
}

//邻接表的深度遍历操作
void DFSTraverse(GraphList g)
{
    int i;
    for(i = 0; i < g.numVertexes; i++)
    {
        visited[i] = FALSE;
    }
    for(i = 0; i < g.numVertexes; i++)
    {
        if(!visited[i])
        {
            DFS(g, i);
        }
    }
    printf("\n");
} 

//邻接表的广度遍历算法
void BFSTraverse(GraphList g)
{
    int i;
    EdgeNode *p;
    queue<int> q;
    for(i = 0; i < g.numVertexes; i++)
    {
        visited[i] = FALSE;
    }
    for(i = 0; i < g.numVertexes; i++)
    {
        if(!visited[i])
        {
            visited[i] = TRUE;
            printf("%c ", g.adjList[i].data);   //打印顶点,也可以其他操作
            q.push(i);
            while(!q.empty())
            {
                int m;
                m = q.front();
                q.pop();
                p = g.adjList[m].firstedge;    // 找到当前顶点边表链表头指针
                while(p)
                {
                    if(!visited[p->adjvex])
                    {
                        visited[p->adjvex] = TRUE;
                        printf("%c ", g.adjList[p->adjvex].data);
                    	q.push(p->adjvex);
                    }
                    p = p->next;
                }
            }
        }
    }
    printf("\n");
} 

int main(int argc, char **argv)
{
    GraphList g;
    CreateGraph(&g);
    printGraph(&g);

    DFSTraverse(g);
    BFSTraverse(g);

    return 0;
}
时间: 2024-10-08 11:18:26

数据结构 - 图的存储结构表示及其遍历 (DFS && BFS)的相关文章

数据结构 - 图的存储结构

图的抽象数据类型定义 图是一种数据结构,加上一组基本操作就构成了图的抽象数据类型. 图的抽象数据类型定义如下: ADT Graph{ 数据对象V:具有相同特性的数据元素的集合,称为顶点集. 数据关系R:R={VR} VR={<v,w>|<v,w>| v,w?V∧p(v,w) ,<v,w>表示 从v到w的弧,P(v,w)定义了弧<v,w>的信息 } 基本操作P: Create_Graph() : 图的创建操作. 初始条件:无. 操作结果:生成一个没有顶点的空图

(转)数据结构之图(存储结构、遍历)

一.图的存储结构 1.1 邻接矩阵 图的邻接矩阵存储方式是用两个数组来表示图.一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息. 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 看一个实例,下图左就是一个无向图. 从上面可以看出,无向图的边数组是一个对称矩阵.所谓对称矩阵就是n阶矩阵的元满足aij = aji.即从矩阵的左上角到右下角的主对角线为轴,右上角的元和左下角相对应的元全都是相等的. 从这个矩阵中,很容易知道图中的信息. (1)要判断任意两顶点是否有

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

数据结构(五)图---图的存储结构5种

一:图的抽象数据类型 ADT 图(Graph) Data 顶点的有穷非空集合和边的集合 Operation CreateGraph(*G,V,VR):按照顶点集V和边弧集VR的定义构造图G DestroyGraph(*G):图G存在则销毁 LocateVex(G,u):若图G中存在顶点u,则返回图中位置 GetVex(G,v):返回图中顶点v的值 PutVex(G,v,value):将图G中顶点v赋值给value FirstAdjVex(G,*v):返回顶点v的一个邻接顶点,若顶点在G中无邻接顶

数据结构之图(一)图的存储结构

图的存储结构相对于线性表和树来说更为复杂,因为图中的顶点具有相对概念,没有固定的位置.那我们怎么存储图的数据结构呢?我们知道,图是由(V, E)来表示的,对于无向图来说,其中 V = (v0, v1, ... , vn),E = { (vi,vj) (0 <=  i, j <=  n且i 不等于j)},对于有向图,E = { < vi,vj > (0 <=  i, j <=  n且i 不等于j)}.V是顶点的集合,E是边的集合.所以我们只要把顶点和边的集合储存起来,那么

图的存储结构及遍历

一.图的存储结构 1.1 邻接矩阵 图的邻接矩阵存储方式是用两个数组来表示图.一个一维数组存储图中顶点信息,一个二维数组(邻接矩阵)存储图中的边或弧的信息. 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 看一个实例,下图左就是一个无向图. 从上面可以看出,无向图的边数组是一个对称矩阵.所谓对称矩阵就是n阶矩阵的元满足aij = aji.即从矩阵的左上角到右下角的主对角线为轴,右上角的元和左下角相对应的元全都是相等的. 从这个矩阵中,很容易知道图中的信息. (1)要判断任意两顶点是否有

【algo&amp;ds】5.图及其存储结构、遍历

1.什么是图 图表示"多对多"的关系 包含 一组顶点:通常用 V(Vertex)表示顶点集合 一组边:通常用 E(Edge)表示边的集合 边是顶点对:(v,w)∈ E,其中 v,w ∈ V ,v-w 有向边 <v,w> 表示从 v 指向 w 的边(单行线) v→w 不考虑重边和自回路 常见术语 无向图:图中所有的边无所谓方向 有向图:图中的边可能是双向,也可能是单向的,方向是很重要的 权值:给图中每条边赋予的值,可能有各种各样的现实意义 网络:带权值的图 邻接点:有边直接相

《大话数据结构》笔记(7-2)--图:存储结构

第七章  图 图的存储结构 图不能用简单的顺序存储结构来表示. 而多重链表的方式,即以一个数据域和多个指针域组成的结点表示图中的一个顶点,尽管可以实现图结构,但是会有问题,比如若各个顶点的度数相差很大,按度数最大的顶点设计结点结构会造成很多存储单元的浪费,而若按每个顶点自己的度数设计不同的顶点结构,又带来操作的不便. 对于图来说,如何对它实现物理存储是个难题.图有以下五种不同的存储结构. 邻接矩阵 图的邻接矩阵(Adjacency Matrix)存储方式使用过两个数组来表示图.一个一维数组存储图

图的存储结构(邻接矩阵)

图的存储结构(邻接矩阵) 让编程改变世界 Change the world by program 图的存储结构 图的存储结构相比较线性表与树来说就复杂很多. 我们回顾下,对于线性表来说,是一对一的关系,所以用数组或者链表均可简单存放.树结构是一对多的关系,所以我们要将数组和链表的特性结合在一起才能更好的存放. 那么我们的图,是多对多的情况,另外图上的任何一个顶点都可以被看作是第一个顶点,任一顶点的邻接点之间也不存在次序关系. 我们仔细观察以下几张图,然后深刻领悟一下: 因为任意两个顶点之间都可能