很累很累!!!花了快一周的时间,是真的笨 ,不过还是很开心。
具体思考方式如下:
首先 我们要根据图,确定一个邻接矩阵---》可以表示两个顶点之间是否关联,且当关联时可以表示具体的权重。
其次,定义两个数组,集合......例如:一个数组A:用来储存起点到每个顶点的最短距离,数组B:用来储存还没有确定的顶点,以及顶点到起点的距离。
假设起点为:a,设无穷大为 INF, 顶点个数为 :V
然后,确认起点,根据起点初始化数组A和数组B,数组A初始化之后为:A[] ={(a,0)}---》因为此时只确定了起点;数组B初始化之后 B[] = {(b,INF),(c,INF),(d,INF),(e,INF),(f,INF),(g,INF)......,,(z,INF)}
显然此时数组A的长度为:1,数组B的长度为: V-1,当数组A的长度为V时遍历也就结束了。
程序,所对应的图。实在是懒得再画一次了。凑活着看看吧。
具体操作:
其实就是对数组A的填充,对数组B的数据删除。
首先根据确定的顶点:a ,寻找其关联的点,然后修改所关联的点到起点a的距离,修改成功之后,得到新的数组B,将数组B中最小的权重值所对应的点添加到数组A中,然后在数组B中删除该点对应的元素;
然后再根据刚刚确定的权重最小的点为新的遍历起点(注意:这里仅仅是新的遍历起点不是换了起点!!!!),再次寻找其关联的点,然后修改所关联的点到起点a的距离。。。一直持续到所有的点遍历完成,也就是数组A的长度 = V。
而修改关联点的唯一尺度就是他的本身定义:数组B储存的是每个点到达起点的最短路径。如果最短路径上的点之和 << 该点直接到达起点的权重,那就修改,如果没有那就不修改。
例如:
AB+BC《AC,所以数组B中的元素c的权重要修改为 AB+BC =10 而非原来的 17
而像这种情况,顶点A和顶点C没有连线,也就是A与C之间不关联 根据初始化 AC = INF(无穷大)所以此时肯定是 AB+BC《AC,所以数组B中的元素c的权重要修改为 AB+BC =10 而非原来的INF。
还有一种情况:
AB+BC》》AC,所以此时C在数组B中的权重仍然为 7 。
好了最精华的东西,这最中心的内容都在这了。具体细节 在代码中,我注释的很明显。有想法的同学们可以自行优化一下,确实只是为了实现功能没有注意其他的细节。
这次本来是 用java写的 但是中途还是没坚持下来,正确在在最近一周吧java部分的也搞出来。
加油!!!奥利给!!!!
代码如下:
#define _CRT_SECURE_NO_WARNINGS//必须定义在预处理命令之前---》4996
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define V 5//V:顶点个数
//数据结点
typedef struct node {
char name;
int num ;
}node;
typedef struct Node {
node date[V] ;
int len;
};
//结点初始化
void Inin(Node *& a) {
a = (Node *)malloc(sizeof(Node));
int Len =a->len= V;
//结点中全为1000 意指无穷大
//初始化 name值
for (int i = 0; i < Len; i++) {
a->date[i].name = (char)(65 + i);
a->date[i].num = 1000;
}
}
//数据的删除
void Delete(Node *& a,char name) {
int i = a->len,j=0;
while (j < i) {
if (a->date[j].name == name) {
break;
}
j++;
}
while (j < i) {
a->date[j++] = a->date[j + 1];
}
a->len--;
}
//数据修改---》进行关联判断之后,修改num值
void Update(Node*& a, char name, int num) {
Node* p = a;
int i = 0,j = 0;
while (i<p->len) {
if (p->date[i].name == name) { p->date[i].num = num; }
i++;
}
}
//数据判断--->目的:返回最小路径的结点值
node Judge(Node*& a) {
node s;
Node* p = a;
int len = p->len;
int i, j, k = 10000;
for (i = 0; i < len; i++) {
if (p->date[i].num < k) {
j = i;
k = p->date[i].num;
}
}
s = p->date[j];
return s;
}
//数据添加---》添加结点值
void add(Node*& a, node s) {
Node* p = a;
p->date[p->len++] =s;
}
//数据求址1--》根据name找到对应的num
int index(Node* a,int nameNum) {
char c;
int i = 0;
switch (nameNum)
{
case 0:c='A'; break;
case 1:c='B'; break;
case 2:c='C'; break;
case 3:c='D'; break;
case 4:c='E'; break;
}
while (a->date[i].name != c) {
i++;
}
return a->date[i].num;
}
//数据求址2--》根据name找到对应的i--->0:A 1:B...
int Index(Node* a, char name) {
Node* p = a;
int i=0;
while (p->date[i].name != name && i<p->len) {
i++;
}
if (p->date[i].name != name) {
return -1;
}
return i;
}
void main() {
int t[V][V] = {
{0,1000,2,5,4},
{1000,0,1,3,3},
{2,1,0,4,2},
{5,3,4,0,1000},
{4,3,2,1000,0}
};
Node* U, * S;//S为记录已求出最短路径的顶点;U则是记录还未求出最短路径的顶点--->包含距离
Inin(U); Inin(S);
int i = 0, j = 0,k = 0;
//设置起点
printf("请设置起点:(注意是大写):\n");
char First /*= 'E'*/;
scanf("%c", &First);
while (i < S->len)
{
if (S->date[i].name == First) {
S->date[0].name = First;
S->date[0].num = 0;
S->len = 1;
}
i++;
}
i = Index(U, S->date[0].name);//从起点开始遍历
Delete(U, First);
node t0 = Judge(U);
t0.name = 'z';//这里的Z是随便定义的字符 ,必须是一个顶点数组中没有的元素
//目的是确保在顶点数组中没有找到对应的点从而避免损失一次关联
//具体指的是 j==Index(U,t0.name)
for (k=0; k < V; k++) {
for (j = 0; j < V; j++) {
if (t[i][j] == 1000 || t[i][j] == 0 || j==Index(U,t0.name)) {
continue;
}
int s = 0;
if (k == 0) {
s = t[i][j];
switch (j)
{
case 0: {
Update(U, 'A', s); break;
}
case 1: {
Update(U, 'B', s); break;
}
case 2: {
Update(U, 'C', s); break;
}
case 3: {
Update(U, 'D', s); break;
}
case 4: {
Update(U, 'E', s); break;
}
}
}
else if ((t[i][j] + t0.num) < index(U, j)) {
s = t[i][j] + t0.num;
switch (j)
{
case 0: {
Update(U, 'A', s); break;
}
case 1: {
Update(U, 'B', s); break;
}
case 2: {
Update(U, 'C', s); break;
}
case 3: {
Update(U, 'D', s); break;
}
case 4: {
Update(U, 'E', s); break;
}
}
}
}
node x = Judge(U);
t0 = x;
Update(S, x.name, x.num);
Delete(U, x.name);
add(S, x);
if (S->len == V) {
break;
}
switch (x.name)
{
case 'A':i = 0; break;
case 'B':i = 1; break;
case 'C':i = 2; break;
case 'D':i = 3; break;
case 'E':i = 4; break;
}
}
//打印起点到每个顶点最近距离
for (i=0; i < S->len; i++) {
printf("( %c , %d )\t", S->date[i].name, S->date[i].num);
}
}