创建: 2018/06/01

图的概念

有向边

有向图

无向边

无向图

点的次数: 点连接的边的数量

闭路: 起点和重点一样

连接图: 任意两点之间都可到达

无闭路有向图: 没有闭路的有向图

森林: 互素的树的集合

生成树: 含有图里所有点的树

生成树林: 所有生成树的并集

   
   
图论算法的应用  
 

● 电路的元件关系

● 交通网

● 电脑网络(本地网络, 互联网, web等)

● 数据库(实体关系图(ER图))

   
图的数据结构  
 邻接矩阵

适用于数据多的

//------------------------------------------------
// 邻接矩阵
//------------------------------------------------
struct Graph {
int v;
int e;
int **adj;
}; // 创建图
struct Graph *adjMatrixOfGraph() {
int i, u, v;
struct Graph *G = (struct Graph *)malloc(sizeof(struct Graph));
if (G == NULL) {
printf("memory error\n");
return NULL;
}
printf("Number of Verticees: ");
scanf("%d", &G->v);
printf("Number of Edges: ");
scanf("%d", &G->e);
G->adj = (int **)malloc(sizeof(int *) * G->v);
if (G->adj == NULL) {
printf("Memory Error\n");
return NULL;
}
for (i = ; i < G->v; i++) {
G->adj[i] = (int *)malloc(sizeof(int) * G->v);
if (G->adj[i] == NULL) {
printf("Memory Error\n");
return NULL;
}
}
printf("v: %d, e: %d\n", G->v, G->e);
for (u=; u<G->v; u++) { // 初始化点
for (v=; v<G->v; v++) {
if (u==v) {
G->adj[u][v] = ;
} else {
G->adj[u][v] = ; // 以0初始化矩阵
}
}
} for (i=; i<G->e; i++) { // 初始化边
printf("Reading Edge: ");
scanf("%d %d", &u, &v);
G->adj[u][v] = G->adj[v][u] = ;
}
return G;
}
 邻接链表 

适用于数据小的

//------------------------------------------------
// 邻接链表
//------------------------------------------------
struct S9ListNode {
int vertexNumber;
struct S9ListNode *next;
}; struct ListGraph {
int v;
int e;
struct S9ListNode *adj;
}; struct ListGraph *adjListOfGraph() { // 无向图
int i, x, y;
struct S9ListNode *temp;
struct ListGraph *G = (struct ListGraph *)malloc(sizeof(struct ListGraph));
if (G == NULL) {
printf("Memory Error\n");
return NULL;
}
printf("Number of Vertices: ");
scanf("%d", &G->v);
printf("Number of Edges: ");
scanf("%d", &G->e);
G->adj = (struct S9ListNode *)malloc(sizeof(struct S9ListNode)*G->v);
if (G->adj == NULL) {
printf("Memory Error\n");
return NULL;
}
for (i=; i<G->v; i++) { // 先初始化所有链表
G->adj[i] = *(struct S9ListNode *)malloc(sizeof(struct S9ListNode));
G->adj[i].vertexNumber = i;
G->adj[i].next = &G->adj[i];
} for (i=; i<G->e; i++) {
printf("Reading Edge: ");
scanf("%d %d", &x, &y);
struct S9ListNode *node;
temp = (struct S9ListNode *)malloc(sizeof(struct S9ListNode));
// 把y添加到x的链表上
temp->vertexNumber = y;
temp->next = &G->adj[x];
node = &G->adj[x];
while (node != NULL && node->next != &G->adj[x]) {
node = node->next;
}
node->next = temp;
// 把x添加到y的链表山
temp = (struct S9ListNode *)malloc(sizeof(struct S9ListNode));
temp->vertexNumber = x;
temp->next = &G->adj[y];
node = &G->adj[y];
while (node != NULL && node->next != &G->adj[y]) {
node = node->next;
}
node->next = temp;
}
return G;
}
   
图的遍历

DFS

深度优先搜索

Depth First Search

//------------------------------------------------
// 深度优先搜索 DFS
//------------------------------------------------
int visited[]; // 实际只需要点的数量的长度
// 状态: 1: 已访问 0: 未访问
// 邻接矩阵的DFS
void depthFirstSearch(struct Graph *g, int u) {
int v;
visited[u] = ;
printf("%d visited\n", u); // 访问中的处理
for (v = ; v <g->v; v++) {
// 对点u连接的未访问的节点进行访问
if (visited[v] == && g->adj[u][v] != ) { // 节点并未访问且u和v连接
depthFirstSearch(g, v); // 从v出发
}
}
} void depthFirstSearchTraversal(struct Graph *g) {
int i;
for (i = ; i < g->v; i++) { // 初始化访问表
visited[i] = ;
}
// 有不通的子连接图时需要
for (i = ; i < g->v; i++) {
if (visited[i] == ) {
depthFirstSearch(g, i); // 一次呼出直接遍历完i可到的所有点
}
}
} // 邻接链表的DFS
void depthFirstSearch_List(struct ListGraph *g, int u) {
struct S9ListNode *temp = g->adj[u].next;
visited[u] = ;
printf("%d visited\n", u); // 访问中的处理
while (temp != &g->adj[u]) {
if (visited[temp->vertexNumber] == ) {
depthFirstSearch_List(g, temp->vertexNumber);
}
temp = temp->next;
} } void depthFirstSearchTraversal_List(struct ListGraph *g) {
int i;
for (i = ; i < g->v; i++) { // 初始化访问表
visited[i] = ;
}
// 有不通的子连接图时需要
for (i = ; i < g->v; i++) {
if (visited[i] == ) {
depthFirstSearch_List(g, i); // 一次呼出直接遍历完i可到的所有点
}
}
}

BFS

宽度优先搜索

Breadth First Search

//------------------------------------------------
// 宽度优先搜索 BFS
//------------------------------------------------
struct S9QueueNode {
int data;
struct S9QueueNode *next;
};
struct S9Queue {
struct S9QueueNode *front;
}; struct S9Queue *S9CreateQueue() {
struct S9Queue *q = (struct S9Queue *)malloc(sizeof(struct S9Queue));
if (q == NULL) {
return NULL;
}
q->front = NULL;
return q;
} int S9DeQueue(struct S9Queue *queue) {
if (queue==NULL) {
return -;
}
if (queue->front == NULL) {
return -;
}
struct S9QueueNode *temp = queue->front;
if (queue->front == NULL) {
return -;
}
int data = temp->data;
queue->front = queue->front->next;
free(temp);
return data;
}
void S9EnQueue(struct S9Queue *queue, int data) {
if (queue == NULL) {
queue = (struct S9Queue *)malloc(sizeof(struct S9Queue));
}
struct S9QueueNode *newNode = (struct S9QueueNode *)malloc(sizeof(struct S9QueueNode));
struct S9QueueNode *temp = queue->front;
newNode->next = NULL;
newNode->data = data;
if (temp == NULL) {
queue->front = newNode;
} else {
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
} void S9FreeQueue(struct S9Queue *q) {
if (q == NULL) {
return;
}
if (q->front != NULL) {
struct S9QueueNode *temp = q->front, *temp2;
while (temp != NULL) {
temp2 = temp;
temp = temp->next;
free(temp2);
}
}
free(q);
} int S9IsEmptyQueue(struct S9Queue *queue) { // true: 1, false: 0
if (queue == NULL) {
return ;
}
int result = queue->front == NULL ? : ;
return result;
}
void S9ShowQueue(struct S9Queue *q) {
if (q == NULL) {
printf("queue is null\n");
return;
}
if (q->front == NULL) {
printf("queue has no data\n");
return;
}
struct S9QueueNode *temp = q->front;
int count = ;
while (temp) {
printf("[%d]: %d ", count, temp->data);
temp = temp->next;
count++;
}
puts("");
} int visited_bfs[];
void breadthFirstSearch(struct Graph *g, int u) { // 矩阵
int count = , i;
struct S9Queue *queue = S9CreateQueue();
S9EnQueue(queue, u);
while (!S9IsEmptyQueue(queue)) {
int u = S9DeQueue(queue);
printf("顶点[%d]: %d\n", count, u);
count++;
visited_bfs[u] = ;
for (i=; i<g->v; i++) {
if (g->adj[u][i] == && visited_bfs[i] == ) {
S9EnQueue(queue, i);
}
}
}
S9FreeQueue(queue);
}
void breadthFirstSearchTravsal(struct Graph *g) {
for (int i=; i<; i++) {
visited_bfs[i] = ;
}
for (int i = ; i<g->v; i++) {
if (visited_bfs[i] == ) {
breadthFirstSearch(g, i);
}
}
}
   
最短路径算法  
 种类

● 不带加权的图

● 带加权的图

● 有负加权的图

 应用 

● 两地间最近的路

●  从A到B发送数据最便宜的方法

 不加权的图最短路径
//------------------------------------------------
// 不带加权的图
//------------------------------------------------
int distant[];
int path[];
void unweightedShortestPath(struct Graph *g, int s) { // 邻接矩阵版
struct S9Queue *queue = S9CreateQueue();
int v, w;
S9EnQueue(queue, s);
for (int i = ; i<g->v; i++) {
distant[i] = -;
path[i] = -; // 起点为-1
}
distant[s] = ;
while(!S9IsEmptyQueue(queue)) {
v = S9DeQueue(queue);
for (w = ; w<g->v; w++) {
if (g->adj[v][w] != && distant[w] == -) {
S9EnQueue(queue, w);
distant[w] = distant[v] + ;
path[w] = v;
}
}
}
S9FreeQueue(queue);
}

迪杰斯特拉算法

加权图最短路径算法

//------------------------------------------------
// 不带负加权的图 迪杰斯特拉算法
//------------------------------------------------
void dijkstra(struct Graph *g, int s) {
struct S9Queue *queue = S9CreateQueue(); // 优先队列
int v, w;
S9EnQueue(queue, s);
for (int i = ; i<g->v; i++) {
distant[i] = -; // -1 表示还没处理
}
distant[s] = ; // 自己到自己的距离为0
while (!S9IsEmptyQueue(queue)) {
// v = S9DeQueue(queue); // TODO-PRO: fix here [这里要改成以距离为排序的DeleteMin]
v = S9DeleteMin(queue);
for (w = ; w<g->v; w++) {
if (g->adj[v][w] != ) { // v -> w 直接相同
int newDistant = distant[v] + g->adj[v][w]; // 新距离
printf("distant[v]: %d\n", distant[v]);
if (distant[w] == -) {
distant[w] = newDistant;
S9EnQueue(queue, w);
path[w] = v;
} else if (newDistant < distant[w]) {
distant[w] = newDistant;
path[w] = v;
// 更新w
S9EnQueue(queue, w);
}
}
}
}
}
 贝尔曼-福特算法  可以有负加权边
   

【WIP_S9】图论算法的更多相关文章

  1. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

  2. 图论算法-网络最大流【EK;Dinic】

    图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...

  3. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

  4. tarjan图论算法

    tarjan图论算法 标签: tarjan 图论 模板 洛谷P3387 [模板]缩点 算法:Tarjan有向图强连通分量+缩点+DAGdp 代码: #include <cstdio> #i ...

  5. [算法模版]Tarjan爷爷的几种图论算法

    [算法模版]Tarjan爷爷的几种图论算法 前言 Tarjan爷爷发明了很多图论算法,这些图论算法有很多相似之处(其中一个就是我都不会).这里会对这三种算法进行简单介绍. 定义 强连通(strongl ...

  6. NOIp 图论算法专题总结 (1):最短路、最小生成树、最近公共祖先

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 最短路 Floyd 基本思路:枚举所有点与点的中点,如果从中点走最短,更新两点间 ...

  7. NOIp 图论算法专题总结 (2)

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 树链剖分 https://oi-wiki.org/graph/heavy-lig ...

  8. NOIp 图论算法专题总结 (3):网络流 & 二分图 简明讲义

    系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 网络流 概念 1 容量网络(capacity network)是一个有向图,图的 ...

  9. 图论算法(一)存图与STL第六弹——vector容器

    图论算法(一)存图 我发现我的博客阅读量贼低,问小伙伴们,ta们都说这些博客太长了QAQ! 今天来个短亿点的(也短不了多少……) 进入正题,图论究竟是什么? 图论就是给你一张图,让你在这张图上进行各种 ...

随机推荐

  1. Linux内核RCU(Read Copy Update)锁简析

    在非常早曾经,大概是2009年的时候.写过一篇关于Linux RCU锁的文章<RCU锁在linux内核的演变>,如今我承认.那个时候我尽管懂了RCU锁,可是我没有能力用一种非常easy的描 ...

  2. Scala随记

    使用Scala首先确保本地Java 8版本,然后按照官网所说,比较流行的方式(1) sbt; (2) IDE "The most popular way to get Scala is ei ...

  3. ecshop忘记管理员密码

    直接修改数据表 ecs_admin_user, 找到对应的管理员, 同时修改 password 为 2fc3ec4c91d51bee94f4a8ccbdbe5383 和 ec_salt 为1819, ...

  4. 深入理解Java:注解(Annotation)自定义注解入门(转载)

    要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...

  5. android好博客

    app集成支付宝.app缓存管理.app列表圆角设计.App自动更新之通知栏下载(有续).索引ListView.App数据格式之解析Json.拖拽ListView http://www.cnblogs ...

  6. iOS Dev (26) 初步了解下UIColor的最常用知识

    作者:CSDN 大锐哥 地址:http://blog.csdn.net/prevention - 内置的颜色有啥? // Some convenience methods to create colo ...

  7. eacharts 根据后台数据生成柱状图

    说明:开发环境vs2012 ,asp.net mvc4项目,c#语言 1.效果图 2.HTML 前端代码 <%@ Page Language="C#" AutoEventWi ...

  8. 九度OJ 1117:整数奇偶排序 (排序)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3174 解决:932 题目描述: 输入10个整数,彼此以空格分隔.重新排序以后输出(也按空格分隔),要求: 1.先输出其中的奇数,并按从大到 ...

  9. llala js弹出层 颜色渐变

    网址:http://bbs.csdn.net/topics/370254842

  10. js日期和时间戳互换

    <script> function js_strto_time(str_time){ var new_str = str_time.replace(/:/g,'-'); new_str = ...