拓扑排序的两种实现
/*****************************
title : 拓扑排序(邻接矩阵实现)
author: jay chang
date : 2009/07/14
*****************************/
#include<iostream>
using namespace std;
#define MAXSIZE 99
#define FALSE 0
#define TRUE 1
typedef char VertexData;
typedef int AdjType;
typedef struct VertexNode
{
VertexData vertexData;
}VertexNode;
typedef struct ArcNode
{
AdjType adj; //弧的权值
}ArcNode;
typedef struct AdjMatrix
{
VertexNode vertexNodes[MAXSIZE+1];
ArcNode arcNodes[MAXSIZE+1][MAXSIZE+1];
int vertexNum,arcNum;
}AdjMatrix;
typedef struct Queue
{
int data[MAXSIZE+1];
int head,rear;
}Stack;
/**********************************************************************************
Function Name:LocateGraph
Return Type: int
Function Description: 查询在图中是否存在结点信息为vertexData的结点,存在返回结
点位置,否则返回FALSE。
**********************************************************************************/
int LocateGraph(AdjMatrix* g,VertexData vertexData)
{
int iIndex;
for(iIndex=1;iIndex<=g->vertexNum;iIndex++)
{
if(vertexData==g->vertexNodes[iIndex].vertexData)
return iIndex;
}
return FALSE;
}
/**********************************************************************************
Function Name:InitAdjMatrix
Return Type: void
Function Description: 初始化有向无环图
**********************************************************************************/
inline void InitAdjMatrix(AdjMatrix* g)
{
for(int iIndex=1;iIndex<=g->vertexNum;iIndex++)
{
for(int jIndex=1;jIndex<=g->vertexNum;jIndex++)
{
g->arcNodes[iIndex][jIndex].adj=0;
}
}
}
/**********************************************************************************
Function Name:CreateAdjMatrix
Return Type: void
Function Description: 创建连通图
**********************************************************************************/
void CreateAdjMatrix(AdjMatrix* g)
{
cout<<"******************************************************************\n";
cout<<" 拓扑排序\n";
cout<<"******************************************************************\n";
cout<<"输入连通图的顶点数,弧数:\n";
cin>>g->vertexNum>>g->arcNum;
cout<<"输入顶点信息"<<endl;
int iCount,start,end;char arcStart,arcEnd;
InitAdjMatrix(g);
for(iCount=1;iCount<=g->vertexNum;iCount++)
{
cout<<"结点"<<iCount<<"的信息"<<endl;
cin>>g->vertexNodes[iCount].vertexData;
}
for(iCount=1;iCount<=g->arcNum;iCount++)
{
cout<<"输入第"<<iCount<<"条弧的起始,终点"<<endl;
cin>>arcStart>>arcEnd;
start=LocateGraph(g,arcStart);end=LocateGraph(g,arcEnd);
g->arcNodes[start][end].adj=1;
}
}
/**********************************************************************************
Function Name:FindID
Return Type: void
Function Description: 计算每个顶点的入度
**********************************************************************************/
void FindID(AdjMatrix* g,int indegree[])
{
for(int jIndex=1;jIndex<=g->vertexNum;jIndex++)
{
for(int iIndex=1;iIndex<=g->vertexNum;iIndex++)
{
if(g->arcNodes[iIndex][jIndex].adj==1)
{
indegree[jIndex]++;
}
}
}
}
/**********************************************************************************
Function Name:QueueOperation
Function Description: 队列的基本操作
**********************************************************************************/
inline void InitQueue(Queue* queue)
{
queue->head=0;
queue->rear=0;
}
inline bool IsEmpty(Queue* queue)
{
return queue->head%MAXSIZE==queue->rear?true:false;
}
inline void Quit(Queue* queue,int* i)
{
*i=queue->data[queue->head++];
}
inline int Enter(Queue* queue,int value)
{
if(queue->head==((queue->rear+1)%MAXSIZE))
return FALSE;
queue->data[queue->rear++]=value;
return TRUE;
}
/**********************************************************************************
Function Name:ClearZero
Return Type: int
Function Description: 删除以顶点i为起点的弧
**********************************************************************************/
inline void ClearZero(AdjMatrix* g,int iIndex,int indegree[],Queue* queue)
{
int jIndex;
for(jIndex=1;jIndex<=g->vertexNum;jIndex++)
{
if(g->arcNodes[iIndex][jIndex].adj>0)
{
g->arcNodes[iIndex][jIndex].adj=0;
indegree[jIndex]--;
if(indegree[jIndex]==0)
Enter(queue,jIndex);
}
}
}
/**********************************************************************************
Function Name:TopoSort
Return Type: int
Function Description: 拓扑排序
**********************************************************************************/
int TopoSort(AdjMatrix* g)
{
int indegree[MAXSIZE+1]={0},count;
Queue queue;
FindID(g,indegree);
InitQueue(&queue);
int iCount;
for(iCount=1;iCount<=g->vertexNum;iCount++)
{
if(indegree[iCount]==0)
Enter(&queue,iCount);
}
count=0;
while(!IsEmpty(&queue))
{
Quit(&queue,&iCount);
cout<<g->vertexNodes[iCount].vertexData<<" "; //输出顶点并计数
count++;
ClearZero(g,iCount,indegree,&queue); //删除以顶点i为起点的弧
}
cout<<endl;
return count==g->vertexNum?TRUE:FALSE;
}
int main()
{
AdjMatrix *g=(AdjMatrix*)malloc(sizeof(AdjMatrix));
InitAdjMatrix(g);
CreateAdjMatrix(g);
TopoSort(g);
return 0;
}
/**********************************
title: 拓扑排序(邻接表实现)
author: jay chang
date: 2009/07/16
**********************************/
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 99
#define TRUE 1
#define FALSE 0
using namespace std;
typedef char VertexData;
typedef int AdjType;
typedef struct Stack //定义栈
{
int data[MAXSIZE+1];
int top;
}Stack;
typedef struct ArcNode //定义弧结点
{
AdjType adj;
ArcNode *nextArc;
}ArcNode;
typedef struct VertexNode //定义顶点
{
VertexData vertexData;
ArcNode *firstArc;
}VertexNode;
typedef struct AdjMatrix //定义图
{
VertexNode vertexNodes[MAXSIZE+1];
int verNum,arcNum;
}AdjMatrix;
//全局变量
int indegree[MAXSIZE+1]={0};
int LocateGraph(AdjMatrix *g, VertexData vertexData)
{
int iIndex;
for(iIndex=1;iIndex<=g->verNum;iIndex++)
{
if(vertexData==g->vertexNodes[iIndex].vertexData)
return iIndex;
}
return FALSE;
}
void CreateGraph(AdjMatrix *g)
{
int iCount,arcStart,arcEnd;char start,end;
cout<<"*****************************************"<<endl;
cout<<"*** 拓扑排序\n";
cout<<"*** Author: Jay Chang\n";
cout<<"*****************************************"<<endl;
cout<<"输入有向无环图的顶点,及弧数\n";
cin>>g->verNum>>g->arcNum;
cout<<"输入有向无环图的顶点信息\n";
ArcNode *q=NULL;
for(iCount=1;iCount<=g->verNum;iCount++)
{
cout<<"输入第"<<iCount<<"个顶点的信息"<<endl;
cin>>g->vertexNodes[iCount].vertexData;
g->vertexNodes[iCount].firstArc=NULL;
}
for(iCount=1;iCount<=g->arcNum;iCount++)
{
cout<<"输入第"<<iCount<<"条弧的起始与结束的信息"<<endl;
cin>>start>>end;
arcStart=LocateGraph(g,start);
arcEnd =LocateGraph(g,end);
//添加弧结点
q=(ArcNode*)malloc(sizeof(ArcNode));
q->adj=arcEnd;
q->nextArc=g->vertexNodes[arcStart].firstArc;
g->vertexNodes[arcStart].firstArc=q;
//对于第arcEnd个顶点的入度值加1
indegree[arcEnd]++;
}
}
//判栈空
int IsEmpty(Stack *stack)
{
return stack->top==-1?TRUE:FALSE;
}
//初始化栈
void InitStack(Stack *stack)
{
stack->top=-1;
}
//出栈
void Pop(Stack *stack,int *iIndex)
{
*iIndex=stack->data[stack->top--];
}
//进栈
void Push(Stack *stack,int value)
{
stack->data[++stack->top]=value;
}
//拓扑排序
int Tuopu(AdjMatrix *g)
{
int iCount,count=0;
Stack *stack=(Stack*)malloc(sizeof(Stack));
InitStack(stack);
ArcNode *p=NULL;
//对于入度为0的顶点入栈
for(iCount=1;iCount<=g->verNum;iCount++)
{
if(indegree[iCount]==0){
Push(stack,iCount);
}
}
cout<<"输出拓扑序列\n";
//输出顶点后,将与该顶点相连的顶点的边删除,将与相连顶点的入度减1,如减后为0,入栈,栈空结束
while(!IsEmpty(stack))
{
Pop(stack,&iCount);
cout<<g->vertexNodes[iCount].vertexData<<" ";
count++;
p=g->vertexNodes[iCount].firstArc;
while(p!=NULL)
{
if(--indegree[p->adj]==0)
Push(stack,p->adj);
p=p->nextArc;
}
}//end while
if(count<g->verNum){
cout<<"有回路"<<endl;
return FALSE;
}
cout<<endl;
}
int main()
{
AdjMatrix *g=(AdjMatrix*)malloc(sizeof(AdjMatrix));
CreateGraph(g);
Tuopu(g);
return 0;
}
一个不会敲代码的程序员

浙公网安备 33010602011771号