图的深度优先和广度优先遍历

目录

  • 5. 图
    • 5.1 图的抽象数据结构
    • 5.2 图的表示方法
    • 5.3 图的定义与术语总结
    • 5.4 邻接矩阵
      • 5.4.1 邻接矩阵存储的图深度优先遍历
      • 5.4.2 邻接矩阵存储的图广度优先遍历
    • 5.5 临接表表示法
      • 5.5.1 临接表表示的图深度优先遍历
      • 5.5.2 临接表表示的图广度优先遍历

5. 图

5.1 图的抽象数据结构

ADT Graph
Data
顶点的有穷非空集合和边的集合
Operation
	CreateGraph(*G, V, VR) 按照顶点集和边弧集VR的定义构造图G
	DestoryGraph 图G存在则销毁
	LocateVex(G, u) 若存在顶点u,则返回图中的位置
	GetVex(G, u),返回顶点u的值
	InsertVex(*G, v) 在图中新增顶点v
	DeleteVex(*G, v) 删除图中顶点v和相关弧
	InsertArc(*G, v, w) 在图中增添弧<v, w>
	DFSTraverse(G) 深度优先遍历,在遍历过程中对每个顶点调用
	HFSTraverse(G) 对图中进行广度优先遍历,在遍历过程中对每个顶点调用
endADT

5.2 图的表示方法

  1. 图的表示方法中,不允许出现图的节点为空的情况!
  2. 无向图的表示方法G = (V1, {E1}) V1 = {A,B,C,D} , E1 = {(A,B), (B,C), (C,D),
    (D, A)} 无向图使用小括号()
  3. 有向图的表示方法G = (V2, {E2}) V1= {A,B,C,D}, E2 = {, , ,
    } 有向图使用<>,同时第一个元素表示弧尾,第二个元素表示弧首

5.3 图的定义与术语总结

  1. 图分为无向图和有向图,无向图有顶点和边构成,有向图由顶点和弧构成,弧有弧尾和弧头之分
  2. 任意两个顶点之间都存在边叫做完全图,有向的叫有向完全图,若无重复的边或顶点到自身,叫做简单图
  3. 图中顶点之间有邻接点、依附的概念,无向图顶点的边数叫做度,有向图顶点分为入度和出度
  4. 简单路径:路径最终回到起点且不重复,若任意两顶点都是连通的,是连通图,有向则称为强连通图
  5. 生成树:无向图中连通N个顶点的n-1条边叫做生成树

5.4 邻接矩阵

#include 
#include 

typedef char VertexType;
typedef int EdgeType;

#define MAXVEX 100
#define INFINITY 65535

typedef struct {
    VertexType vexs[MAXVEX];
    EdgeType arc[MAXVEX][MAXVEX];
    int numVertexes, numEdges;
} MGraph;

void CreateGraph(MGraph *G)
{
    int i, j, k, w;
    printf("输入顶点数和边数:\n");
    scanf("%d %d", &G->numVertexes, &G->numEdges);
    for (i = 0; i < G->numVertexes; i++) {
        scanf(&G->vexs[i]);
    }
    for (i = 0; i < G->numVertexes; i++) {
        for (j = 0; j < G->numVertexes; j++) {
            G->arc[i][j] = INFINITY;
        }
    }
    for (k = 0; k < G->numEdges; k++) {
        printf("输入边的上下标\n");
        scanf("%d %d %d", &i, &j, &w);
        G->arc[i][j] = w;
        G->arc[j][i] = G->arc[i][j];
    }
}

5.4.1 邻接矩阵存储的图深度优先遍历

typedef int Boolean;
Boolean visited[MAXVEX];
/* 递归方法实现深度优先遍历 */
void DFS(MGraph G, int i)
{
    int j;
    visited[i] = true;
    printf("%d", G.vexs[i]);
    for (j = 0; j < G.numVertexes; j++) {
        if (G.arc[i][j] == 1 && !visited[j]) {
            DFS(G, j);
        }
    }
}

void DFSTraverse(MGraph G)
{
    int i, j;
    memset(visited, 0, sizeof(visited[0])*MAXVEX);
    for (i = 0; i < G.numVertexes; i++) {
        if (!visited[i]) {
            DFS(G, i);
        }
    }
}

/* 非递归用栈实现深度优先遍历 */
void DFS(MGraph G, int i)
{
    int j;
    stack s;
    visited[i] = 1;
    printf("%c", G.vexs[i]);
    Push(&s, i);
    while (!StackEmpty(s)) {
        i = s.top()
        for (j = 0; j < G.numVertexes; j++) {
            if (G.arc[i][j] == 1 && !visited[j]) {
                visited[j] = 1;
                printf("%c", G.vexs[j]);
                Push(&s, j);
                break;
            }
        }
        if (j == G.numVertexes) {
            Pop(&s);
        }
    }
}

void DFSTraverse(MGraph G)
{
    int i;
    for (i = 0; i < G.numVertexes; i++) {
        visited[i] = 0;
    }
    for (i = 0; i < G.numVertexes; i++) {
        if (!visited[i]) {
            DFS(G, i);
        }
    }
}

5.4.2 邻接矩阵存储的图广度优先遍历

/* 用队列实现广度优先遍历 */
void BFSTraverse(MGraph G)
{
    int i, j;
    Queue Q;
    for (i = 0; i < G.numVertexes; i++) {
        visited[i] = FALSE;
    }
    InitQueue(&Q);
    for (i = 0; i < G.numVertexes; i++) {
        if (!visited[i]) {
            visited[i] = true;
            printf("%c", G.vexs[i]);
            EnQueue(&G, i);
            while (!QueueEmpty(&G)) {
                DEQueue(&G, &i);
                for (j = 0; j < G.numVertexes; j++) {
                    if (!visited[j] && G.arc[i][j] == 1) {
                        visited[j] = true;
                        printf("%c", G.vexs[j]);
                        EnQueue(&G, j);
                    }
                }
            }
        }
    }
}

5.5 临接表表示法

#include 
#include 

#define MAXVEX 100

typedef char VertexType;
typedef int EdgeType;

typedef struct EdgeNode {
    int adjvex;
    EdgeType weight;
    struct EdgeNode *next;
} EdgeNode;

typedef struct VertexNode {
    VertexType data;
    struct EdgeNode *firstEdge;
} VertexNode, AdjList[MAXVEX];

typedef struct {
    AdjList adjList;
    int numVertexes, numEdges;
} GraphAdjList;

void CreateGraph(GraphAdjList *G)
{
    int i, j, k;
    EdgeNode *e;
    printf("输入定点数和边数:\n");
    scanf("%d %d", &G->numVertexes, &G->numEdges);
    for (i = 0; i < G->numVertexes; i++) {
        scanf(&G->adjList[i].data);
        G->adjList[i].firstEdge = NULL;
    }

    for (k = 0; k < G->numEdges; k++) {
        printf("输入边上的顶点号\n");
        scanf("%d %d", &i, &j);
        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        e->adjvex = j;
        e->next = G->adjList[i].firstEdge;
        G->adjList[i].firstEdge = e;

        e = (EdgeNode *)malloc(sizeof(EdgeNode));
        e->adjvex = i;
        e->next = G->adjList[j].firstEdge;;
        G->adjList[j].firstEdge = e;
    }
}

5.5.1 临接表表示的图深度优先遍历

typedef int Boolean;
Boolean visited[MAXVEX];

/* 递归方法实现深度优先遍历 */
void DFS(GraphAdjList *GL, int i)
{
    EdgeNode *p;
    visited[i] = true;
    printf("%c", GL->adjList[i].data);
    p = GL->adjList[i].firstEdge;
    while (p) {
        if (!visited[p->adjvex]) {
            DFS(GL, p->adjvex);
        }
        p = p->next
    }
}

void DFSTraverse(GraphAdjList *GL)
{
    int i;
    for (i = 0; i < GL->numVertexes; i++) {
        visited[i] = FALSE;
    }

    for (i = 0; i < GL->numVertexes; i++) {
        if (!visited[i]) {
            DFS(GL, i);
        }
    }
}


/* 非递归用栈实现深度优先遍历 */
void DFS(GraphAdjList *GL, int i)
{
    stack s;
    EdgeNode *p;
    printf("%c", GL->adjList[i].data);
    visited[i] = 1;
    Push(&s, i)
    while (!StackEmpty(s)) {
        p = GL->adjList[s.top()].firstEdge;
        while (p) {
            if (!visited[p->adjvex]) {
                visited[p->adjvex] = 1;
                printf("%c", GL->adjList[p->adjvex].data);
                Push(&s, p->adjvex);
                p = GL->adjList[p->adjvex].firstEdge;
            } else {
                p = p->next;
            }
        }
        if (p == NULL) {
            Pop(&s);
        }
    }
}

void DFSTraverse(GraphAdjList *GL)
{
    int i;
    for (i = 0; i < GL->numVertexes; i++) {
        visited[i] = 0;
    }
    for (i = 0; i < GL->numVertexes; i++) {
        if (!visited[i]) {
            DFS(GL, i);
        }
    }
}

5.5.2 临接表表示的图广度优先遍历

/* 用队列实现广度优先遍历 */
void BFSTraverse(GraphAdjList *GL)
{
    int i;
    EdgeNode *p;
    Queue Q;
    for (i = 0; i < GL->numVertexes; i++) {
        visited[i] = FALSE;
    }
    InitQueue(&Q);
    for (i = 0; i < GL->numVertexes; i++) {
        if (!visited[i]) {
            visited[i] = true;
            printf("%c", GL->adjList[i].data);
            EnQueue(&G, i);
            while (!QueueEmpty(&G)) {
                DEQueue(&G, i);
                p = GL->adjList[i].firstEdge;
                while (p) {
                    if (!visited[p->adjvex]) {
                        visited[p->adjvex] = true;
                        printf("%c", GL->adjList[p->adjvex].data);
                        EnQueue(&G, p->adjvex);
                    }
                    p = p->next;
                }
            }
        }
    }
}

你可能感兴趣的:(数据结构与算法)