下为要进行拓扑排序的图:
首先进行一些基础结构与操作的定义:
有关图的邻接存储:
typedef struct ArcNode{ //边表节点
int adjvex; //弧所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条弧的指针;
//InfoType info; //网的边权值;
}ArcNode;
typedef struct VNode{ //顶点表结点
VertexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];
typedef struct{
AdjList vertices; //邻接表
int vexnum,arcnum; //图的顶点数和弧数
}Graph; //Graph是以邻接表存储的图的类型
有关链栈:
//链栈
typedef struct Linknode{
VertexType data; //数据域
struct Linknode *next;
}Linknode,*LiStack;
//初始化(带头结点)(自写)
bool InitStack2(LiStack &S){
S = (Linknode*)malloc(sizeof(Linknode));
if(S==NULL) //这里第一次写成=了!!!!!!!!!!!
return false;
S->next = NULL;
return true;
}
//链栈判空
bool IsEmpty(LiStack S){
if(S->next == NULL)
return true;
else
return false;
}
//链栈进栈(自写)
bool Push(LiStack &S,VertexType x){
Linknode*p;
p = (Linknode*)malloc(sizeof(Linknode));
if(p==NULL)
return false;
p->data = x;
p->next = S->next;
S->next = p;
return true;
}
//链栈出栈(自写2)
bool Pop(LiStack &S,VertexType &x) {
if(S->next ==NULL)
return false;
x = S->next->data;
S->next = S->next->next;
return true;
}
建立图的邻接表结构:
//建立图的邻接表结构
void CreateGraph(Graph *G){
int i,j,k;
ArcNode *e;
//输入顶点数和边数
printf("请输入顶点数和边数:\n");
scanf("%d,%d",&G->vexnum,&G->arcnum);
//输入顶点信息,建立顶点表
printf("请输入顶点字符:\n");
for(i=0;i<G->vexnum;i++){
scanf("%d",&G->vertices[i].data);
G->vertices[i].firstarc=NULL;
}
//建立边表
for(k=0;k<G->arcnum;k++){
printf("请输入边(vi,vj)上的顶点序号:\n");
scanf("%d,%d",&i,&j);
//单链表中的头插法
e = (ArcNode*)malloc(sizeof(ArcNode));
e-> adjvex = j;
e->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = e;
//e = (ArcNode*)malloc(sizeof(ArcNode));
//e-> adjvex = i;
//e->nextarc = G->vertices[i].firstarc;
//G->vertices[j].firstarc = e;
}
}
输出图的邻接表结构:
void DispGraphAdjList(Graph *G)
{
int i;
ArcNode *p;
printf("图的邻接表表示如下\n");
printf("%6s%8s%12s\n","编号","顶点","相邻边编号");
for(i=0;i< G->vexnum;i++)
{
printf("%4d %8d",i,G->vertices[i].data);//
for(p=G->vertices[i].firstarc;p!=NULL;p=p->nextarc)
printf("%4d",p->adjvex);
printf("\n");
}
}
拓扑排序及输出代码:
void TopologicalSort(Graph *G){
printf("测试1:\n");
//声明indegree数组,用来记录每个结点的当前入度。
int indegree[5]={0,1,0,2,2};
//声明print数组,用来记录生成的拓扑排序序列。
int print[5];
printf("测试1.1:\n");
LiStack S;
printf("测试1.2:\n");
InitStack2(S);
printf("测试1.3:\n");
for(int i=0;i<G->vexnum;i++)
if(indegree[i]==0)
Push(S,i);
int count = 0;
printf("测试2:\n");
while(!IsEmpty(S)){
VertexType j;
Pop(S,j); //栈顶元素出栈,并命名为j
print[count++]=j; //输出顶点j,储存到pirint数组中.
ArcNode*p;
for(p=G->vertices[j].firstarc;p;p=p->nextarc){
//将所有i指向的顶点入度-1,并将入度减为0的顶点压入栈中。
int v=p->adjvex;
if(!(--indegree[v]))
Push(S,v);
}
}
printf("测试3:\n");
printf("拓扑排序如下:");
for(int i=0;i<5;i++){
printf("%d,",print[i]);
}
}
主函数
int main(){
Graph G;
CreateGraph(&G);
DispGraphAdjList(&G);
TopologicalSort(&G);
return 0;
}
完整代码:
#include <stdio.h>
#include <stdlib.h>
#define MaxVertexNum 20
//结点定义
typedef int VertexType;
typedef struct ArcNode{ //边表节点
int adjvex; //弧所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条弧的指针;
//InfoType info; //网的边权值;
}ArcNode;
typedef struct VNode{ //顶点表结点
VertexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}VNode,AdjList[MaxVertexNum];
typedef struct{
AdjList vertices; //邻接表
int vexnum,arcnum; //图的顶点数和弧数
}Graph; //Graph是以邻接表存储的图的类型
//建立图的邻接表结构
void CreateGraph(Graph *G){
int i,j,k;
ArcNode *e;
//输入顶点数和边数
printf("请输入顶点数和边数:\n");
scanf("%d,%d",&G->vexnum,&G->arcnum);
//输入顶点信息,建立顶点表
printf("请输入顶点字符:\n");
for(i=0;i<G->vexnum;i++){
scanf("%d",&G->vertices[i].data);
G->vertices[i].firstarc=NULL;
}
//建立边表
for(k=0;k<G->arcnum;k++){
printf("请输入边(vi,vj)上的顶点序号:\n");
scanf("%d,%d",&i,&j);
//单链表中的头插法
e = (ArcNode*)malloc(sizeof(ArcNode));
e-> adjvex = j;
e->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = e;
//e = (ArcNode*)malloc(sizeof(ArcNode));
//e-> adjvex = i;
//e->nextarc = G->vertices[i].firstarc;
//G->vertices[j].firstarc = e;
}
}
//输出图的邻接表结构
void DispGraphAdjList(Graph *G)
{
int i;
ArcNode *p;
printf("图的邻接表表示如下\n");
printf("%6s%8s%12s\n","编号","顶点","相邻边编号");
for(i=0;i< G->vexnum;i++)
{
printf("%4d %8d",i,G->vertices[i].data);//
for(p=G->vertices[i].firstarc;p!=NULL;p=p->nextarc)
printf("%4d",p->adjvex);
printf("\n");
}
}
//链栈
typedef struct Linknode{
VertexType data; //数据域
struct Linknode *next;
}Linknode,*LiStack;
//初始化(带头结点)(自写)
bool InitStack2(LiStack &S){
S = (Linknode*)malloc(sizeof(Linknode));
if(S==NULL) //这里第一次写成=了!!!!!!!!!!!
return false;
S->next = NULL;
return true;
}
//链栈判空
bool IsEmpty(LiStack S){
if(S->next == NULL)
return true;
else
return false;
}
//链栈进栈(自写)
bool Push(LiStack &S,VertexType x){
Linknode*p;
p = (Linknode*)malloc(sizeof(Linknode));
if(p==NULL)
return false;
p->data = x;
p->next = S->next;
S->next = p;
return true;
}
//链栈出栈(自写2)
bool Pop(LiStack &S,VertexType &x) {
if(S->next ==NULL)
return false;
x = S->next->data;
S->next = S->next->next;
return true;
}
void TopologicalSort(Graph *G){
printf("测试1:\n");
//声明indegree数组,用来记录每个结点的当前入度。
int indegree[5]={0,1,0,2,2};
//声明print数组,用来记录生成的拓扑排序序列。
int print[5];
printf("测试1.1:\n");
LiStack S;
printf("测试1.2:\n");
InitStack2(S);
printf("测试1.3:\n");
for(int i=0;i<G->vexnum;i++)
if(indegree[i]==0)
Push(S,i);
int count = 0;
printf("测试2:\n");
while(!IsEmpty(S)){
VertexType j;
Pop(S,j); //栈顶元素出栈,并命名为j
print[count++]=j; //输出顶点j,储存到pirint数组中.
ArcNode*p;
for(p=G->vertices[j].firstarc;p;p=p->nextarc){
//将所有i指向的顶点入度-1,并将入度减为0的顶点压入栈中。
int v=p->adjvex;
if(!(--indegree[v]))
Push(S,v);
}
}
printf("测试3:\n");
printf("拓扑排序如下:");
for(int i=0;i<5;i++){
printf("%d,",print[i]);
}
//if(count<G.vexnum)
//return false;
//else
//return true;
}
int main(){
Graph G;
CreateGraph(&G);
DispGraphAdjList(&G);
TopologicalSort(&G);
return 0;
}
我写代码中遇到的问题:
1.在链栈初始化中,把==写成了=:
//初始化(带头结点)(自写)
bool InitStack2(LiStack &S){
S = (Linknode*)malloc(sizeof(Linknode));
if(S=NULL) //这里第一次写成=了!!!!!!!!!!!
return false;
S->next = NULL;
return true;
}
没有任何报错,却导致代码运行过程到此直接结束,没有后续的拓扑排序。
2.初始化时,将2号节点的入度误写为1,导致拓扑排序后的结果不正确。