图的建立和遍历两种方法(转载)

/************************************************************************/
/* 图的邻接表存储结构                                                    */
/************************************************************************/
#ifdef _MSC_VER
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#endif

#include <stdio.h>
#define MaxVertexNum 100
#define QueueSize 30
typedef enum{ FALSE, TRUE }Boolean;
Boolean visited[MaxVertexNum];
typedef char VertexType;
typedef int EdgeType;
typedef struct node     //边表结点
{
    int adjvex;         //邻接点域
    struct node *next;  //域链
    //若是要表示边上的权,则应增加一个数据域
}EdgeNode;
typedef struct vnode    //顶点边结点
{
    VertexType vertex;  //顶点域
    EdgeNode *firstedge;//边表头指针
}VertexNode;
typedef VertexNode AdjList[MaxVertexNum];   //AdjList是邻接表类型
typedef struct
{
    AdjList adjlist;    //邻接表
    int n, e;           //图中当前顶点数和边数
}ALGraph;               //对于简单的应用,无须定义此类型,可直接使用AdjList类型
/************************************************************************/
/* 建立无向图的邻接表算法                                               */
/************************************************************************/
void CreateGraphAL(ALGraph *G)
{
    int i, j, k;
    EdgeNode * s;
    printf("请输入顶点数和边数(输入格式为:顶点数,边数):\n");
    scanf("%d,%d", &(G->n), &(G->e));       // 读入顶点数和边数   
    printf("请输入顶点信息(输入格式为:顶点号<CR>)每个顶点以回车作为结束:\n");
    for (i = 0; i < G->n; i++)              // 立有n个顶点的顶点表   
    {
        scanf("\n%c", &(G->adjlist[i].vertex)); // 读入顶点信息   
        G->adjlist[i].firstedge = NULL;            // 点的边表头指针设为空   
    }
    printf("请输入边的信息(输入格式为:i,j):\n");
    for (k = 0; k < G->e; k++)      // 建立边表   
    {
        scanf("\n%d,%d", &i, &j); // 读入边<Vi,Vj>的顶点对应序号   
        s = new EdgeNode;         // 生成新边表结点s   
        s->adjvex = j;         // 邻接点序号为j   
        s->next = G->adjlist[i].firstedge; // 将新边表结点s插入到顶点Vi的边表头部   
        G->adjlist[i].firstedge = s;
        s = new EdgeNode;
        s->adjvex = i;
        s->next = G->adjlist[j].firstedge;
        G->adjlist[j].firstedge = s;
    }
}
/************************************************************************/
/* 深度优先遍历                                                         */
/************************************************************************/
void DFS(ALGraph *G, int i)
{
    //以vi为出发点对邻接表表示的图G进行深度优先搜索
    EdgeNode *p;
    printf("visit vertex:%c\n", G->adjlist[i].vertex);  // 访问顶点vi
    visited[i] = TRUE;              //标记vi已访问
    p = G->adjlist[i].firstedge;        //取vi边表的头指针
    while (p)
    {                               //依次搜索vi的邻接点vj,这里j=p->adjvex
        if (!visited[p->adjvex])    //若vi尚未被访问
            DFS(G, p->adjvex);      //则以Vj为出发点向纵深搜索
        p = p->next;                     //找vi的下一邻接点
    }
}
void DFSTraverseM(ALGraph *G)
{
    int i;
    for (i = 0; i < G->n; i++)
        visited[i] = FALSE;
    for (i = 0; i < G->n; i++)
        if (!visited[i])
            DFS(G, i);
}
/************************************************************************/
/* 广度优先遍历                                                         */
/************************************************************************/
typedef struct
{
    int front;
    int rear;
    int count;
    int data[QueueSize];
}CirQueue;
void InitQueue(CirQueue *Q)
{
    Q->front = Q->rear = 0;
    Q->count = 0;
}
int QueueEmpty(CirQueue *Q)
{
    return Q->count == 0;
}
int QueueFull(CirQueue *Q)
{
    return Q->count == QueueSize;
}
void EnQueue(CirQueue *Q, int x)
{
    if (QueueFull(Q))
        printf("Queue overflow");
    else
    {
        Q->count++;
        Q->data[Q->rear] = x;
        Q->rear = (Q->rear + 1) % QueueSize;
    }
}
int DeQueue(CirQueue *Q)
{
    int temp;
    if (QueueEmpty(Q))
    {
        printf("Queue underflow");
        return NULL;
    }
    else
    {
        temp = Q->data[Q->front];
        Q->count--;
        Q->front = (Q->front + 1) % QueueSize;
        return temp;
    }
}
void BFS(ALGraph*G, int k)
{   // 以vk为源点对用邻接表表示的图G进行广度优先搜索
    int i;
    CirQueue Q;             //须将队列定义中DataType改为int
    EdgeNode *p;
    InitQueue(&Q);          //队列初始化
    printf("visit vertex:%c\n", G->adjlist[k].vertex);      //访问源点vk
    visited[k] = TRUE;
    EnQueue(&Q, k);         //vk已访问,将其人队。(实际上是将其序号人队)
    while (!QueueEmpty(&Q))
    {                                   //队非空则执行
        i = DeQueue(&Q);                    //相当于vi出队
        p = G->adjlist[i].firstedge;        //取vi的边表头指针
        while (p)
        {                               //依次搜索vi的邻接点vj(令p->adjvex=j)
            if (!visited[p->adjvex])
            {                           //若vj未访问过
                printf("visit vertex:%c\n", G->adjlist[p->adjvex].vertex);      //访问vj
                visited[p->adjvex] = TRUE;
                EnQueue(&Q, p->adjvex); //访问过的vj人队
            }
            p = p->next;                    //找vi的下一邻接点
        }
    }
}
void BFSTraverseM(ALGraph *G)
{
    int i;
    for (i = 0; i < G->n; i++)
        visited[i] = FALSE;
    for (i = 0; i < G->n; i++)
        if (!visited[i])
            BFS(G, i);
}
/************************************************************************/
/* 打印邻接表                                                     */
/************************************************************************/
void PrintfGraphAL(ALGraph *G)
{
    for (int i = 0; i < G->n; i++)
    {
        printf("vertex:%c", G->adjlist[i].vertex);
        EdgeNode *p = G->adjlist[i].firstedge;
        while (p)
        {
            printf("→:%d", p->adjvex);
            p = p->next;
        }
        printf("\n");
    }
}
/************************************************************************/
/* 删除邻接表                                                     */
/************************************************************************/
void DeleteGraphAL(ALGraph *G)
{
    for (int i = 0; i < G->n; i++)
    {
        EdgeNode *q;
        EdgeNode *p = G->adjlist[i].firstedge;
        while (p)
        {
            q = p;
            p = p->next;
            delete q;
        }
        G->adjlist[i].firstedge = NULL;
    }
}
/************************************************************************/
/* 主函数调用                                                           */
/************************************************************************/
int main()
{
#ifdef _MSC_VER
    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
    _CrtDumpMemoryLeaks();
#endif

ALGraph G;
    CreateGraphAL(&G);
    printf("深度优先遍历:\n");
    DFSTraverseM(&G);
    printf("广度优先遍历:\n");
    BFSTraverseM(&G);
    printf("邻接表:\n");
    PrintfGraphAL(&G);
    DeleteGraphAL(&G);

return 0;
}

测试结果如下:
 NormalText Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    
    
请输入顶点数和边数(输入格式为:顶点数,边数):
8,9
请输入顶点信息(输入格式为:顶点号<CR>)每个顶点以回车作为结束:
A
B
C
D
E
F
G
H
请输入边的信息(输入格式为:i,j):
0,1
0,2
1,3
1,4
2,5
2,6
3,7
4,7
5,6
深度优先遍历:
visit vertex:A
visit vertex:C
visit vertex:G
visit vertex:F
visit vertex:B
visit vertex:E
visit vertex:H
visit vertex:D
广度优先遍历:
visit vertex:A
visit vertex:C
visit vertex:B
visit vertex:G
visit vertex:F
visit vertex:E
visit vertex:D
visit vertex:H
邻接表:
vertex:A→:2→:1
vertex:B→:4→:3→:0
vertex:C→:6→:5→:0
vertex:D→:7→:1
vertex:E→:7→:1
vertex:F→:6→:2
vertex:G→:5→:2
vertex:H→:4→:3
请按任意键继续. . .

时间: 2024-10-20 15:19:25

图的建立和遍历两种方法(转载)的相关文章

有向无环图(DAG)拓扑排序的两种方法

如下图的DAG: 第一种: (1)从AOV网中选择一个没有前驱的顶点并且输出它: (2)从AOV网中删除该顶点,并且上去所有该顶点为尾的弧: (3)重复上述两步,直到全部顶点都被输出,或者AOV网中不存在没有前驱的顶点. 第二种: 使用深度优先搜索(DFS),并标记每一个节点的第一次访问(pre)和最后一次访问时间(post),最后post的逆序就是DAG的拓扑排序,其实也是节点在进行DFS搜索时,出栈的逆序就是拓扑排序. 拓扑序列的结果有: (1) c++,高等数学,离散数学,数据结构,概率论

遍历Map的两种方法

MAP集合遍历的两种方法 1.使用keyset()获得Map中的的key ,然后使用get方法获得这个key对应的value; 示例:Map<String,Integer> map = new HashMap<String,Integer>(); map.put("张三",15); map.put("李四",16); map.put("王五",17); Set ss = map.keyset(); Iterator<

CSS实现背景图尺寸不随浏览器大小而变化的两种方法

一些网站的首页背景图尺寸不随浏览器缩放而变化,本例使用CSS 实现背景图尺寸不随浏览器缩放而变化,方法一. 把图片作为background,方法二使用img标签.喜欢的朋友可以看看 一些网站的首页背景图尺寸不随浏览器缩放而变化,例如百度个人版的首页,缩放后背景图的尺寸并不改变:  再比如花瓣网( huaban.com ): 现在用CSS来实现这一效果. 首 先需要一张足够大尺寸的图片,上图百度背景图的尺寸为1600*1000px( 图片地址:http://4.su.bdimg.com/skin/

python遍历数组的两种方法的代码

工作过程中,把开发过程中较好的一些内容段备份一下,下面内容是关于python遍历数组的两种方法的内容,希望对小伙伴有用途. colours = ["red","green","blue"] for colour in colours: print colour # red # green # blue 下面的方法可以先获得数组的长度,然后根据索引号遍历数组,同时输出索引号 colours = ["red","gree

基于邻接矩阵和邻接表的两种方法实现无向图的BFS和DFS

广度优先搜索(Breadth-First-Search)和深度优先搜索(Deep-First-Search)是搜索策略中最经常用到的两种方法,特别常用于图的搜索. BFS的思想: 从一个图的某一个顶点V0出发,首先访问和V0相邻的且未被访问过的顶点V1.V2.--Vn,然后依次访问与V1.V2--Vn相邻且未被访问的顶点.如此继续,找到所要找的顶点或者遍历完整个图.我们采用队列来存储访问过的节点. DFS的思想: 深度优先搜索所遵循的策略就是尽可能"深"的在图中进行搜索,对于图中某一个

SQL Server 批量插入数据的两种方法

在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍SQL Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters). 运行下面的脚本,建立测试数据库和表值参数. [c-sharp] view plaincopy --Create DataBase create database BulkTestDB; go use BulkTes

自制按钮图标的两种方法: image sprite和svg字体文件

用image sprite和svg字体文件这两种方法,都能够极大地减少小图形文件的数量, 从而减少服务器请求和带宽需求.提高网页的响应速度. 一.建立SVG字体文件 iconmoon 是一个在线工具,可以上传自己的SVG格式的图标文件,也可以从其中选择已有的图标, 定制出自己的字体文件.下载的结果包括了字体文件和一个简单的demo.html, (https://icomoon.io/app/#/select), (类似工具: https://glyphter.com) 二.用 image spr

HTTPS的证书未经权威机构认证的情况下,访问HTTPS站点的两种方法

注意一下文章中提到的jsse在jdk1.4以后已经集成了,不必纠结. 摘 要 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问.但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点.本文在简要介绍JSSE的基础上提出了两种解决该问题的方法. 引言 过去的十几年,网络上已经积累了大量的Web应用.如今,无论是整合原有的Web应用系统,还是进行新的Web开发,都要求通过编程来访问某些Web页面.传统的方法是使

两种方法DatagridView轻松导入到Excel

众所周知,DatagridView控件来处理表各类数据真的是"简单.方便.疗效快",因此备受广大民众喜爱.今天我们再来继续探讨一下有关它和Excel的"姊妹情深". 几乎没有人不对Excel不了解,但要说熟悉和认识透彻恐怕我们还远远没有做到(这是题外之言),重点还是Excel的强大数据处理能力带给我们的便利,所以把DatagridView数据表变为老少皆宜的Excel表格就显得尤为重要了. 其实这一转换也很简单,下面就为大家介绍下两种方法,轻松连接"姊妹情