算法导论24.3章中算法的C++实现,代码如下:
/********************************************************************
* Copyright (C) 2012 Li Yachao
* Contact: liyc7711(at)gmail.com
*
* Permission to use, copy, modify, and distribute this software for
* any non-commercial purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both
* that copyright notice.
* It is provided "as is" without express or implied warranty.
*********************************************************************/
#include <iostream>
using namespace std;
#define N 5 /*顶点的数目*/
#define INFINITE 0x7fffffff
//顶点结点结构
struct Vertex
{
Vertex * next;/*指向下一个顶点*/
int id;/*节点的标志*/
int weight;/*节点的权值,临界表表头到此元素上边的权值*/
Vertex():next(NULL),id(0){}
};
//图结构
struct Graph
{
Vertex *Adj[N+1];//N个顶点及邻接点头指针
int p[N+1];//指向遍历树节点的父结点
int d[N+1];/*节点的最短路径权值的上界*/
bool s[N+1];/*当前节点是否访问过*/
Graph()
{
for(int i = 1; i <= N; i++)
{
Adj[i] = new Vertex;
d[i] = 0;
p[i] = 0;
s[i] = false;
}
}
~Graph()
{
for(int i = 1; i <= N; i++)
delete Adj[i];
}
};
/******最小优先级队列实现***************************************/
int Tail = 0;
std::pair<int,int> PriorStack[N+1];
bool Push(std::pair<int,int>p);
void PrintList();
bool inline Exchange(int index1,int index2);
bool inline Clear(int index);
int Pop();
/******算法实现***************************************/
void Print(Graph *g);
bool Init(Graph *g);
bool InsertEdge(Graph *g , int start,int end,int weight);
bool InitializeSingleSource(Graph *g,int s);
bool Relax(Graph *g,int u,int v,int weight);
bool Relax(Graph *g,int u,int v);
int Weight(const Graph *g,int u,int v);
bool Dijkstra(Graph *g,int s);
int ExtractMin(Graph *g);
bool UpdateKey(Graph *g);
/******最小优先级队列实现***************************************/
void PrintList()
{
for(int i=1;i<=Tail;i++)
{
std::cout<<PriorStack[i].first<<"\t";
}
std::cout<<std::endl ;
}
/*向优先级队列插入元素,最大的元素在队列首部*/
bool Push(std::pair<int,int>p)
{
if(Tail >= N)
{
return false;/*溢出*/
}
Tail ++;
PriorStack[Tail] = p;
int cur = Tail/2;
if(cur < 1)
{
return true;
}
int t = Tail;
while(true)
{/*依次于其父节点比较,如果小于则交换元素*/
if(PriorStack[t].second < PriorStack[cur].second)
{
Exchange(t,cur);
}
t = cur;
cur = cur/2;
if(cur == 0)
{
break;
}
}
}
/*弹出优先级最高的元素,一般为最大值*/
int Pop()
{
if(Tail < 1)
{
return -1;
}
int val = PriorStack[1].first;
Exchange(1,Tail);/*尾部元素与首部元素交换*/
Clear(Tail);
Tail --;
int p = 1;
int cur = 2*p;
while(true)
{/*如果父节点元素小于子节点元素则予以交换*/
if(PriorStack[p].second > PriorStack[cur].second)
{
Exchange(p,cur);
}
p = cur;
cur = p *2;
if(p >= Tail)
{
break;
}
}
return val;
}
/*交换两个位置上的元素*/
bool inline Exchange(int index1,int index2)
{
std::pair<int,int> tmp = PriorStack[index2];
PriorStack[index2] = PriorStack[index1];
PriorStack[index1] =tmp;
return true;
}
/*清空某个位置的元素*/
bool inline Clear(int index)
{
PriorStack[index].first = 0;
return true;
}
/*清空最小优先级队列*/
bool Clear()
{
int Tail = 0;
return true;
}
/******end最小优先级队列实现***************************************/
/*
start边开始节点,end边结束节点,weight边权值
*/
//插入边
bool InsertEdge(Graph *g , int start,int end,int weight)
{
Vertex* v = new Vertex();
v->id = end;
v->weight = weight;
if(g->Adj[start]->next == NULL)
{/*如果不存在临界表的头结点列表中,则插入*/
Vertex* s = new Vertex();
s->id = start;
g->Adj[start] = s;
}
Vertex* tmp = g->Adj[start];
while(tmp->next)
{
tmp = tmp->next;
}
tmp->next =v;
return true;
}
/*初始化邻接表表示的图,有向图。
*/
bool Init(Graph *g)
{
InsertEdge(g,1,2,10);
InsertEdge(g,1,4,5);
InsertEdge(g,2,3,1);
InsertEdge(g,2,4,2);
InsertEdge(g,3,5,4);
InsertEdge(g,4,2,3);
InsertEdge(g,4,3,9);
InsertEdge(g,4,5,2);
InsertEdge(g,5,1,7);
InsertEdge(g,5,3,6);
return true;
}
/*取得两个两个节点连接的边的权重*/
int Weight(const Graph *g,int u,int v)
{
Vertex * t = g->Adj[u]->next;
while(t)
{
if(t->id == v)
{
return t->weight;
}
t = t->next;
}
return 0;
}
bool Relax(Graph *g,int u,int v,int weight)
{
if(g->d[v] > (g->d[u] + Weight(g,u,v)))
{
g->d[v] = g->d[u] + Weight(g,u,v);
g->p[v] = u;
}
return true;
}
/*对边进行松弛操作*/
bool Relax(Graph *g,int u,int v)
{
Relax(g,u,v,Weight(g,u,v));
return false;
}
/*
最短路径估计和前驱化进行初始化
s 源顶点
*/
bool InitializeSingleSource(Graph *g,int s)
{
for(int i=1;i<=N;i++)
{
g->d[i] = INFINITE;
g->p[i] = 0;
}
g->d[s] = 0;
return true;
}
/*抽取顶点的路径权值最小的节点*/
int ExtractMin(Graph *g)
{
UpdateKey(g);
return Pop();
}
/*更新顶点的最小优先级队列*/
bool UpdateKey(Graph *g)
{
Clear();
for(int i=1;i<=N;i++ )
{
if(g->s[i] != true)
{
Push(std::make_pair<int,int>(i,g->d[i]));
}
}
return true;
}
/*单源最短路径的Dijkstra算法*/
bool Dijkstra(Graph *g,int s)
{
InitializeSingleSource(g,s);
int vertex = ExtractMin(g);
while(vertex >= 0)
{
g->s[vertex] = true;
Vertex * t = g->Adj[vertex]->next;
while(t)
{
Relax(g,vertex,t->id);
t = t->next;
}
vertex = ExtractMin(g);
}
return true;
}
/*
开始顶点 1
顶点 最短路径
1 0
2 8
3 9
4 5
5 7
*/
int main(int argc,char * argv[])
{
Graph *g = new Graph;
Init(g);
Dijkstra(g,1);
for(int i=1;i<=N;i++)
{
std::cout<<i<<"\t"<<g->d[i]<<std::endl;
}
delete g;
getchar();
return 0;
}