6.图——数据结构(严蔚敏 C语言版)

6.图

6.1定义和术语

无向图: 每条边都是无方向的
有向图: 每条边都是有方向的
在这里插入图片描述

完全图: 任意两个点都有一条边相连。
在这里插入图片描述

无向完全图:n个顶点,n(n-1)/2条边
有向完全图:n个顶点,n(n-1)条边

网: 边/弧带权的图。
邻接: 有边/弧相连的两个顶点之间的关系。
存在(v, v),则称v,和v互为邻接点;
存在<Vi; Vj>,则称vi邻接到vj,vj邻接于vi。
顶点的度: 与该顶点相关联的边的数目,记为TD(v);在有向图中,顶点的度等于该顶点的入度与出度之和。顶点v的入度是以v为终点的有向边的条数,记作ID(v)顶点v的出度是以v为始点的有向边的条数,记作OD(v)。
路径: 接续的边构成的顶点序列。
路径长度: 路径上边或弧的数目/权值之和。
回路(环): 第一个顶点和最后一个顶点相同的路径。
连通图(强连通图): 在无(有)向图G=(V,{E})中,若对任何两个顶点v、u都存在从v到u的路径,则称G是连通图(强连通图)。

在这里插入图片描述
权: 图中边或弧所具有的相关数称为权。表明从一个顶点到另一个顶点的距离或耗费。
网: 带权的图称为网。
子图: 设有两个图G= (V,{E})、G1= (V1,{E1}),若V1属于 V,E1 属于E,则称G1是G的子图。
极大连通子图: 该子图是G的连通子图,将G的任何不在该子图中的顶点加入,子图不再连通。
连通分量(强连通分量): 无向图G的极大连通子图称为G的连通分量。
在这里插入图片描述
强连通分量: 有向图G的极大强连通子图称为G的强连通分量。
极大强连通子图: 该子图是G的强连通子图,将D的任何不在该子图中的顶点加入,子图不再是强连通的。
极小连通子图: 该子图是G的连通子图,在该子图中删除任何一条边,子图不再连通。
生成树: 包含无向图G所有顶点的极小连通子图。
生成森林: 对非连通图,由各个连通分量的生成树的集合。

在这里插入图片描述

6.2图的存储

6.2.1数组(邻接矩阵)表示法

建立一个顶点表(记录各个顶点信息)和一个邻接矩阵((表示各个顶点之间关系)。

6.2.1.1有向图

例1:画出下面图的邻接矩阵

在这里插入图片描述
邻接矩阵

在这里插入图片描述
注: 在有向图的邻接矩阵中,
第i行含义:以结点vi为尾的弧(即出度边) ;
第i列含义:以结点vi为头的弧(即入度边)。

分析1:有向图的邻接矩阵可能是不对称的。
分析2:顶点的出度=第i行元素之和
顶点的入度=第i列元素之和
顶点的度=第i行元素之和+第i列元素之和

6.2.1.2无向图

例2:画出下面图的邻接矩阵

在这里插入图片描述
邻接矩阵

在这里插入图片描述

分析1:无向图的邻接矩阵是对称的;
分析2:顶点i的度=第i行(列)中1的个数;
特别:完全图的邻接矩阵中,对角元素为0,其余1。

6.2.1.3网(即有权图)的邻接矩阵表示法

在这里插入图片描述

6.2.2邻接表

节点构成:

在这里插入图片描述

在这里插入图片描述

6.2.2.1无向图

在这里插入图片描述

特点:

  • 邻接表不唯一
  • 若无向图中有n个顶点、e条边,则其邻接表需n个头结点和2e个表结点。适宜存储稀疏图。
  • 无向图中顶点vi的度为第i个单链表中的结点数。
6.2.2.2有向图

在这里插入图片描述

  1. 邻接表特点:
    顶点vi的出度为第i个单链表中的结点个数。
    顶点vi的入度为整个单链表中邻接点域值是i-1 的结点个数。

  2. 逆邻接表特点:
    顶点vi 的入度为第i个单链表中的结点个数。
    顶点vi 的出度为整个单链表中邻接点域值是i-1的结点个数。

6.2.3十字链表

1.结点:
在这里插入图片描述

在这里插入图片描述

2.邻接表:
在这里插入图片描述

3.十字链表:
在这里插入图片描述

6.3图的遍历

6.3.1深度优先遍历

原则: 一条路走到底,直到走不通,返回上一有通路的节点,再继续走。

  • 深度优先搜索(Depth First Search,DFS)遍历类似于树的先序遍历,是树的先序遍历的推广。
  • 用邻接矩阵来表示图,遍历图中每一个顶点都要从头扫描该顶点所在行,时间复杂度为O(2)。
  • 用邻接表来表示图,虽然有2e个表结点,但只需扫描e个结点即可完成遍历,加上访问r个头结点的时间,时间复杂度为O(n+e)。
  • 稠密图适于在邻接矩阵上进行深度遍历;稀疏图适于在邻接表上进行深度遍历。
    1.用邻接表进行表示
    2.用邻接矩阵进行表示
    在这里插入图片描述

6.3.2广度优先遍历

原则: 从一结点开始,依次访问该点所有的邻接点,再按照这些点被访问的先后次序访问他们的邻接点。重复此过程。

在这里插入图片描述

遍历:
在这里插入图片描述

6.4最小生成树

6.4.1生成树

生成树: 所有顶点均由边连接在一起,但不存在回路的图。
在这里插入图片描述

  • 一个图可以有许多棵不同的生成树所有生成树具有以下共同特点。生成树的顶点个数与图的顶点个数相同;
  • 生成树是图的极小连通子图,去掉一条边则非连通;
  • 一个有n个顶点的连通图的生成树有n-1条边;
  • 在生成树中再加一条边必然形成回路。
  • 生成树中任意两个顶点间的路径是唯一的。

在这里插入图片描述
深度优先(左)和广度优先(右)生成树

6.4.2最小生成树

最小生成树: 给定一个无向网络,在该网的所有生成树中,使得各边权值之和最小的那棵生成树称为该网的最小生成树,也叫最小代价生成树。

6.4.2.1Prim算法(普利姆算法)

普里姆算法的构造过程
假设N=(V,E)是连通网,TE是N上最小生成树中边的集合。①U={uo}(uEW),TE=号。
在所有uEU, vEV-U的边(u,v)∈E中找一条权值最小的边(uo vo)并入集合TE,同时v并入U。
③重复②,直至U=V为止。
此时TE中必有n-1条边,则T=(V, TE)为N的最小生成树。

在这里插入图片描述

6.4.2.2Kruskal算法(克鲁斯卡尔算法)

克鲁斯卡尔算法的构造过程
假设连通网N=(V, E),将N中的边按权值从小到大的顺序排列。
①初始状态为只有n个顶点而无边的非连通图T=(V,),图中每个顶点自成一个连通分量。在E中选择权值最小的边,若该边依附的顶点落在T中不同的连通分量上(即不形成回路),则将此边加入到T中,否则舍去此边而选择下一条权值最小的边。
③重复②,直至T中所有顶点都在同一连通分量上为止。

在这里插入图片描述

6.5拓扑排序

有向无环图:

  • AOV网 (Active on Vertex)
    用一个有向图表示一个工程的各子工程及其相互制约的关系,其中以顶点表示活动或表示活动之间的关系。称顶点表示活动的网。。 Active on Vertex network.
  • AOE网(Active on Edge)
    用一个有向图表示一个工程的各子工程及其相互制约的关系。以弧表示活动,以顶点表示活动开始或结束事件,边表示活动的网。

拓扑排序
在aov网中设有回路的前提下,将全部活动排成一个线性序列,使aov网中有弧<i,j>存在。i一定排在j前面,具有这种性质的线性序列为拓扑有序序列,相应的算法称为拓扑排序。
拓扑排序的方法

  1. 在有向图中选一个没有前驱的定点输出。
  2. 从图中删除该顶点和所有以它为尾的弧。
  3. 重复上述两步,直到全部顶点输出或当图中,不存在无前驱的顶点为止。

在这里插入图片描述

在这里插入图片描述

检测AOV网中是否存在环的方法。
对有象图构造其顶点的拓扑有序序列入网中所有景点都在它的拓扑有序序列中,这该aov网必定不存在。

6.6关键路径

关键路径: AOE网中边表示活动的网络顶点表示事件弧表示活动图的权表示活动持续时间事件表示在他之前的活动已经完成,他之后的活动可以开始。

  • 关键路径——路径长度,最长的路径。
    路径长度——路径上各活动持续时间之和。
    源点——入度为0的顶点。
    汇点——出度为0的顶点。

ve(vj):表示事件vj的最早发生时间。
vl(vj) :事件vj的最迟发生时间。
e(i) :活动 AI的最早开始时间。
l(i) :活动ai最迟开始时间。
l(i)-e(i) :完成活动AI的时间余量。
关键活动:关键路径上的活动。即 l(i)-e(i)==0的活动。
求关键路径具体步骤(方法)

例:求下图的关键路径

求关键路径的步骤:

  1. 求ve(i), vl(j)

  2. e(i), l(i)

  3. 计算l(i)-e(i)

    ve(j) = MAX{ve(i)+wi,j} (正序,选权值和的最大)

    vl(i) = MIN{vl(j) - wi,j} (反序,选权值差的最小)

    (1)e(i) = ve(j)

    (2) l(i) = vl(k) - wj,k

在这里插入图片描述
顶点发生的时间:
在这里插入图片描述

活动开始的时间:
在这里插入图片描述

ve:正序选和最大。

vl:反序选差的最小。

e = 前一个顶点的ve。

l = 前一个顶点的vl - ai。
最后选出l-e = 0 的路径连起来就是关键路径

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构》(c语言)是为“数据结构”课程编写的教材,也可作为学习数据结构及其算法的C程序设计的参数教材。学了数据结构后,许多以前写起来很繁杂的代码现在写起来很清晰明了. 本书的前半部分从抽象数据类型的角度讨论各种基本类型的数据结构及其应用;后半部分主要讨论查找和排序的各种实现方法及其综合分析比较。 全书采用类C语言作为数据结构算法的描述语言。 本书概念表述严谨,逻辑推理严密,语言精炼,用词达意,并有配套出的《数据结构题集》(C语言),便于教学,又便于自学。 本书后附有光盘。光盘内容可在DOS环境下运行的以类C语言描述的“数据结构算法动态模拟辅助教学软件,以及在Windows环境下运行的以类PASCAL或类C两种语言描述的“数据结构算法动态模拟辅助教学软件”。 目录: 第1章 绪论 1.1 什么是数据结构 1.2 基本概念和术语 1.3 抽象数据类型的表现与实现 1.4 算法算法分析 第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示及相加 第3章 栈和队列 3.1 栈 3.2 栈的应有和举例 3.3 栈与递归的实现 3.4 队列 3.5 离散事件模拟 第4章 串 4.1 串类型的定义 4.2 串的表示和实现 4.3 串的模式匹配算法 4.4 串操作应用举例 第5章 数组和广义表 5.1 数组的定义 5.2 数组的顺序表现和实现 5.3 矩阵的压缩存储 5.4 广义表的定义 5.5 广义表的储存结构 5.6 m元多项式的表示 5.7 广义表的递归算法第6章 树和二叉树 6.1 树的定义和基本术语 6.2 二叉树 6.2.1 二叉树的定义 6.2.2 二叉树的性质 6.2.3 二叉树的存储结构 6.3 遍历二叉树和线索二叉树 6.3.1 遍历二叉树 6.3.2 线索二叉树 6.4 树和森林 6.4.1 树的存储结构 6.4.2 森林与二叉树的转换 6.4.3 树和森林的遍历 6.5 树与等价问题 6.6 赫夫曼树及其应用 6.6.1 最优二叉树(赫夫曼树) 6.6.2 赫夫曼编码 6.7 回溯法与树的遍历 6.8 树的计数 第7章 7.1 的定义和术语 7.2 的存储结构 7.2.1 数组表示法 7.2.2 邻接表 7.2.3 十字链表 7.2.4 邻接多重表 7.3 的遍历 7.3.1 深度优先搜索 7.3.2 广度优先搜索 7.4 的连通性问题 7.4.1 无向的连通分量和生成树 7.4.2 有向的强连通分量 7.4.3 最小生成树 7.4.4 关节点和重连通分量 7.5 有向无环及其应用 7.5.1 拓扑排序 7.5.2 关键路径 7.6 最短路径 7.6.1 从某个源点到其余各顶点的最短路径 7.6.2 每一对顶点之间的最短路径 第8章 动态存储管理 8.1 概述 8.2 可利用空间表及分配方法 8.3 边界标识法 8.3.1 可利用空间表的结构 8.3.2 分配算法 8.3.3 回收算法 8.4 伙伴系统 8.4.1 可利用空间表的结构 8.4.2 分配算法 8.4.3 回收算法 8.5 无用单元收集 8.6 存储紧缩 第9章 查找 9.1 静态查找表 9.1.1 顺序表的查找 9.1.2 有序表的查找 9.1.3 静态树表的查找 9.1.4 索引顺序表的查找 9.2 动态查找表 9.2.1 二叉排序树和平衡二叉树 9.2.2 B树和B+树 9.2.3 键树 9.3 哈希表 9.3.1 什么是哈希表 9.3.2 哈希函数的构造方法 9.3.3 处理冲突的方法 9.3.4 哈希表的查找及其分析 第10章 内部排序 10.1 概述 10.2 插入排序 10.2.1 直接插入排序 10.2.2 其他插入排序 10.2.3 希尔排序 10.3 快速排序 10.4 选择排序 10.4.1 简单选择排序 10.4.2 树形选择排序 10.4.3 堆排序 10.5 归并排序 10.6 基数排序 10.6.1 多关键字的排序 10.6.2 链式基数排序 10.7 各种内部排序方法的比较讨论 第11章 外部排序 11.1 外存信息的存取 11.2 外部排序的方法 11.3 多路平衡归并的实现 11.4 置换一选择排序 11.5 最佳归并树 第12章 文件 12.1 有关文件的基本概念 12.2 顺序文件 12.3 索引文件 12.4 ISAM文件和VSAM文件 12.4.1 ISAM文件 12.4.2 VSAM文件 12.5 直接存取文件(散列文件) 12.6 多关键字文件 12.6.1 多重表文件 12.6.2 倒排文件 附录A 名词索引 附录B 函数索引 参考书目
C语言是一门非常流行的编程语言,也是很多数据结构算法课程的教学语言之一。以下是一些基本数据结构C语言实现: 1. 数组 数组是一种基本的数据结构,它可以存储同一类型的一组数据。在C语言中,数组的定义形式如下: ``` type arrayName[arraySize]; ``` 例如,以下代码定义了一个包含10个整数的数组: ``` int numArray[10]; ``` 2. 链表 链表是一种常见的动态数据结构,它由一系列节点组成,每个节点都包含一个数据和一个指向下一个节点的指针。在C语言中,链表的定义通常使用结构体和指针来实现。 例如,以下代码定义了一个简单的链表节点结构体: ``` struct Node { int data; struct Node* next; }; ``` 3. 栈 栈是一种基于后进先出(LIFO)原则的数据结构。在C语言中,可以使用数组或者链表来实现栈。以下是一个基于数组实现的简单栈: ``` #define MAX_SIZE 100 int stack[MAX_SIZE]; int top = -1; void push(int data) { if (top >= MAX_SIZE-1) { printf("Stack Overflow\n"); return; } stack[++top] = data; } int pop() { if (top < 0) { printf("Stack Underflow\n"); return -1; } return stack[top--]; } ``` 4. 队列 队列是一种基于先进先出(FIFO)原则的数据结构。在C语言中,可以使用数组或者链表来实现队列。以下是一个基于数组实现的简单队列: ``` #define MAX_SIZE 100 int queue[MAX_SIZE]; int front = -1; int rear = -1; void enqueue(int data) { if (rear >= MAX_SIZE-1) { printf("Queue Overflow\n"); return; } if (front == -1 && rear == -1) { front = 0; } queue[++rear] = data; } int dequeue() { if (front == -1 || front > rear) { printf("Queue Underflow\n"); return -1; } return queue[front++]; } ``` 这些是一些常见的数据结构C语言中的实现方式。当然,这只是冰山一角,还有很多其他的数据结构算法需要掌握。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值