数据结构C++版 王红梅 OJ习题

1027: 拓扑排序

Description

利用邻接表存储结构实现一个有向图的数据输出,计算各顶点的入度,
再输出拓扑排序序列,
若拓扑排序失败,输出Failure。已知部分代码如下,
勿改动。请完成CountInD,TopSort函数。

//graphmain.cpp
#include <iostream>
#include <string>
using namespace std;
//栈类
const int StackSize=100;  //10只是示例性的数据,可以根据实际问题具体定义
template <class T>       //定义模板类SeqStack
class SeqStack
{
public:
    SeqStack( ) ;            //构造函数,栈的初始化
 ~SeqStack( );            //析构函数
    void Push(T x);          //将元素x入栈
    T Pop( );                //将栈顶元素弹出
    T GetTop( );          //取栈顶元素(并不删除)
 bool Empty( );           //判断栈是否为空
 bool Full();             //判断栈是否为满
private:
    T data[StackSize];      //存放栈元素的数组
    int top;                //栈顶指针,指示栈顶元素在数组中的下标
};

//初始化空栈
template <class T>
SeqStack<T>::SeqStack( )
{
 top=-1;
}

//功    能:销毁栈
template <class T>
SeqStack<T>::~SeqStack( )
{
}

//功    能:元素x压栈
template <class T>
void SeqStack<T>::Push(T x)
{
    if (Full()) throw "Overflow";
    top++;
    data[top]=x;
}
// 功    能:栈顶元素弹栈
template <class T>
T SeqStack<T>::Pop( )
{
    T x;
    if (Empty()) throw "Downflow";
    x=data[top--];
    return x;
}

// 功    能:读取当前的栈顶元素
template <class T>
T SeqStack<T>::GetTop( )
{
 if (Empty())throw"Downflow"; 
    return data[top];
}

//功    能:判断栈是否为空
template <class T>
bool SeqStack<T>::Empty( )
{
 if(top==-1) return 1;
 else return 0;
}

//功    能:判断栈是否为满
template <class T>
bool SeqStack<T>::Full( )
{
 return top==StackSize-1;
}
//图
const int MaxSize=20;     // 顶点个数的最大值
int visited[MaxSize];     //访问标志数组(0表示未访问,1表示已访问)

//定义边表结点
struct ArcNode                
{
 int adjvex;                    //邻接点的序号
 ArcNode *next;                 //指向下一个边结点的指针
};

 //定义顶点表结点
template <class T>
struct VertexNode             
{
 int in;     //各顶点的入度
 T vertex;                 //顶点的名称
 ArcNode *firstedge;        //指向第一个边表结点的头指针
};

//邻接表类
template <class T>
class ALGraph
{
public:
   ALGraph(T a[ ], int n, int e);   //构造函数,初始化一个有n个顶点e条边的图
   ~ALGraph();                      //析构函数,释放邻接表中各边表结点的存储空间
   void DispALGraph();              //输出邻接表
   void CountInD();     //计算各个顶点的入度,存储在adjlist[i].in中
   void DispInD();     //输出各顶点的入度
   void TopSort();     //拓扑排序,失败,抛出异常:Failure
private:
   VertexNode<T> adjlist[MaxSize];  //存放顶点表的数组
   int vertexNum, arcNum;           //图的顶点数和边数
};

/*
 *前置条件:图不存在
 *输    入:无
 *功    能:图的初始化
 *输    出:无
 *后置条件:得到一个无向图
 */
template <class T>
ALGraph<T>::ALGraph(T a[ ], int n, int e)
{
    arcNum = e;                             //边数
 vertexNum=n;                            //顶点数
    int i,j;
 for (i=0; i<vertexNum; i++)
 {       
    adjlist[i].vertex = a[i];
    adjlist[i].firstedge = NULL;    
 }

 for (int k=0; k<arcNum; k++)    //依次输入每一条边,并在相应边表中插入结点
    {
  cin>>i>>j;                         //输入边所依附的两个顶点的序号
        ArcNode *s=new ArcNode;
  s->adjvex=j;  //生成一个边表结点s
     s->next=adjlist[i].firstedge;      //将结点s插入到i号表的头结点之后 
        adjlist[i].firstedge=s;
 }
}
/*   前置条件:图已存在
 *   输    入:无
 *   功    能:销毁图
 *   输    出:无
 *   后置条件:释放图所占用的存储空间
 */
template <class T>
ALGraph<T>::~ALGraph( )
{
  for (int i=0; i<vertexNum; i++)
  {
    ArcNode * p=adjlist[i].firstedge;
 while (p!=NULL)                                              //循环删除
 {
  adjlist[i].firstedge=p->next;
  delete p;                                                 //释放结点空间
  p=adjlist[i].firstedge;
 }
  }
}

/*  
 *前置条件:图已存在
 *输    入:无
 *功    能:输出图中所有顶点及边的数据信息
 *输    出:图中所有顶点及边的数据信息
 *后置条件:图保持不变
 */
template <class T>
void ALGraph<T>::DispALGraph( )                    
{                                 
 int i;
 ArcNode *p;
 cout<<"图的邻接表:\n";
    for(i=0;i<vertexNum;i++){     
  cout<<i<<" "<<adjlist[i].vertex<<" "; //输出图中顶点的序号i及值
  for(p=adjlist[i].firstedge;p;p=p->next)
   cout<<p->adjvex<<" ";  //输出i号顶点的邻接点的序号
  cout<<endl;
 }
}

//计算各个顶点的入度
template <class T>
void ALGraph<T>::CountInD()
{

}
//输出各个顶点的入度
template <class T>
void ALGraph<T>::DispInD()
{
 int i;
 cout<<"In:";
    for(i=0;i<vertexNum;i++)
  cout<<adjlist[i].in<<" ";
 cout<<endl;
}
//topsort
template <class T>
void ALGraph<T>::TopSort()
{


}

int main()
{
 string a[]={"A","B","C","D","E","F","G","H","I","J","K","L","M","N"}; //顶点信息
 int n,e;
 cin>>n>>e;  //输入顶点个数和边个数
    ALGraph<string> G(a,n,e);
 G.DispALGraph();
 G.CountInD();
 G.DispInD();
 try{
  G.TopSort();
 }
 catch(const char *ms)
 {
  cout<<ms<<endl;
 }
    return 0;
}

Input

Output

Sample Input

6 7
0 1 0 3 1 2 1 5 2 4 3 5 4 5

Sample Output

Graph adjlist:
0 A 3 1 
1 B 5 2 
2 C 4 
3 D 5 
4 E 5 
5 F 
In:0 1 1 1 1 3 
TopSort:A B C E D F 
//
// Created by Legends丶Hu on 2020/2/6.
//

#include <iostream>
#include <string>

using namespace std;

const int StackSize = 100;

template<class T>
class Stack {
private:
    int top;
    T data[StackSize];
public:
    Stack();

    void Push(T x);

    T Pop();

    T GetTop();

    int Empty();

    ~Stack() {}
};

template<class T>
void Stack<T>::Push(T x) {
    if (top == StackSize - 1) throw "Overflow";
    data[++top] = x;
}

template<class T>
Stack<T>::Stack() {
    top = -1;
}

template<class T>
T Stack<T>::Pop() {
    if (Empty()) throw "Downflow";
    return data[top--];
}

template<class T>
T Stack<T>::GetTop() {
    return Empty() ? throw "Downflow" : data[top];
}

template<class T>
int Stack<T>::Empty() {
    return top == -1;
}
const int MaxSize = 20;     // 顶点个数的最大值
int visited[MaxSize];     //访问标志数组(0表示未访问,1表示已访问)
//定义边表结点
struct ArcNode {
    int adjvex;                    //邻接点的序号
    ArcNode *next;                 //指向下一个边结点的指针
};
//定义顶点表结点
template<class T>
struct VertexNode {
    int in;     //各顶点的入度
    T vertex;                 //顶点的名称
    ArcNode *firstedge;        //指向第一个边表结点的头指针
};

//邻接表类
template<class T>
class ALGraph {
public:
    ALGraph(T a[], int n, int e);   //构造函数,初始化一个有n个顶点e条边的图
    ~ALGraph();                      //析构函数,释放邻接表中各边表结点的存储空间
    void DispALGraph();              //输出邻接表
    void CountInD();     //计算各个顶点的入度,存储在adjlist[i].in中
    void DispInD();     //输出各顶点的入度
    void TopSort();     //拓扑排序,失败,抛出异常:Failure
private:
    VertexNode<T> adjlist[MaxSize];  //存放顶点表的数组
    int vertexNum, arcNum;           //图的顶点数和边数
};

template<class T>
ALGraph<T>::ALGraph(T a[], int n, int e) {
    arcNum = e;                             //边数
    vertexNum = n;                            //顶点数
    int i, j;
    for (i = 0; i < vertexNum; i++) {
        adjlist[i].vertex = a[i];
        adjlist[i].firstedge = nullptr;
    }
    for (int k = 0; k < arcNum; k++)    //依次输入每一条边,并在相应边表中插入结点
    {
        cin >> i >> j;                         //输入边所依附的两个顶点的序号
        ArcNode *s = new ArcNode;
        s->adjvex = j;  //生成一个边表结点s
        s->next = adjlist[i].firstedge;      //将结点s插入到i号表的头结点之后
        adjlist[i].firstedge = s;
    }
}

/*   前置条件:图已存在
 *   输    入:无
 *   功    能:销毁图
 *   输    出:无
 *   后置条件:释放图所占用的存储空间
 */
template<class T>
ALGraph<T>::~ALGraph() {
    for (int i = 0; i < vertexNum; i++) {
        ArcNode *p = adjlist[i].firstedge;
        while (p != NULL)                                              //循环删除
        {
            adjlist[i].firstedge = p->next;
            delete p;                                                 //释放结点空间
            p = adjlist[i].firstedge;
        }
    }
}

template<class T>
void ALGraph<T>::DispALGraph() {
    int i;
    ArcNode *p;
    cout << "Graph adjlist:\n";
    for (i = 0; i < vertexNum; i++) {
        cout << i << " " << adjlist[i].vertex << " "; //输出图中顶点的序号i及值
        for (p = adjlist[i].firstedge; p; p = p->next)
            cout << p->adjvex << " ";  //输出i号顶点的邻接点的序号
        cout << endl;
    }
}

//计算各个顶点的入度
template<class T>
void ALGraph<T>::CountInD() {
    for(int i = 0; i < vertexNum; i++) {
        adjlist[i].in = 0;
    }
    for (int i = 0; i < vertexNum; i++) {
        for (ArcNode *p = adjlist[i].firstedge; p; p = p->next) {
            adjlist[p->adjvex].in++;
        }
    }
}

//输出各个顶点的入度
template<class T>
void ALGraph<T>::DispInD() {
    int i;
    cout << "In:";
    for (i = 0; i < vertexNum; i++)
        cout << adjlist[i].in << " ";
    cout << endl;
}

//topsort
template<class T>
void ALGraph<T>::TopSort() {
    Stack<int> s;
    int count = 0;
    for(int i = 0; i < vertexNum; i++) {
        if(adjlist[i].in == 0) {
            s.Push(i);
        }
    }
    cout << "TopSort:";
    while(!s.Empty()) {
        int t = s.Pop();
        cout << adjlist[t].vertex << " ";
        count++;
        for(ArcNode *p = adjlist[t].firstedge; p; p = p->next) {
            adjlist[p->adjvex].in--;
            if(adjlist[p->adjvex].in == 0) {
                s.Push(p->adjvex);
            }
        }
    }
    if(count < vertexNum)throw "有回路";
}
/*
6 7
0 1 0 3 1 2 1 5 2 4 3 5 4 5
 */
int main() {
    string a[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N"}; //顶点信息
    int n, e;
    cin >> n >> e;  //输入顶点个数和边个数
    ALGraph<string> G(a, n, e);
    G.DispALGraph();
    G.CountInD();
    G.DispInD();
    try {
        G.TopSort();
    }
    catch (const char *ms) {
        cout << ms << endl;
    }
    return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值