Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

求图最短路径 #144

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
318 changes: 318 additions & 0 deletions 2017-1/hh-bo/第七次作业/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
//
// main.c
// homework7
//
// Created by Huhongbo on 2017/5/17.
// Copyright © 2017年 Huhongbo. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>

typedef enum
{
OK,
ERROR,
OVERFLOW
}Status;

typedef enum
{
true,
false
}bool;


//图的数组存储结构
#define MAX_VERTEX_NUM 10
#define VRType int
#define InfoType int
#define VertexType int
#define INFINITY -1

typedef struct ArcCell
{
VRType adj;
InfoType *info;
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct
{
VertexType vexs[MAX_VERTEX_NUM];
AdjMatrix arcs;
int vexnum, arcnum; //图的顶点数和弧数;
}MGraph;


//队列的双链存储结构
#define QElemType int

typedef struct QNode
{
QElemType data;
struct QNode *next;
struct QNode *pre;
}QNode, *QueuePtr;

typedef struct LinkQueue
{
QueuePtr front;
QueuePtr rear;
}LinkQueue;

//队列的基本操作
Status InitQueue(LinkQueue *Q);
Status EnQueue(LinkQueue*Q, QElemType e);
Status DeQueue(LinkQueue*Q, QElemType*e);
bool QueueEmpty(LinkQueue*Q);
Status DestroyQueue(LinkQueue*Q);

//图的基本操作
Status LocateVex(MGraph *G, int v1, int v2);
Status CreateUDN(MGraph *G);
int FirstAdjVex(MGraph *G, int u);
int NextAdjvex(MGraph *G, int u, int w);
Status BFSTraverse(MGraph*G, LinkQueue *Q, int a, int b);
Status print(LinkQueue *Q, int a);

//队列的基本操作
Status InitQueue(LinkQueue *Q)
{
Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
if (!Q->front)
{
return ERROR;
}
Q->front->next = Q->rear->next = NULL;
return OK;
}

Status EnQueue(LinkQueue*Q, QElemType e)
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
if (!p)
{
return ERROR;
}
else
{
p->data = e;
p->next = NULL;
p->pre = Q->front;
Q->rear->next = p;
Q->rear = p;
return OK;
}
}

Status DeQueue(LinkQueue*Q, QElemType*e)
{
if (Q->front == Q->rear)
{
return ERROR;
}
Q->front = Q->front->next;
*e = Q->front->data;
return OK;
}

bool QueueEmpty(LinkQueue*Q)
{
if (Q->front == Q->rear)
{
return true;
}
else
{
return false;
}
}

Status DestroyQueue(LinkQueue*Q)
{
while (Q->front)
{
Q->rear = Q->front->next;
free(Q->front);
Q->front = Q->rear;
}
return OK;
}
//图的基本操作

Status LocateVex(MGraph *G,int v1,int v2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

按照我们课件中的操作定义,LocateVex应该是实现若G中存在顶点u,则返回该顶点在图中“位置” ;否则返回其它信息,你这里实际的连线操作是不是用InsertArc更合适?

// 在G中增添弧<v,w>,若G是无向的,
// 则还增添对称弧<w,v>。
InsertArc(&G, v, w); 

{
int i;
int j;
int m = 0;
int n = 0;
for (i = 0; i <= G->vexnum; i++)
{
if (G->vexs[i]==v1)
{
m = i;
break;
}
}
for (j = 0; j <= G->vexnum; j++)
{
if (G->vexs[j] == v2)
{
n = j;
break;
}
}
G->arcs[i][j].adj = 1;//两点之间有连线,弧值为1;
G->arcs[j][i] = G->arcs[i][j];
return OK;
}

//构建图
Status CreateUDN(MGraph *G)
{
int i;
int j;
//根据用例直接赋值。
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

虽然就题论题你这里这样写是能得到正确答案的,但建议以后在实际应用编程时,尽量把这种参数配置类的工作交给调用者(函数)在调用函数时执行传参操作,代码的封装可复用就会一点点积累起来了。

G->vexnum = 9;
G->arcnum = 12;
for (i = 1; i <= G->vexnum; i++)
{
G->vexs[i] = i;//构建顶点向量;
}
for (i = 0; i <= G->vexnum; i++)//初始化邻接矩阵;
{
for (j = 0; j <= G->vexnum; j++)
{
G->arcs[i][j].adj = INFINITY;
G->arcs[i][j].info = NULL;
}
}
//构建邻接矩阵;
LocateVex(G, 1, 2);
LocateVex(G, 1, 3);
LocateVex(G, 1, 4);
LocateVex(G, 1, 7);
LocateVex(G, 2, 3);
LocateVex(G, 4, 5);
LocateVex(G, 4, 6);
LocateVex(G, 5, 6);
LocateVex(G, 6, 8);
LocateVex(G, 7, 8);
LocateVex(G, 7, 9);
LocateVex(G, 8, 9);

return OK;
}

//找出第一个邻接点
int FirstAdjVex(MGraph *G, int u)
{
int i;
for (i = 1; i <= G->vexnum; i++)
{
if (G->arcs[u][i].adj == 1)
{
return i;
}
}
return -1;
}

//找出下一个邻接点
int NextAdjvex(MGraph *G, int u, int w)
{
int i;
for (i = w + 1; i <= G->vexnum; i++)
{
if (G->arcs[u][i].adj == 1)
{
return i;
}
}
return -1;
}
//广度优先遍历图,求两点a,b间的最短路径;
Status BFSTraverse(MGraph*G, LinkQueue *Q,int a,int b)
{

int v;
int u = 0;
int w = 0;
bool visited[MAX_VERTEX_NUM];
for (v = 1; v <= G->vexnum; v++)
{
visited[v] = false; //标记数组,标记图中已访问的点
}

EnQueue(Q, a); //a先入队列;
while (QueueEmpty(Q)!= true)
{
DeQueue(Q, &u);
for (w = FirstAdjVex(G, u); w >=0; w = NextAdjvex(G, u, w))
{
if (visited[w] == false)//判断w是否已经访问过
{
visited[w] = true;
EnQueue(Q, w);
}
if (w == b)
{
break;
}
}
if (w == b)
{
break;
}
}
return OK;
}

Status print(LinkQueue *Q,int a)
{
if (Q->rear->data == a)
{
printf("%d->%d\n", a, a);
return OK;
}

int i = 0;
int j;
int num[MAX_VERTEX_NUM] = { 0 };
while (Q->rear->data!=a)//倒序进入数组
{
num[i] = Q->rear->data;
Q->rear = Q->rear->pre;
i++;
}
printf("%d", a);
for (j = i - 1; j >= 0; j--)
{
printf("->%d", num[j]);
}


printf("\n");
return OK;
}
int main()
{
int i;
int j;

MGraph Graph;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C/C++代码中,我们习惯于使用小写字母打头的单词表示一个变量。大写字母开头的单词,我们的编码风格惯例是留给结构体函数名方法的。

CreateUDN(&Graph);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CreateUDN 有个返回值,再判断一下返回值就更有范儿了~

for (i = 1; i <= Graph.vexnum; i++)
{
for (j = 1; j <= Graph.vexnum; j++)
{
LinkQueue Q;
InitQueue(&Q);
printf("%d<->%d:", i, j);
BFSTraverse(&Graph, &Q, i, j);
print(&Q, i);
DestroyQueue(&Q);
}
}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading