《数据结构》第6章 图

本文介绍了图的基本概念,如无向图、有向图、度等,并详细讲解了图的存储结构,包括邻接矩阵和邻接表。接着探讨了图的遍历方法,深度优先搜索DFS和广度优先搜索BFS。最后,文章重点讨论了图的应用,如最小生成树(普里姆和克鲁斯卡尔算法)、最短路径(迪杰斯特拉和弗洛伊德算法)以及关键路径分析。
摘要由CSDN通过智能技术生成

第6章 图

在这里插入图片描述在这里插入图片描述

6.1 图的定义和基本数据

在这里插入图片描述概念总览:

  1. 无向图、有向图
  2. 完全图、稠密图、稀疏图
  3. 度、入度、出度、邻接点(相邻接)
  4. 连通图(=强连通图)、路径
  5. 权、网
  6. 子图
  7. 简单图
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    现阶段研究的一般都是简单图

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

在这里插入图片描述

6.2.1 邻接矩阵(顺序存储结构 两步:初始化(图0网∞)+1的修正)

1.无向图

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.有向图(行出尾,列入头)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

3.无向网

在这里插入图片描述

4.有向网

在这里插入图片描述在这里插入图片描述在这里插入图片描述

6.2.2 邻接表(链式存储结构 表结点+头结点)

在这里插入图片描述

1.无向图

在这里插入图片描述在这里插入图片描述

2.有向图(邻接表+逆邻接表)

在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述

3.网(数据结构的魅力)

在这里插入图片描述在这里插入图片描述

6.3 图的遍历(2 深度by栈+广度by队列→生成树 都不唯一)

在这里插入图片描述在这里插入图片描述

6.3.1 深度优先搜索DFS(Depth First Search)一路走到头,不撞墙不回头。回退去哪里找?去里,后进来的先出去。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

6.3.2 广度优先搜索BFS(Breadth First Search)闪电 自上向下,自左向右。分组判断

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

6.4 图的应用(要掌握7个算法:最小生成树2+最短路径2+拓扑排序+关键路径)

在这里插入图片描述在这里插入图片描述

一、生成树和最小生成树(4种方法,讲2个)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

1.普里姆 prim 算法(稠密图 n个结点n步——初始化+n-1条边)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.克鲁斯卡尔 kruskal 算法(稀疏图 更简单 n个结点n步——初始化+n-1条边)

在这里插入图片描述在这里插入图片描述

二、最短路径

在这里插入图片描述

1.【常考】迪杰斯特拉 Dijkstra 算法(单源点 n个结点n步——初始化+n-1次变实线)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.弗洛伊德 Floyd 算法(顶点对)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述下图解释:
D数组:D0是左图的邻接矩阵表示,D1根据等式换算得到(第一次修正)。
出现问题:数据多的话容易混乱。→借助P数组(存放路径中其前驱顶点)
V2的前驱顶点是1,V1的前驱顶点是0→V0到V2的路径是0→1→2
阿杰算法只需要一维数组,弗洛伊德算法需要D、P两个二维数组
在这里插入图片描述在这里插入图片描述代码:3个嵌套,时间复杂度是O(n^3)
在这里插入图片描述1.初始化
在这里插入图片描述2.结果
P的理解:
对角线——自己到自己就填自己
V0到V1~V8都需要经过1
V3到V0~V2都需要经过4
在这里插入图片描述

三、关键路径(研究2个问题)

甘特图以图示通过活动列表和时间刻度表示出特定项目的顺序与持续时间。一条线条图,横轴表示时间,纵轴表示项目,线条表示期间计划和实际完成情况。直观表明计划何时进行,进展与要求的对比。便于管理者弄清项目的剩余任务,评估工作进度。
甘特图是以作业排序为目的,将活动与时间联系起来的最早尝试的工具之一,帮助企业描述工作中心、超时工作等资源的使用。 甘特图包含以下三个含义
1、以图形或表格的形式显示活动; 2、通用的显示进度的方法; 3、构造时含日历天和持续时间,不将周末节假算在进度内。
简单、醒目、便于编制,在管理中广泛应用。 甘特图按内容不同,分为计划图表、负荷图表、机器闲置图表、人员闲置图表和进度表五种形式

如何合理地干完工程?

  1. 能不能干完?(有没有环)——拓扑排序输出顶点序列
  2. 关键路径
1.拓扑排序(AOV网,可判断一个图中是否存在环)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.关键路径(AOE网 事件与活动)

事件瞬间 发生
活动持续一段 开始 结束
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

变量法

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

习题

1.例题

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.考研真题

在这里插入图片描述在这里插入图片描述

#include <iostream>
#include "Stack.h"
#include <malloc.h>
using namespace std;

#define  MAXVEX   14
#define  MAXEDGE  20

typedef struct EdgeNode
{
    int adjvex;    // 邻接点域,存储该顶点对应的下标
    struct EdgeNode* next; // 链域
} EdgeNode;

typedef struct VertexNode
{
    int inNum;    // 顶点入度值
    int data;    // 顶点数值欲
    EdgeNode* firstedge; // 边表头指针
} VertexNode, AdjList[MAXVEX];

typedef struct
{
    AdjList adjList;
    int numVertexes, numEdges; // 图中当前顶点数和边数(对于本案例,已经存在宏定义)
} graphAdjList, *GraphAdjList;

// 构建节点
EdgeNode* BuyNode()
{
    EdgeNode* p = (EdgeNode*)malloc(sizeof(EdgeNode));
    p->adjvex = -1;
    p->next = NULL;
    return p;
}
// 初始化图
void InitGraph(graphAdjList& g)
{
    for (int i = 0; i < MAXVEX; ++i)
    {
        g.adjList[i].firstedge = NULL;
    }
}
// 创建图
void CreateGraph(graphAdjList& g)
{
    int i = 0, begin = 0, end = 0;
    EdgeNode *pNode = NULL;
    cout << "输入14个顶点信息(顶点 入度):" << endl;
    for (i = 0; i < MAXVEX; ++i)
    {
        cin >> g.adjList[i].data >> g.adjList[i].inNum;
    }
    cout << "输入20条边的信息:" << endl;
    for (i = 0; i < MAXEDGE; ++i)
    {
        cin >> begin >> end;
        pNode = BuyNode();
        pNode->adjvex = end;
        pNode->next = g.adjList[begin].firstedge;
        g.adjList[begin].firstedge = pNode;
    }
}
// 打印输入信息的逻辑图
void PrintGraph(graphAdjList &g)
{
    cout << "打印邻接表的逻辑图:" << endl;
    for (int i = 0; i < MAXVEX; ++i)
    {
        cout << " " << g.adjList[i].inNum << " " << g.adjList[i].data << " ";
        EdgeNode* p = g.adjList[i].firstedge;
        cout << ": ";
        while (p != NULL)
        {
            int index = p->adjvex;
            cout << g.adjList[index].data << "  ";
            p = p->next;
        }
        cout << endl;
    }
}
bool TopologicalSort(graphAdjList g)
{
    EdgeNode* pNode = NULL;
    int i = 0, k = 0, gettop = 0;
    int nCnt = 0;
    SeqStack<int> sQ;
    for (i = 0; i < MAXVEX; ++i)
    {
        if (0 == g.adjList[i].inNum)
            sQ.Push(i);
    }
    while (!sQ.IsEmpty())
    {
        sQ.Pop(gettop);
        ++nCnt;
        if (MAXVEX == nCnt)
        {    //去掉拓扑路径后面的-->
            cout << g.adjList[gettop].data; 
            break;
        }
        cout << g.adjList[gettop].data << "-->";
        pNode = g.adjList[gettop].firstedge;
        while (pNode != NULL)
        {
            k = pNode->adjvex;
            --g.adjList[k].inNum;
            if (0 == g.adjList[k].inNum)
                sQ.Push(k);
            pNode = pNode->next;
        }
    }
    return nCnt != MAXVEX;
}
void main()
{
    graphAdjList myg;
    InitGraph(myg);
    cout << "创建图:" << endl;
    CreateGraph(myg);
    cout << "打印图的邻接表逻辑结构:" << endl;
    PrintGraph(myg);
    cout << "拓扑排序路径:" << endl;
    bool bAcire = TopologicalSort(myg);
    cout << endl;
    cout << "存在回环? " << bAcire << endl;
}
/*
创建图:
输入14个顶点信息(顶点 入度):
0 0
1 0
2 2
3 0
4 2
5 3
6 1
7 2
8 2
9 2
10 1
11 2
12 1
13 2
输入20条边的信息:
0 5
0 4
0 11
1 4
1 8
1 2
2 5
2 6
2 9
3 2
3 13
4 7
5 8
5 12
6 5
8 7
9 10
9 11
10 13
12 9
打印图的邻接表逻辑结构:
打印邻接表的逻辑图:
0 0 : 11  4  5
0 1 : 2  8  4
2 2 : 9  6  5
0 3 : 13  2
2 4 : 7
3 5 : 12  8
1 6 : 5
2 7 :
2 8 : 7
2 9 : 11  10
1 10 : 13
2 11 :
1 12 : 9
2 13 :
拓扑排序路径:
3-->1-->2-->6-->0-->5-->8-->12-->9-->10-->13-->11-->4-->7
存在回环? 0
 */

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值