方法:采用邻接表数据结构,加入顶点入度in,定义一个栈,用于存储入度为零的顶点
1、循环查找首次入度为零的顶点,入栈
2、循环,出栈,打印栈顶,处理栈顶指向顶点的入度减一,减一后入度为零的顶点再入栈,直到栈为空推出循环。
main.cpp
#include<iostream>
#include<stdio.h>
#include <stdlib.h>
#include<string>
#include"structfun.h"
using std::string;
using std::printf;
using std::scanf;
using std::endl;
using std::to_string;
void main()
{
//图的邻接矩阵
//AdjMarGraph amg;
//CreateAdjMaxGraph(&amg);//创建图的邻接矩阵
AdjMarDepthFirstSearch(&amg,0);//图的邻接矩阵深度优先遍历
AdjMarBreadthFirstSearch(&amg);//广度优先遍历(递归)
// //AMBFS(&amg);//(非递归)
AdjMarGraphLeastPath(&amg);//图-最小生成路径(采用邻接矩阵)prim算法
printf("\n");
AdjMarGraphLeastPathKruskal(&amg);//图-最小生成路径(采用邻接矩阵)kruskal算法
ShortestPath(&amg,8,0);//自己写的
//
pathmatirx *p;
shortpathtable *D;
p=(pathmatirx*)malloc(sizeof(pathmatirx));
D=(shortpathtable*)malloc(sizeof(shortpathtable));
//
shortestpathA(&amg,4,p,D);教科书上的
//
//shortestpathFloyd(&amg,4,8);//Floyd最短路径弗洛伊德算法
//图的邻接表
AdjListGraph alg;
CreateAdjListGraph(&alg);
//TopologicalSort(&alg);//直接调用定点删除函数的方法
TopologicalSortA(&alg);//拓扑排序
//printf("删除的定点是:%s",DeleteAdjListVertex(&alg,0).c_str());
//AdjListDepthFirstSearch(&alg,0);//图的深度遍历
//AdjListBreadthFirstSearch(&alg);//图的广度遍历
//图的十字链表
//OrthogonalListGraph olg;
//CreateOrthogonalListGraph(&olg);
//图的邻接多重表
//AdjacencyMultipleTableGraph amtg;
//CreateAdjacencyMultipleTableGraph(&amtg);
system("pause");
}
structfun.h
#include <stdio.h>
#include <iostream>
#include<string>
using std::cout;
using std::cin;
using std::string;
#define MAXSIZE 100
#define OK 1
#define ERROR 0
#define INFINITY 65535//无穷大
typedef string ElemType;
typedef string VertexType;//图顶点数据类型
typedef int EdgeType;//图边的数据类型
typedef struct stack{
ElemType data[MAXSIZE];
int top;
}stackList;
//初始化栈
int InitStack(stackList *L);
//入栈push
int push(stackList *L,ElemType e);
//出栈pop
ElemType pop(stackList *L);
//2、邻接表(Adjacency List)
//设置一个顶点数组vertex[],设置一个边的链表,顶点的next指向所对应的链表
typedef struct EdgeNode//边链表节点
{
EdgeType arcVertex;
int weight;//权值
EdgeNode *next;
}EdgeNode;
typedef struct//顶点数组
{
VertexType vertex;
EdgeNode *firstEdge;
int in;//入度
}VertexList[MAXSIZE];
typedef struct//图结构
{
VertexList vlist;
int numVertex,numArc;
}AdjListGraph;
int CreateAdjListGraph(AdjListGraph *alg);
string DeleteAdjListVertex(AdjListGraph *alg,int vertexcur);//删除顶点
void TopologicalSort(AdjListGraph *alg);//拓扑排序直接删除定点
void TopologicalSortA(AdjListGraph *alg);//拓扑排序改变入度
int AdjListDepthFirstSearch(AdjListGraph *alg,int f);//邻接表深度遍历
int AdjListBreadthFirstSearch(AdjListGraph *alg);//邻接表广度遍历
structfun.cpp
#include<iostream>
#include<stdio.h>
#include<string>
#include<sstream>
#include"structfun.h"
using std::cout;
using std::cin;
using std::string;
using std::endl;
using std::ostringstream;
using std::stoi;
using std::to_string;
//初始化栈
int InitStack(stackList *L)
{
for(int i=0;i<MAXSIZE;i++)
(*L).data[i]="";
(*L).top=-1;
return 1;
}
//入栈push
int push(stackList *L,ElemType e)
{
//
if((*L).top>MAXSIZE)
return 0;
(*L).top=(*L).top+1;
(*L).data[(*L).top]=e;
return 1;
}
//出栈pop
ElemType pop(stackList *L)
{
ElemType e;
if((*L).top==-1)
return 0;
e=(*L).data[(*L).top].c_str();
(*L).data[(*L).top]="";
(*L).top=(*L).top-1;
return e;
}
int CreateAdjListGraph(AdjListGraph *alg)
{
int i=0;
alg->numVertex=0;
alg->numArc=0;
FILE *fp=fopen("4.txt","rb");//文件使用方式由r,w,a,t,b,+各字符的含义是:r(read): 只读 w(write): 只写 a(append): 追加 t(text): 文本文件,可省略不写 b(binary): 二进制文件 +: 读和写
while(1)//创建顶点
{
printf("请输入邻接表的顶点结束用#:");
fscanf(fp,"%s",alg->vlist[i].vertex.c_str());
printf("%s\n",alg->vlist[i].vertex.c_str());
//cin>>alg->vlist[i].vertex;
if(*alg->vlist[i].vertex.c_str()=='#')
break;
alg->vlist[i].firstEdge=NULL;
alg->vlist[i].in=0;//初始化入度为0
i++;
alg->numVertex++;
}
while(1)//创建边链表
{
int v1=0,v2=0,w=0;
EdgeNode *edgenode;
printf("请输入邻接表的顶点对应的边(v1,v2,w)以(0,0,0)结束:");
fscanf(fp,"%d,%d,%d",&v1,&v2,&w);
printf("%d,%d,%d\n",v1,v2,w);
if(!v1&&!v2&&!w)//(0,0,0)结束
break;
alg->vlist[v2].in++;//目的边的入度加1
edgenode = new EdgeNode();//创建边节点
edgenode->arcVertex=v2;
edgenode->weight=w;
edgenode->next=NULL;
if(alg->vlist[v1].firstEdge==NULL)//插入边节点
alg->vlist[v1].firstEdge=edgenode;
else
{
EdgeNode *temp;
temp=alg->vlist[v1].firstEdge;
while(temp->next!=NULL)
temp=temp->next;
temp->next=edgenode;
}
//无向图要添加反方向的边,跟上面的代码一样,只是v1换成v2 v2换成v1
/*edgenode = new EdgeNode();//创建边节点
edgenode->arcVertex=v1;
edgenode->weight=w;
edgenode->next=NULL;
if(alg->vlist[v2].firstEdge==NULL)//插入边节点
alg->vlist[v2].firstEdge=edgenode;
else
{
EdgeNode *temp;
temp=alg->vlist[v2].firstEdge;
while(temp->next!=NULL)
temp=temp->next;
temp->next=edgenode;
}
alg->numArc++;*/
}
return OK;
}
//删除邻接表定点,传入要删除定点的下标,返回成功该定点;
string DeleteAdjListVertex(AdjListGraph *alg,int vertexcur)
{
string str;
str=alg->vlist[vertexcur].vertex.c_str();
//处理入度减1
EdgeNode *temp;
temp=alg->vlist[vertexcur].firstEdge;
while(temp)
{
alg->vlist[temp->arcVertex].in--;//减入度
alg->numArc--;//减边数
temp=temp->next;
}
if(vertexcur<0&&vertexcur>alg->numVertex)
return 0;
alg->vlist[vertexcur].firstEdge=NULL;
int vertexcur1=vertexcur;
while(vertexcur<alg->numVertex) //删除顶点
{
alg->vlist[vertexcur].vertex=alg->vlist[vertexcur+1].vertex.c_str();
alg->vlist[vertexcur].firstEdge=alg->vlist[vertexcur+1].firstEdge;
alg->vlist[vertexcur].in=alg->vlist[vertexcur+1].in;
vertexcur++;
}
alg->numVertex--;//定点数减1
//所有边链表下标减1
for(int i=0;i<alg->numVertex;i++)
{
temp=alg->vlist[i].firstEdge;
while(temp)
{
if(temp->arcVertex>=vertexcur1)
{temp->arcVertex--;}
temp=temp->next;
}
}
return str;
}
//拓扑排序
void TopologicalSort(AdjListGraph *alg)
{
//定义一个栈,存储入度为零的定点
stackList stack;
InitStack(&stack);
string vc;
int count=0,vnum=alg->numVertex;
while(1)//判断入度是否为零,为零删除定点
{
for(int i=0;i<alg->numVertex;i++)
{
if(alg->vlist[i].in==0)
{
push(&stack,alg->vlist[i].vertex.c_str());
printf("%s->",alg->vlist[i].vertex.c_str());//打印被删除的定点
DeleteAdjListVertex(alg,i);
count++;
i--;
}
}
vc=pop(&stack).c_str();
//printf("%s->",vc.c_str());
if(stack.top==-1)
{
if(count==vnum)
printf("AOV网不存在环");
else
printf("AOV网存在环");
break;
}
}
}
void TopologicalSortA(AdjListGraph *alg)
{
//定义一个数组
stackList stack;
InitStack(&stack);
int count=0,i;
//查找入度为零的定点
for(i=0;i<alg->numVertex;i++)
{
if(alg->vlist[i].in==0)
{
push(&stack,to_string((long long)i));//入度为零的顶点下标入栈
}
}
//处理并打印
while(stack.top!=-1)
{
string vstr;
int cur;
EdgeNode *temp;
temp=(EdgeNode*)malloc(sizeof(EdgeNode));
vstr=pop(&stack);
cur=stoi(vstr.c_str());
printf("%s->",alg->vlist[cur].vertex.c_str());
count++;
//遍历该定点连接的其他边,把他们的入度减一
temp=alg->vlist[cur].firstEdge;
while(temp!=NULL)
{
if(!--alg->vlist[temp->arcVertex].in)
push(&stack,to_string((long long)temp->arcVertex));//入度为零的顶点下标入栈
temp=temp->next;
}
}
if(count==alg->numVertex)
printf("AOV网不存在环");
else
printf("AOV网存在环");
}