@【数据结构】(图-拓扑排序)
方法1:采用邻接表存储结构,按照堆栈的实现。
方法2:采用邻接矩阵实现:
#include<iostream>
#include<iomanip>
#include<stdlib.h>
#include<stdio.h>
#define INF 65535 //设为双字节无符号整数的最大值
using namespace std;
#define MAX 9999
//邻接矩阵结构
typedef struct
{
char vexs[100]; //顶点表
int edges[100][100]; //邻接表,即边表
int n, e; //顶点数和边数
}MGraph;
//邻接表结构
typedef char VextexType[10];
typedef struct edgenode
{
int adjvex; //相邻点序号
int weight;
struct edgenode *nextarc; //下一条边的顶点
}ArcNode;
typedef struct vexnode
{
char data; //存放一个顶点的信息;
ArcNode *firstarc; //指向第一条边结点
}VHeadNode;
typedef struct
{
int n, e;
VHeadNode adjlist[MAX]; //单链表头结点指针
}AdjGraph; //图的邻接表类型
void createMG(MGraph &G)
{
int n, e;
int i, j, k, w;
cout << "输入图的顶点数和边数:";
cin >> n >> e;
G.n = n; G.e = e;
for (i = 0; i < n; i++) //矩阵初始化
for (j = 0; j < n; j++)
G.edges[i][j] = 0;
cout << "输入每条边对应的顶点序号(从0开始)与权值:" << endl;
for (k = 0; k < e; k++)
{
cin >> i >> j >> w;
G.edges[i][j] = w; //图的邻接矩阵
}
}
void outG(MGraph G)
{
for (int i = 0; i < G.n; i++)
{
for (int j = 0; j < G.n; j++)
if (G.edges[i][j] != 0 && G.edges[i][j] < INF)
cout << setw(4) << G.edges[i][j];
else if (i == j) cout << setw(4) << "0";
else cout << setw(4) << "∞";
cout << endl;
}
}
void MatToAdj(MGraph G, AdjGraph *&g)
{
int i, j; ArcNode *p;
g = (AdjGraph*)malloc(sizeof(AdjGraph));
for (i = 0; i < G.n; i++)
g->adjlist[i].firstarc = NULL;
for(i=0;i<G.n;i++)
for(j=G.n-1;j>=0;j--)
if (G.edges[i][j] != 0)
{
p = (ArcNode*)malloc(sizeof(ArcNode));
p->adjvex = j;
p->weight = G.edges[i][j];
p->nextarc = g->adjlist[i].firstarc;
g->adjlist[i].firstarc = p;
}
g->n = G.n; g->e = G.e;
}
void Indegree(MGraph G, int A[])
{
int i, j, w = 0;
for (j = 0; j < G.n; j++)
{
int in = 0;
for (i = 0; i < G.n; i++)
{
if (G.edges[i][j] != INF)
w++;
}
A[j] = w;
}
}
void topsort1(MGraph &G)
{
int i, j, visit[MAX], A[20];
int Qu[MAX], front = 0, rear = 0; //定义循环队列
for (i = 0; i < G.n; i++)
visit[i] = 0;
for (int a = 0; a < G.n; a++)
if (visit[a] == 0) //如果还有顶点没有被访问到
{
for (j = 0; j < G.n; j++)
{
int in = 0;
for (i = 0; i < G.n; i++)
{
if (G.edges[i][j] != 0)
in++;
}
A[j] = in;
}
for (i = 0; i < G.n; i++)
{
if (A[i] == 0 && visit[i] == 0) //入度为0先排序
{
visit[i] = 1;
rear = (rear + 1) % MAX; Qu[rear] = i; //初始结点进队
for (j = 0; j < G.n; j++)
G.edges[i][j] = 0; //把入度为零的结点行值改为0即为删除其出度
}
}
}
if (rear < G.n)
cout << "有环路" << endl;
else
for (j = 1; j <= G.n; j++)
cout << Qu[j] << " ";
cout << endl;
}
void out(AdjGraph *g)
{
ArcNode *p;
int i;
cout << "顶点-->相邻顶点序号与权值为:" << endl;
for (i = 0; i < g->n; i++)
{
cout <<i;
p = g->adjlist[i].firstarc;
if (p != NULL)
{
cout << "-->";
}
while (p != NULL)
{
cout << p->adjvex << " " << p->weight << " /";
p = p->nextarc;
}
cout << endl;
}
}
void topsort2(AdjGraph *g)
{
int i, j, visit[MAX], A[20];
}
int indegree[MAX];//用来存储所有节点的入度之和
typedef struct
{
int top;
int *base;
int stacksize;
}SqStack;
void FindInputDgeree(AdjGraph *G)//计算所有节点的入度
{
ArcNode *p;
int i;
for(i = 0; i < G->n; i ++)
indegree[i] = 0;
for(i = 0; i < G->n; i ++)
{
p = G->adjlist[i].firstarc;
while(p)
{
indegree[p->adjvex] ++;
p = p->nextarc;
}
}
}
typedef struct node
{
int data;
struct node *next;
}StackNode, *LinkStack;
LinkStack Init() //置空栈
{
return NULL;
}
int Empty(LinkStack top)
{
if (top == NULL) return 1;
else return 0;
}
LinkStack push(LinkStack top, int x)
{
StackNode *s;
s = (StackNode*)malloc(sizeof(StackNode));
s->data = x;
s->next = top; top = s; //新结点插入链表
return top;
}
LinkStack pop(LinkStack top, int &x)
{
StackNode *s;
if (top == NULL) return(NULL); //空栈,返回空
else
{
x = top->data; s = top;
top = top->next; free(s);
return top; //返回原栈顶结点数据域的值
}
}
void TopologicalSort(AdjGraph *G)
{
FindInputDgeree(G);
int count = 0,i;
LinkStack top;
ArcNode *p;
top = Init();
for(i = 0; i < G->n; i ++)
if (indegree[i] == 0)//把入度为零的节点入栈
top = push(top, i);
while(!Empty(top))
{
top=pop(top,i);
cout<<i<<" "; count ++;
p = G->adjlist[i].firstarc;
while(p)
{
if(-- indegree[p->adjvex]==0)//判断去掉一条边后节点的入度是否为零
top = push(top, p->adjvex);
p = p->nextarc;
}
}
cout << endl;;
}
void main()
{
cout << "1.采用邻接矩阵存储实现:" << endl;
MGraph G;
createMG(G);
cout << "建立的邻接矩阵如下:" << endl;
outG(G);
cout << endl;
cout << "2.采用邻接表存储,按照堆栈实现:" << endl;
AdjGraph *g;
MatToAdj(G, g);
cout << "输入的邻接表为:" << endl;
out(g);
cout << endl;
cout << "-----------------------------------------------------" << endl;
cout << "邻接矩阵拓扑排序结果为:" << endl;
topsort1(G);
cout << "邻接表拓扑排序结果为:" << endl;
TopologicalSort(g);
system("pause");
}
测试:
有向无环图的拓扑排序不唯一