数据结构-图-拓扑排序算法

方法:采用邻接表数据结构,加入顶点入度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网存在环");

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值