算法勘误 图.docx
《算法勘误 图.docx》由会员分享,可在线阅读,更多相关《算法勘误 图.docx(16页珍藏版)》请在冰豆网上搜索。
算法勘误图
邻接表:
#definemax_vertex_num20//最大顶点数
structarcnode
{
intadjvex;
structarcnode*nextarc;
infotypeinfo;//和弧有关的其它信息
};
typedefstructarcnode*arcptr;
typedefstructvexnode
{
vextypevexdata;//和顶点有关的信息
arcptrfirstarc;
}adjlist[max_vertex_num+1];
算法6.1
voidsetadjlist(adjlistgraph)//根据所读入的边,建立图的邻接表graph
{
intv1,v2,i;
for(i=1;i<=max_vertex_num;i++)
graph[i].firstarc=NULL;
arcptrp=NULL,q=NULL;
scanf("%d%d",&v1,&v2);//读入第一条边(v1,v2)
while(v1!
=0)//边的结束标志v1=0
{
q=(arcptr)malloc(sizeof(arcnode));
q->adjvex=v2;q->nextarc=NULL;
if(graph[v1].firstarc==NULL)
graph[v1].firstarc=q;
else
{
p=graph[v1].firstarc;
while(p->nextarc!
=NULL)
p=p->nextarc;
p->nextarc=q;
}
scanf("%d%d",&v1,&v2);//读下一条边
}
}//endofsetadjlist
十字链表形式:
structarctype
{
inttailvex,headvex;
arctype*hlink,*tlink;
};
typedefstructarctype*arclink;
typedefstructvnode
{
vertexdata;
arclinkfirstin,firstout;
}ortholist[max_vertex_num+1];
算法6.2
voidcrt_ortho(ortholistga)//建立有向图的十字链表存储结构
{
intn,e,k,i,j;
arclinkp,q;
scanf("%d%d",&n,&e);//输入顶点和弧的数目
getchar();
for(i=1;i<=n;i++)
{
scanf("%c",&ga[i].data);//输入顶点信息的函数
ga[i].firstin=NULL;ga[i].firstout=NULL;//指针初始化
}
for(k=1;k<=e;k++)
{
scanf("%d%d",&i,&j);//输入弧的信息,i是弧尾顶点的编号,j是弧头顶点的编号
q=(arclink)malloc(sizeof(arclink));
q->headvex=j;
q->tailvex=i;
q->hlink=q->tlink=NULL;
if(NULL==ga[j].firstout)
ga[j].firstout=q;
else
{
p=ga[j].firstout;
while(p->tlink)
p=p->tlink;
p->tlink=q;
}
if(NULL==ga[i].firstin)
ga[i].firstin=q;
else
{
p=ga[i].firstin;
while(p->hlink)
p=p->hlink;
p->hlink=q;
}//将弧结点分别插入到两个链表中
}
}//endofcrt-ortho
边集数组:
structedge//定义边集数组的元素类型
{
intfromvex;//边的起点域
intendvex;//边的终点域
intweight;//边的权值域,对应无权图可省去此域
};
typedefstructedgeedgeset[max_arc_num+1];//定义edgeset为边集数组类型
voidcreatedgeset(vextypegv[],edgesetge,intn,inte)
{//通过从键盘上输入的n个顶点信息和e条边的信息
//建立顶点数组gv和边集数组ge
inti,k,j,w;
for(i=1;i<=n;i++)
scanf("%c",&gv[i]);//输入顶点信息
for(k=1;k<=e;k++)
{
scanf("%d%d%d",&i,&j,&w);//输入一条边的起点、终点和权值
ge[k].fromvex=i;
ge[k].endvex=j;
ge[k].weight=w;
}
}
算法6.2(遍历)
voiddfs(adjlistg,intv0,int*visited)
{
arcptrp;
visite(g,v0);
visited[v0]=1;
p=g[v0].firstarc;
while(p!
=NULL)
{
if(!
visited[p->adjvex])
dfs(g,p->adjvex,visited);
p=p->nextarc;
};
}
voiddfs_begin(adjlistg,intv0,intn)
{//假设图G有n个顶点,用邻接表存储G,DFS遍历图G
arcptrp;
inti;
int*visited;
visited=(int*)malloc(sizeof(int)*(n+1));
for(i=1;i<=n;i++)
visited[i]=0;
visite(g,v0);
visited[v0]=1;
p=g[v0].firstarc;
while(p!
=NULL)
{
if(!
visited[p->adjvex])
dfs(g,p->adjvex,visited);
p=p->nextarc;
};
};//endofdfs
算法6.3:
voidunrecurrentdfs(adjlistg,integerv0,intn)
{//假设图G用邻接表存储,从顶点v0出发非递归地DFS图G,stack是一栈
inti;
arcptrp;
int*visited;
int*stack;
stack=(int*)malloc(sizeof(int)*(n+1));
visited=(int*)malloc(sizeof(int)*(n+1));
for(i=1;i<=n;i++)
visited[i]=0;
visite(g,v0);
visited[v0]=1;
i=1;//i为栈顶指针
stack[i]=v0;//v0进栈
p=g[v0].firstarc;
while(i!
=0)//若栈不空
{
while(p!
=NULL&&visited[p->adjvex])
p=p->nextarc;
if(!
p)//顶点p的所有邻接点都已访问过了
{
i=i-1;//退栈
if(i)
p=g[stack[i]].firstarc;//p取新的栈顶元的邻接点
}
else
{
visite(g,p->adjvex);
visited[p->adjvex]=1;
i=i+1;
stack[i]=p->adjvex;
p=g[p->adjvex].firstarc;
}
}
};//endofunrecurrrntdfs
算法6.4:
voidbfs(adjlistg,intv0,intn)
{//从v0出发广度优先遍历图G
int*visited;
intw,v;
inti;
arcptrp;
visited=(int*)malloc(sizeof(int)*(n+1));
for(i=1;i<=n;i++)
visited[i]=0;
visite(g,v0);
visited[v0]=1;
QueueQ;
iniqueque(&Q);//初始化设置空队列Q
enqueque(&Q,v0);//v0进队列Q
while(!
empty(&Q))//当队列不空时
{
v=dequeque(&Q);//队头元素v出队列
p=g[v].firstarc;//v的第一个邻接点
while(p)//w不是最后一个邻接点
{
w=p->adjvex;
if(!
visited[w])
{
visite(g,w);
visited[w]=1;
enqueque(&Q,w);//顶点w进队列Q
}
p=p->nextarc;//求下一个邻接点
//求顶点w的下一个邻接点,若w是v的最后一个邻接点,则函数nextadj的值为0
}
}
};//endofbfs
算法6.5
voidcomp(adjlistg,intn)
{//用DFS或BFS求g的连通分量
intvi;
int*visited;
visited=(int*)malloc(sizeof(int)*(n+1));
for(vi=1;vi<=n;vi++)
visited[vi]=0;//标志数组初始化
for(vi=1;vi<=n;vi++)
if(!
visited[vi])
{
printf("aconnectedcomponentis");
dfs(g,vi);//深度遍历,标志数组已经初始化,与前面的dfs算法不同
}
}//ofcomp
算法6.6
#definen//...//网的顶点数
#definemaxi//网中权的最大值小于maxi
typedefintcosttype[n+1][n+1];//下标从1开始
voidprim(costtypecost)
{
intlowcost[n+1];
intclosest[n+1];
inti,j,k,min;
for(i=2;i<=n;i++)
{
lowcost[i]=cost[1][i];
closest[i]=1;
}
for(i=2;i{
min=maxi;
k=0;
for(j=2;j<=n;j++)
if((lowcost[j]=0))
{
min=lowcost[j];
k=j;
}
printf("%d%5d\n",k,closest[k]);//输出生成树的边
lowcost[k]=0;//k加入u
closest[k]=0;
for(j=2;j<=n;j++)//调整代价
if((cost[k][j]=0))
{
lowcost[j]=cost[k][j];
closest[j]=k;
}
}//endfor
}//endofprim
Kruscal算法:
这里我想了一个时间复杂度比较好的算法:
#definemax_arc_num//最大边数
#definev_max//最大顶点数
voidkruscal(edgesetgraph,intr[max_arc_num+1])
{//r[]存放结果r[i]为1的话graph[i]边存在
intresult[max_arc_num+1];
inttimes=1;
inttemp;
intnow=1;
inti,j;
intfirst,second;
for(i=1;i<=max_arc_num;i++)
{
result[i]=0;
r[i]=0;
}
while(times{
first=graph[now].endvex;
second=graph[now].fromvex;
if(0==result[first]&&0==result[second])
{
result[first]=result[second]=now;
r[now]=1;
times++;
}
else
if(0==result[first]||0==result[second])
{
if(0==result[first])
result[first]=result[second];
else
result[second]=result[first];
times++;
r[now]=1;
}
else
if(result[first]!
=result[second])
{
times++;
temp=result[second];
for(j=1;j<=max_arc_num;j++)
{
if(temp==result[j])
result[j]=result[first];
}
r[now]=1;
}
now++;
}
}
算法6.7:
#defineM//图中顶点个数的最大值
#defineNM+1
#defineLENsizeof(structarcnode)
structarcnode
{intadjvex;
structarcnode*nextarc;
};
structvexnode
{intvexdata;
intindegree;
structarcnode*firstarc;
};
voidcrt_adjlist(structvexnodedig[N])//读入有向边,建立图G的邻接表
{
structarcnode*p;
intk,m,i;
for(i=1;i<=N;i++)//表头结点初始化
{
dig[i].vexdata=i;
dig[i].firstarc=NULL;
dig[i].indegree=0;
}
printf("\npleaseinputthearc\n");
scanf("%d%d",&k,&m);//k为弧尾,m为弧头
while(!
(k==0&&m==0))//生成邻接表,表头结点的degree域为每个顶点的入度
{
p=(structarcnode*)malloc(LEN);
p->adjvex=m;
p->nextarc=dig[k].firstarc;//新的弧结点插入在单链表的表头
dig[k].firstarc=p;
dig[m].indegree++;//入度加1
scanf("%d%d",&k,&m);
}
}
voidtopsort(structvexnodedig[N])//拓扑排序
{
intm,i,j,top,k,stack[N];
structarcnode*q;
top=-1;//栈初始化
for(i=1;i<=N;i++)//入度为零的顶点进栈
if(dig[i].indegree==0)
stack[++top]=i;
m=0;//输出顶点的计数器
while(top!
=-1)//栈不空
{
j=stack[top--];//j取栈顶元素,栈顶元素退栈
printf("%5d",dig[j].vexdata);
m++;
q=dig[j].firstarc;//在邻接表上查找j的所有后继k,将k的入度减1
while(q!
=NULL)
{
k=q->adjvex;
if(--dig[k].indegree==0)stack[++top]=k;//若k的入度为零,让k进栈
q=q->nextarc;
}
}
if(m}
算法6.8:
#defineN6//顶点数
#defineMAX1000//max是计算机允许的最大值
voidshortpath(intcost[N][N],intv)
{//cost为带权有向图的邻接矩阵,v为指定的源点,数据从0开始储存
intdist[N],s[N],rear[N];//dist[i]为当前源点到顶点i的最小距离,s表示相应顶点是否并入集合的标志
intq[N][N];//到i顶点的最短路径存储在队列q[i]中,队头指针为0,队尾指针存储在rear[i]中。
inti,j,k,win,m;
for(i=0;i{
s[i]=0;
rear[i]=-1;
}
for(i=0;i{
dist[i]=cost[v][i];
if(dist[i]{
q[i][++rear[i]]=v;
q[i][++rear[i]]=i;
}
}
s[v]=1;//v并入集合
for(k=0;k{
win=MAX;j=v;
for(i=1;iif(s[i]==0&&dist[i]{
j=i;win=dist[i];}
if(j!
=i)
{
s[j]=1;
printf("\nthe%d'sshortestdistanceis%d\n",j,dist[j]);
for(i=0;i<=rear[j];i++)
printf("%5d",q[j][i]);//打印从源点到j的最短路径
for(i=1;iif(s[i]==0&&((dist[j]+cost[j][i]){
dist[i]=dist[j]+cost[j][i];
for(m=0;m<=rear[j];m++)
q[i][m]=q[j][m];//修改相应的路径
rear[i]=rear[j];
q[i][++rear[i]]=i;
}//if
}//if
}//for
}//end
算法6.9
voidfloyed(intgraph[MAX+1][MAX+1],intpath[MAX+1][MAX+1][MAX+1])//下标从1开始
{
inti,j,k,l,n,m;
inta[MAX+1][MAX+1];
for(k=1;k<=MAX;k++)
for(i=1;i<=MAX;i++)
for(j=1;j<=MAX;j++)
path[i][j][k]=0;
for(i=1;i<=MAX;i++)
for(j=1;j<=MAX;j++)
{
if(0!
=graph[i][j])
{
a[i][j]=graph[i][j];
path[i][j][1]=i;
path[i][j][2]=j;
}
else
{
a[i][j]=0;
}
}
for(k=1;k<=MAX;k++)
for(i=1;i<=MAX;i++)
for(j=1;j<=MAX;j++)
{
if(a[i][k]!
=0&&a[k][j]!
=0&&((a[i][k]+a[k][j]{
a[i][j]=a[i][k]+a[k][j];
for(l=1,m=1,n=2;l<=MAX;l++)
{
if(0!
=path[i][k][m])
{
path[i][j][l]=path[i][k][m];
m++;
}
else
{
if(0!
=path[k][j][n])
{
path[i][j][l]=path[k][j][n];
n++;
}
else
break;
}
}
}
}
}