邻接表实现prim算法c语言,邻接表实现PRIM算法(C++)

参考张宪超老师《数据结构、算法及应用》

原理:

G=是一个连通的带权无向图。Prim算法通过不断地增加生成树的顶点来得到最小生成树。在算法的任一时刻,一部分顶点已经添加到生成树的顶点集合中,而其余顶点尚未加到生成树中。此时,Prim算法通过选择边,使得的权值是所有u(起点)在生成树中,但v(终点)不在生成树中的边的权值最小者,从而找到新的顶点v把她添加到生成树中。

详细步骤:

1)初始状态,U={u1},TE={}。其中,u1是图顶点集合的某一顶点。

2)在所有u∈U,v∈V-U的边(u,v)中寻找代价最小的边(u',v'),并纳入集合TE中;同时将v'纳入集合U中。确保这一过程中不产生回路。

3)如果u=v,则算法结束;否则重复2.

代码实现:

#include

#include

using namespace std;

class edge{

public:

int start;

int end;

int weight;

edge(int strt,int ed,int w){

start=strt;

end=ed;

weight=w;

}

edge(){

start=-1;

end=-1;

weight=-1;

}

};

//邻接表

class listnode{

public:

int listver;

int edgenam;

int weight;

listnode * next;

listnode(listnode * nextval=NULL){

next=nextval;

}

listnode(const int& lv,const int& en,const int &

w,listnode* nextval=NULL){

listver=lv;

edgenam=en;

weight=w;

next=nextval;

}

};

class headnode{

public:

listnode *start;

headnode(){

start=new listnode();

}

void removeall(){

listnode *tmp;

while(start!= NULL){

tmp=start;

start=start->next;

delete tmp;

}

}

~headnode(){

removeall();

}

};

class listgraph{

private:

headnode* gralist;

public:

int vertexnum;

int edgenum;

int *mark; //访问过为1,未访问为0;

listgraph(int n){

vertexnum=n;

edgenum=0;

mark=new int[vertexnum];

for(int i=0;i

mark[i]=0;

gralist=new headnode[vertexnum];

}

~listgraph(){

delete[]mark;

delete[]gralist;

vertexnum=0;

edgenum=0;

}

edge firstedge(int v){

edge tmpedge;

tmpedge.start=v;

listnode* tmplst=gralist[v].start;

if(tmplst->next!=NULL)

{

tmpedge.end=tmplst->listver;

}

return tmpedge;

}

edge nextedge(edge oneedge){

edge tmpedge;

tmpedge.start=oneedge.start;

listnode* tmplst=gralist[oneedge.start].start;

while(tmplst->next!=NULL&&tmplst->next->listver<=oneedge.end)

tmplst=tmplst->next;

if(tmplst->next!=NULL)

{

tmpedge.end=tmplst->next->listver;

}

return tmpedge;

}

void setedge(int strt,int end,int wt){

listnode* tmplst=gralist[strt].start;

while(tmplst->next!=NULL&&tmplst->next->listver

tmplst=tmplst->next;

//确定该边在边结点插入位置

//边在边结点中不存在

if(tmplst->next==NULL){

tmplst->next=new listnode;

tmplst->next->listver=end;

tmplst->next->edgenam=edgenum;

tmplst->next->weight=wt;

edgenum++;

setedge(end,strt,wt);

return;

}

//边在边结点中已存在

if(tmplst->next->listver==end){

edgenum--;

return;

}

//边在边结点中不存在,但在边表中其后存在其他边

if(tmplst->next->listver>end)

{

listnode* tmp=tmplst->next;

tmplst->next=new listnode;

tmplst->next->listver=end;

tmplst->next->edgenam=edgenum;

tmplst->next->next->weight=wt;

tmplst->next->next=tmp;

edgenum++;

setedge(end,strt,wt);

return;

}

}

void deledge(int start,int end){

listnode* tmplst=gralist[start].start;

while(tmplst->next!=NULL&&tmplst->next->listver

tmplst=tmplst->next;

if(tmplst->next==NULL){

cout<

return;

}

if(tmplst->next->listver==end)

{

listnode * tmp=tmplst->next->next;

delete tmplst->next;

tmplst->next=tmp;

edgenum--;

}

}

void show(int v){

cout<

if(gralist[v].start!=NULL)

{

listnode* tmp=gralist[v].start;

// cout<"<listver<

"<edgenam;

while(tmp->next!=NULL)

{

tmp=tmp->next;

cout<"<listver<

"<edgenam;

}

}

return;

}

void show(){

cout<

cout<

cout<

cout<

for(int i=0;i

{

show(i);

cout<

}

return;

}

void visit(int v){

cout<

}

edge * prim(int s){

int i,j;

edge *mst; //存储最小生成树的边

int *nearest; //nearest[i]表示生成树中点到i点的最小边""权值""

int *neighbor; //neighbor[i]表示生成树中与i点最近的""点编号"",

//-1表示i点已经在生成树集合中

int n=vertexnum;

nearest= new int[n];

neighbor=new int [n];

mst=new edge [n-1];

for(i=0;i

{

neighbor[i]=s;

nearest[i]=100;

}

for(listnode* tmp=gralist[s].start->next;tmp!=

NULL;tmp=tmp->next)

{

nearest[tmp->listver]=tmp->weight;

}

neighbor[s]=-1;//将已加入到生成树的点的最近邻设置成-1

for(i=1;i

//用i标记已经加入到生成树中的点个数

int min=100;

int v=-1;

for(j=0;j

//确定一个顶点在生成树集合一个顶点不在生成树集合且权值最小

//的边所关联的顶点

if(nearest[j]-1){

min=nearest[j];

v=j;

}

}

if(v>=0){

//将V加入到生成树集合中,更新生成树外的各个点最小权值的边信息

edge tempedge(neighbor[v],v,nearest[v]);

mst[i]=tempedge;//将边加入到生成树集合中

neighbor[v]=-1;

for(listnode*

tmp=gralist[v].start->next;tmp!=NULL;tmp=tmp->next){

int u=tmp->listver;

if(neighbor[u]!=-1&&nearest[u]>tmp->weight){

//用于V关联的边更新生成树之外顶点到生成树集合的最小权值边

neighbor[u]=v;

nearest[u]=tmp->weight;

}

}

}

}

delete[]neighbor;

delete[]nearest;

cout<

V"<

for(i=1;i

{

cout<

"<

"<

}

return mst;

}

};

int main(){

listgraph graph=listgraph(6);

graph.setedge(0,1,6);

graph.setedge(0,2,1);

graph.setedge(0,3,5);

graph.setedge(1,2,5);

graph.setedge(1,4,3);

graph.setedge(2,3,5);

graph.setedge(2,4,6);

graph.setedge(2,5,4);

graph.setedge(3,5,2);

graph.setedge(4,5,6);

graph.show();

graph.prim(1);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是邻接表Prim算法实现: ``` #include <iostream> #include <vector> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; const int INF = 0x3f3f3f3f; struct Edge { int to, weight; Edge(int t, int w) : to(t), weight(w) {} }; vector<Edge> G[MAXN]; // 邻接表 int dist[MAXN]; // 到MST的最短距离 bool vis[MAXN]; // 是否已加入MST int n, m; struct Node { // 用于优先队列中的比较 int u, d; Node(int u, int d) : u(u), d(d) {} bool operator<(const Node &rhs) const { return d > rhs.d; } }; void Prim(int start) { memset(dist, INF, sizeof(dist)); memset(vis, false, sizeof(vis)); dist[start] = 0; priority_queue<Node> pq; pq.push(Node(start, 0)); while (!pq.empty()) { int u = pq.top().u; pq.pop(); if (vis[u]) continue; vis[u] = true; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i].to; int w = G[u][i].weight; if (!vis[v] && w < dist[v]) { dist[v] = w; pq.push(Node(v, dist[v])); } } } } int main() { cin >> n >> m; for (int i = 1; i <= m; i++) { int u, v, w; cin >> u >> v >> w; G[u].push_back(Edge(v, w)); G[v].push_back(Edge(u, w)); } Prim(1); int ans = 0; for (int i = 1; i <= n; i++) { if (dist[i] == INF) { // 无法到达 cout << "No MST!" << endl; return 0; } ans += dist[i]; } cout << "MST weight: " << ans << endl; return 0; } ``` 说明: 1. 首先我们定义了一个邻接表`G`,其中`G[i]`表示编号为`i`的点所连接的所有边。 2. 然后,我们定义了一个距离数组`dist`,表示每个点到MST的最短距离,初始时全部赋值为INF。 3. `vis`表示每个点是否已经被加入MST,初始时全部赋值为false。 4. 首先将起点加入MST,然后将起点的所有邻接点加入优先队列中,其中优先队列按照到MST的距离从小到大排序。 5. 从优先队列中取出距离MST最近的点u,并将其加入MST中。 6. 然后,遍历u的所有邻接点v,如果v未被加入MST且u到v的距离比目前v到MST的距离更短,则更新dist[v]的值,并将v加入优先队列。 7. 重复步骤5和6,直到所有点都被加入MST为止。 8. 最后遍历dist数组,如果有点无法到达MST,则说明无法构建MST,输出"No MST!",否则输出MST的总权值。 时间复杂度:$O(m\log n)$,其中$m$为边数,$n$为点数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值