提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、顶点类型、图的类型以及边的结构
typedef int vertex;//顶点编号从0开始
typedef enum bool{
true = 1, false = 0
}bool;
typedef enum Graphkind{
DG=1, DN=2, UDG=3, UDN=4//图的种类:1.有向图 2.有向网 3.无向图 4.无向网
}Graphkind;
typedef struct edgenode {//边结构
vertex v, w;//边的顶点v,w
struct Union {
int weight;
int edge;
}val;//表示权值或者表示是否存在边
}edge;
二、邻接矩阵存储
typedef struct Graph {
int vexnum,edgenum;
//vertex* v;顶点数组,用于顶点可能有数据时
edge* (*matrix);//邻接矩阵
Graphkind kind;
}*MGraph;
三、邻接表存储
typedef struct LGnode {//邻接表顶点数组
//int val;//顶点存储信息时
struct edge* first;//该顶点的第一条边
}LGnode;
typedef struct LGraph {
LGnode* ptr;
int vexnum,edgenum;//顶点数、边数
Graphkind kind;
}*LGraph;
typedef struct edge {//邻接表边结构
vertex end;//弧头
struct edge*next;//下一条边
int weight;
}Ledge;
四、图的建立
1.邻接矩阵建立无向图(网)
MGraph inite_Mgraph(int vnum, Graphkind kind) {//建一个空图
MGraph g = (MGraph)malloc(sizeof(struct Graph));
g->vexnum = vnum;
//g->v = (vertex*)maclloc(sizeof(vertex)*vnum);
g->matrix = (edge**)malloc(sizeof(edge*)*vnum);
for (int i = 0; i < g->vexnum; i++) {
(g->matrix)[i] = (edge*)malloc(sizeof(edge)*vnum);
}
g->kind = kind;
for (vertex v = 0; v < g->vexnum; v++) {
for (vertex w = 0; w < g->vexnum; w++) {
if (g->kind == 3)
(g->matrix)[v][w].val.edge = 0;//或者∞
if (g->kind == 4)
(g->matrix)[v][w].val.weight = 0;
}
}
return g;
}
void create(MGraph g, edge* e) {//插入边e
if (g->kind == 3) {//无向图1表示边存在
(g->matrix)[e->v][e->w].val.edge = 1;
(g->matrix)[e->w][e->v].val.edge = 1;
}
if (g->kind == 4) {
(g->matrix)[e->v][e->w].val.weight = e->val.weight;
(g->matrix)[e->w][e->v].val.weight = e->val.weight;
}
}
MGraph buildMgraph() {
int vnum, kind, edgenum;//顶点数,图类型,顶点关系,边数
scanf_s("%d %d", &vnum, &kind);
MGraph g = inite_Mgraph(vnum, kind);//建空图
scanf_s("%d", &edgenum);
edge* e = (edge*)malloc(sizeof(edge));
for (int i = 0; i < edgenum; i++) {//插入边
if (g->kind == 3) {//无向图
scanf_s("%d %d", &e->v, &e->w);
create(g, e);
}
if (g->kind == 4) {//无向网
scanf_s("%d %d %d", &e->v, &e->w, &e->val.weight);
create(g, e);
}
}
/*for (vertex v= 0; v < g->vexnum; v++) {//若顶点需要存储信息时
scanf_s("%d", &g->v[v]);
}*/
return g;
}
2.邻接表建立有向图(网)
LGraph inite_Lgraph(int vnum, Graphkind kind) {//建一个空图
LGraph g = (LGraph)malloc(sizeof(struct LGraph));
g->vexnum = vnum;
g->kind = kind;
g->ptr = (LGnode*)malloc(sizeof(LGnode));
for (vertex v = 0; v < g->vexnum; v++)
g->ptr[v].first = NULL;//初始化所有顶点均无第一条边
return g;
}
void insertedge(LGraph g, edge* e) {
Ledge *q = (Ledge*)malloc(sizeof(Ledge));
q->end = e->w;
if (g->kind == 2)//有向网存储权值
q->weight = e->val.weight;
q->next = g->ptr[e->v].first;
g->ptr[e->v].first = q;
//若存储无向图还需插入另一边
//Ledge *t = (Ledge*)malloc(sizeof(Ledge));
//t->end = e->v;
//t->weight = e->val.weight;
//t->next=g->ptr[e->w].first;
//g->ptr[e->w].first=t;
}
LGraph buildLgraph() {
int vnum, edgenum, kind;
scanf_s("%d %d", &vnum, &kind);
LGraph g = inite_Lgraph(vnum, kind);//建一个空图
scanf_s("%d", &edgenum);
edge*e = (edge*)malloc(sizeof(edge));
for (int i = 0; i < edgenum; i++) {//插入边
if (g->kind == 1) {//有向图
scanf_s("%d %d", &e->v, &e->w);
insertedge(g, e);
}
if (g->kind == 2) {//有向网
scanf_s("%d %d %d", &e->v, &e->w, &e->val.weight);
insertedge(g, e);
}
}
return g;
}
五、遍历
1.DFS遍历邻接矩阵
void dfs(MGraph g, vertex v, bool*visited) {
visited[v] = true;//更新visited数组
for (vertex w = 0; w < g->vexnum; w++) {
if ((g->matrix)[v][w].val.edge == 1 || (g->matrix)[v][w].val.weight) {//若v,w间存在边或有权值
if (g->kind == 3)
printf("%d<->%d\n", v, w);
if (g->kind == 4)
printf("%d<->%d %d\n", v, w, (g->matrix)[v][w].val.weight);
if (!visited[w])//若为访问过w,则对w做dfs
dfs(g, w, visited);
}
}
}
void DFS(MGraph g) {//对G中每个顶点做DFS
bool* visited = (bool*)malloc(sizeof(g->vexnum));//设置一个标记数组
for (vertex v = 0; v < g->vexnum; v++)visited[v] = false;
for (vertex v = 0; v < g->vexnum; v++) {
if (!visited[v]) {
dfs(g, v, visited);
}
}
}
2.DFS遍历邻接表
void Ldfs(LGraph g, vertex v, bool *visited) {
visited[v] = true;
Ledge*p = g->ptr[v].first;
while (p) {//对v的每个邻接点end
if (g->kind == 1)
printf("%d->%d\n", v, p->end);
if (g->kind == 2)
printf("%d->%d %d\n", v, p->end, p->weight);
if (!visited[p->end])
Ldfs(g, p->end, visited);
p = p->next;
}
}
void LDFS(LGraph g) {
bool *visited = (bool*)malloc(sizeof(g->vexnum));
for (vertex v = 0; v < g->vexnum; v++)visited[v] = false;
for (vertex v = 0; v < g->vexnum; v++) {
if (!visited[v])
Ldfs(g, v, visited);
}
}
3.BFS遍历邻接矩阵
void BFS(MGraph g,vertex u) {//从某一顶点u出发做BFS
bool *visited = (bool*)malloc(sizeof(g->vexnum));
for (vertex v = 0; v < g->vexnum; v++)visited[v] = false;
Queue q = inite();
enqueue(q, u);
visited[u] = true;
while (!isempty(q)) {
vertex v = dequeue(q)->v;
for (vertex w = 0; w < g->vexnum; w++) {
if (g->kind == 3) {
if ((g->matrix)[v][w].val.edge) {//若存在边v,w
if (!visited[w]) {
printf("%d<->%d\n", v, w);
visited[w] = true;
enqueue(q, w);
}
}
}
if (g->kind == 4){
if((g->matrix)[v][w].val.weight)//若存在边v,w
if (!visited[w]) {
printf("%d<->%d %d\n", v, w, (g->matrix)[v][w].val.weight);
visited[w] = true;
enqueue(q, w);
}
}
}
}
}
4.BFS遍历邻接表
void LBFS(LGraph g,vertex u) {
bool* visited = (bool*)malloc(sizeof(g->vexnum));
for (vertex v = u; v < g->vexnum; v++)visited[v] = false;
Queue q = inite();
enqueue(q, u);
visited[u] = true;
while (!isempty(q)) {
vertex v = dequeue(q)->v;
Ledge*t = g->ptr[v].first;
while (t) {
if (!visited[t->end]) {
visited[t->end] = true;
if (g->kind == 1)
printf("%d->%d\n", v, t->end);
if (g->kind == 2)
printf("%d->%d %d\n", v, t->end, t->weight);
enqueue(q, t->end);
}
t = t->next;
}
}
}
六、完整程序
1.函数部分头文件
//邻接矩阵操作集
MGraph inite_Mgraph(int vnum,Graphkind kind);
void create(MGraph g, edge* e);
MGraph buildMgraph();
void showMgraph(MGraph g)
void dfs(MGraph g, vertex v, bool*visited);
void DFS(MGraph g);
void BFS(MGraph g,vertex u);
//邻接表操作集
LGraph inite_Lgraph(int vnum, Graphkind kind);
void insertedge(LGraph g, edge* e);
LGraph buildLgraph();
void showLgraph(LGraph g)
void Ldfs(LGraph g, vertex v, bool *visited);
void LDFS(LGraph g);
void LBFS(LGraph g, vertex u);
//队列
typedef struct qnode {
vertex v;
struct qnode*next;
}qnode;
typedef struct queue {
qnode*head;
qnode*tail;
int num;
}*Queue;
Queue inite();
int isempty(Queue q);
void enqueue(Queue q, vertex u);
qnode* dequeue(Queue q);
2.main
int main() {
MGraph p = buildMgraph();
LGraph g = buildLgraph();
showMgraph(p);
printf("\n");
showLgraph(g);
DFS(p);
LDFS(g);
BFS(p,0);//从任一顶点做BFS
LBFS(g,0);
return 0;
}
void showMgraph(MGraph g) {
for (vertex v = 0; v < g->vexnum; v++) {
for (vertex w = 0; w < g->vexnum; w++) {
if(g->kind==3)
printf("%d",(g->matrix)[v][w].val.edge);
if(g->kind==4)
printf("%d", (g->matrix)[v][w].val.weight);
}
printf("\n");
}
}
void showLgraph(LGraph g) {
for (vertex v = 0; v < g->vexnum; v++) {
printf("%d:", v);
Ledge*e = g->ptr[v].first;
while (e) {
printf("->%d", e->end);
e = e->next;
}
printf("->NULL\n");
}
}
Queue inite()
{
Queue q = (Queue)malloc(sizeof(struct queue));
q->head = q->tail = NULL;
q->num = 0;
}
int isempty(Queue q)
{
if (q->num == 0)return 1;
else return 0;
}
void enqueue(Queue q, vertex v)
{
if (q->head == NULL) {
qnode* tmp = (qnode*)malloc(sizeof(qnode));
tmp->v = v;
tmp->next = NULL;
q->head = tmp;
q->tail = tmp;
}
else {
qnode* tmp = (qnode*)malloc(sizeof(qnode));
tmp->v = v;
tmp->next = q->tail;
q->tail = tmp;
}
q->num++;
}
qnode* dequeue(Queue q)
{
if (q->num == 0)return NULL;
if (q->num == 1) {
q->num = 0;
qnode*tmp = q->head;
q->head = q->tail = NULL;
return tmp;
}
qnode*tmp = q->head;
qnode*p = q->tail;
while (p->next != q->head) {
p = p->next;
}
q->head = p;
q->num--;
return tmp;
}