C++ 数据结构之先行课开设学期

问题描述如下:

某学院有n门课程,(i,j)表示i是j的先行课,即课程i必须在课程j之前的学期开设。对任意给出的先行课集合S={(1,3),(2,4)......},至少需要安排多少个学期?给出每个学期所开的课程清单。

    这是一个拓扑图,我用的是贪婪求解:

    存储课程用的是邻接数组,存储已找到的点的结构用的是栈stack<int> ss,存储每个点入度用的是数组indegree[];每次在所有没有选择的顶点中选择一个顶点W,它没有这样的入边(V,W),其中V不在ss中;

    每学期遍历一次,把所有存进栈里的点输出,即为当前学期所要开设的课程。更新indegree,清空栈,重复操作,直到所有的点已被输出;

    以下是代码:   

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <stack>

using namespace std;
typedef struct
{
    int x,y;
}section;//用来存储用户输入的先行课

//用邻接数组的方法表示图

void methed(int n, section s[], int sn)//n是课程数量,s是用户输入的课程顺序,sn是s的长度
{
    int ss[n+2][n+2];
    int i,j;
    int indegree[n+2];//存储每个点的入度
    stack<int> store;//栈,存储每个学期的课程,
    int Count =0, sTop;//count用来控制学期,sTop是栈顶

    for(i=0; i<=n; i++)
    {
        for(j=0; j<=n; j++)
            ss[i][j] = 0;
        indegree[i]=0;// 初始化
    }
    for(i=1; i<=n; i++)///顶点从 1 开始计,第一次写的时候没注意从0开始n-1结束,导致后来内存越界,百思不得其解=。=;
        for(j=1; j<=n; j++)
            for(int k=0; k<=sn; k++)
                if(s[k].x==i&&ss[i][j]==0)
                {
                    ss[i][j]=s[k].y;
                    indegree[s[k].y]++;//计算入度,s[k]的每个元素只访问一次,
                    s[k].x=0;//防止多次计算
                }
    cout<<"建立的邻接矩阵为:"<<endl;
    for(i=1; i<=n; i++)///
    {
        for(j=1; j<=n; j++)
            cout<<ss[i][j];
        cout<<endl;
    }//主要部分
    for(j=1; j<=n; j++)
    {
        for(i=1; i<=n; i++)
            if(indegree[i]==0)//把所有入度为0的点加入栈
            {
                store.push(i);
                Count++;//每加一次记一次数
            }
    //环的判断:当没有点可以加进去的时候,栈就是空的,而程序没有正常退出的话,就是里面有环
        if(store.empty())
        {
            cout<<"无法继续找出学期数,请检查输入的先行课序列是否有误!";
            exit(1);
        }

        cout<<"第"<<j<<"个学期的课程:";
        while(!store.empty())
        {
            sTop=store.top();
            store.pop();
            cout<<sTop<<",";
            //然后从图里删除这些点,并将它们出度的点的入度减一
            for(int k=1; k<=n; k++)
            {
                if(ss[sTop][k]!=0)
                    indegree[ss[sTop][k]]--; //不用处理ss[sTop][k]=0的情况,因为indegree是从indegree[1]开始
                indegree[sTop]++;//入度为0的点也要处理;不然会再次加入到栈里
            }
        }
        cout<<endl;
        if(Count==n)//如果点处理完了
            break;
    }
}


 

主函数:

#include <iostream>
#include <stdlib.h>
#include "xian.h"

using namespace std;

int main()
{
    int n,sn,pre,las;
    cout<<"课程总数"<<endl;
    cin>>n;
    cout<<"先输入的先行课对数量,再输入先行课的序列:"<<endl;
    cin>>sn;
    section s[sn];//={{1,3},{1,4},{3,4},{3,6},{2,4},{2,5},{5,6},{4,6}};
    for(int i=0;i<sn;i++)
    {
        cin>>pre;
        s[i].x=pre;
        cin>>las;
        s[i].y=las;
    }
    methed(n,s,sn);
    return 0;
}

测试:

这是其中一组测试数据对应main函数里面注释掉的那组数据。

结果。


猜你喜欢

转载自blog.csdn.net/github_38237196/article/details/80062697