一、SLF(Small Label First) 优化
优化思路:将原队列改成双端队列,对要加入队列的点 p,如果 dist[p] 小于队头元素 u 的 dist[u],将其插入到队头,否则插入到队尾。
//SLF优化
void spfa_slf(int s,int t,GH *G)//起点s,终点t,图G
{
//节点编号从0开始
int n=G->vexnum;//节点个数
int *dist=new int[n];//距离数组
bool *visit=new bool[n];//访问标记数组
int *pre=new int[n];;//前驱
AR *p;
//初始化
memset(dist,0x3f,n*sizeof(int));
memset(visit,0,n*sizeof(bool));
memset(pre,-1,n*sizeof(int));
deque<int>Q;//建立双端队列,并将起点入队
visit[s]=1;
dist[s]=0;
Q.push_back(s);
//进行操作
while (!Q.empty())
{
int cur=Q.front();
Q.pop_front();
visit[cur]=0;//出队节点取消标记
p=G->N[cur].next;
while (p)//遍历出队节点的直接后继
{
if (dist[p->index] > dist[cur] + (p->weight))//需要进行松弛操作
{
dist[p->index]=dist[cur] + (p->weight);
pre[p->index]=cur;
if (!visit[p->index])
{
visit[p->index]=1;
if(!Q.empty() && dist[p->index] < dist[Q.front()])//根据dist[p->index]与dist[Q.front()]的大小关系,决定p->index插入到队头还是队尾
Q.push_front(p->index);
else
Q.push_back(p->index);
}
}
p=p->next;
}
}
if (dist[t] == INF)
cout<<"两点不连通."<<endl;
else//输出最短路径
{
cout<<"存在长度为"<<dist[t]<<"的最短路径:"<<endl;
int *path=new int[n];//存放路径
int top=-1;
int q=t;
while (q != -1)//将前驱入栈
{
top++;
path[top]=q;
q=pre[q];
}
for (; top > 0; top--)
cout<<G->vexname[path[top]]<<"-->";
cout<<G->vexname[path[0]]<<endl;
delete []path;
}
delete []dist;
delete []visit;
delete []pre;
}
二、LLL(Large Label Last) 优化
优化思路:对每个要出队的队头元素 u,比较 dist[u] 和队列中点的 dist 的平均值,如果 dist[u] 更大,将其弹出放到队尾,然后取队首元素进行相同操作,直到队头元素的 dist 小于等于平均值。
//LLL优化
void spfa_lll(int s,int t,GH *G)//起点s,终点t,图G
{
//节点编号从0开始
int n=G->vexnum;//节点个数
int *dist=new int[n];//距离数组
bool *visit=new bool[n];//访问标记数组
int *pre=new int[n];//前驱数组
int num;//队列中点的个数
int sum;//队列中点的dist之和
AR *p;
//初始化
memset(dist,0x3f,n*sizeof(