拓扑排序的两种实现
/***************************** 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; }
一个不会敲代码的程序员