- 特点:多个对多个
- 顶点和边的集合:G=(V,E),V:顶点的有穷非空集合,E:边的有穷集合
- 完全图:任意两个点都有一条边相连
- 稀疏图:很少边或弧的图(e<nlogn)
- 稠密图:有较多边或弧
- 网:边或弧带权的图
- 邻接:有边或弧相连的两个顶点之间的关系
- 关联或依附:边或弧与顶点的关系
- 顶点的度:与顶点相关联的边的数目
- 路径:接续的边构成的顶点序列
- 路径长度:路径上边和弧的数目/权值的和
- 回路/环:第一个顶点和最后一个顶点相同的路径
- 简单回路:除了路径的起点和终点可以相同,其余顶点均不相同的路径
- 简单回路:除了路径的起点和终点相同,其余顶点均不相同的路径
- 连通图/强连通图(对有向图):对任意连个顶点都存在到达对方的路径
- 子图:类似子树
- 连通分量/强连通分量:
注意:删除任意一条边
- 图的存储结构:数组表示法,多重链表
- 数组表示法:
无向:如果存在i,j间的边或弧,1;否则,0;统计度,只看横或者竖
有向:横a 竖b,a→b,1或为权值;横b 竖a,b→a,0或无穷大;度,即看横也看竖
- 算法表示:
- 邻接表(链式):
表结点可以多一个类型用来存储权
对于有向:同理,只记出
- 算法表示:
-
十字链表:
逆邻接表和邻接表结合,针对有向图
增加一个指针域表示出度
-
邻接多重表:
针对无向表,
- 图的遍历:
思路:
DFS:
思路:
简而言之,一条路走到底,如果不行了,就回退,继续看有没有路可走
算法实现(对邻接矩阵):
算法实现(对邻接表):循环中变为链表指向下一个
BFS:
思路:
运用队列,步骤:队 0,入队 1,入队2,出队0,入队3,入队4,出队1,入队5.。。。。。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define MAX_SIZE 6
#define OVERFLOW 1
// used to struct queue
typedef struct traversal_
{
int *data;
int front;
int rear;
}Treversal,*treversal;
//used to struct graph
typedef struct graph_
{
int **connect;
int numbernodes;
}Graph,*graph;
treversal iniqueue(){
treversal resultqueue=(treversal)malloc(sizeof(Treversal));
resultqueue->data=(int *)malloc (sizeof(int)*MAX_SIZE);
resultqueue->front=0;
resultqueue->rear=0;
return resultqueue;
}
int isqueueempty(treversal paraqueue){
if ((paraqueue->rear)%MAX_SIZE==paraqueue->front){
return 1;
}
return 0;
}
treversal enqueue(treversal paraqueue,int number){
if (paraqueue->front==(paraqueue->rear+1)%MAX_SIZE){
exit(OVERFLOW);
}
paraqueue->data[paraqueue->rear]=number;
paraqueue->rear=(paraqueue->rear+1)%MAX_SIZE;
return paraqueue;
}
int dedata(treversal paraqueue){
if (isqueueempty(paraqueue)){
exit(OVERFLOW);
}
return paraqueue->data[paraqueue->front];
}
treversal dequeue(treversal paraqueue){
if (isqueueempty(paraqueue)){
exit(OVERFLOW);
}
paraqueue->front=(paraqueue->front+1)%MAX_SIZE;
return paraqueue;
}
graph initgraph(int parasize,int **paradata){
graph resultgraph=(graph)malloc(sizeof(Graph));
resultgraph->connect=(int**)malloc(sizeof (int)*MAX_SIZE);
resultgraph->numbernodes=parasize;
for(int i=0;i<parasize;i++){
resultgraph->connect[i]=(int *)malloc(sizeof(int)*MAX_SIZE);
for (int q=0;q<parasize;q++){
resultgraph->connect[i][q]=paradata[i][q];
}
}
return resultgraph;
}
void lenfitreversal(graph paragraph){
int isvis[paragraph->numbernodes];
for (int i=0;i<paragraph->numbernodes;i++){
isvis[i]=0;
}
treversal paraqueue=iniqueue();
paraqueue=enqueue(paraqueue,4);
while (!isqueueempty(paraqueue))
{
int var=dedata(paraqueue);
paraqueue=dequeue(paraqueue);
if (isvis[var]==0){
printf("%d ",var);
isvis[var]=1;
for (int q=0;q<paragraph->numbernodes;q++){
if (paragraph->connect[var][q]==1){
if (isvis[q]==0)
paraqueue=enqueue(paraqueue,q);
}
}
}
}
printf("\r\n");
}
void depthitreversal(graph paragraph,int n, int *isvis){
printf("%d ",n);
isvis[n]=1;
for (int i=0;i<paragraph->numbernodes;i++){
if (isvis[i]==0 && paragraph->connect[n][i]==1){
depthitreversal(paragraph,i,isvis);
}
}
}
void testsample(){
int migraph[5][5]={
{0,1,0,1,0},
{1,0,1,0,1},
{0,1,0,1,1},
{1,0,1,0,1},
{0,1,0,1,0}
};
int **tempptr;
tempptr=(int **)malloc(sizeof(int*)*5);
for (int i=0;i<5;i++){
tempptr[i]=(int*)malloc(sizeof (int)*5);
for (int q=0;q<5;q++){
tempptr[i][q]=migraph[i][q];
}
}
graph l=initgraph(5,tempptr);
printf("广度优先遍历:");
lenfitreversal(l);
int iss[5]={0,0,0,0,0};
int *isvis=(int*)malloc(sizeof(int)*5);
for (int q=0;q<5;q++){
isvis[q]=0;
}
printf("深度优先遍历:");
depthitreversal(l,4, isvis);
}
int main(){
testsample();
return 0;
}
运行结果: