解排课程表

考虑这样一个问题:给定一些计算机课程,每个课程都有前置课程,只有完成了前置课程才可以开始当前课程的学习;我们的目标是选择出一组课程,这组课程必须确保按顺序学习时,能全部被完成。每个课程的前置课程如下:

gopl.io/ch5/toposort
// prereqs记录了每个课程的前置课程
var prereqs = map[string][]string{
    "algorithms": {"data structures"},
    "calculus": {"linear algebra"},
    "compilers": {
        "data structures",
        "formal languages",
        "computer organization",
    },
    "data structures":       {"discrete math"},
    "databases":             {"data structures"},
    "discrete math":         {"intro to programming"},
    "formal languages":      {"discrete math"},
    "networks":              {"operating systems"},
    "operating systems":     {"data structures", "computer organization"},
    "programming languages": {"data structures", "computer organization"},
}

一个可行解:

1: intro to programming
2: discrete math
3: data structures
4: algorithms
5: linear algebra
6: calculus
7: formal languages
8: computer organization
9: compilers
10: databases
11: operating systems
12: networks
13: programming languages

解决的思路参考:http://www.cnblogs.com/shanyou/archive/2006/11/16/562861.html

自己写了个demo 程序如下:

#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <algorithm> 
#include <iterator>  
using namespace std;

typedef map<string, std::vector<string> >  GraphType;
GraphType  g_courseGraph;


// 题目来源:http://docs.ruanjiadeng.com/gopl-zh/ch5/ch5-06.html
/*var prereqs = map[string][]string{
    "algorithms": {"data structures"},
    "calculus": {"linear algebra"},
    "compilers": {
        "data structures",
        "formal languages",
        "computer organization",
    },
    "data structures":       {"discrete math"},
    "databases":             {"data structures"},
    "discrete math":         {"intro to programming"},
    "formal languages":      {"discrete math"},
    "networks":              {"operating systems"},
    "operating systems":     {"data structures", "computer organization"},
    "programming languages": {"data structures", "computer organization"},
}
*/

void initGraph()
{
    g_courseGraph["algorithms"].push_back("data structures");
    g_courseGraph["calculus"].push_back("linear algebra");

    g_courseGraph["compilers"].push_back("data structures");
    g_courseGraph["compilers"].push_back("formal languages");
    g_courseGraph["compilers"].push_back("computer organization");


    g_courseGraph["data structures"].push_back("discrete math");
    g_courseGraph["databases"].push_back("data structures");
    g_courseGraph["discrete math"].push_back("intro to programming");
    g_courseGraph["formal languages"].push_back("discrete math");
    g_courseGraph["networks"].push_back("operating systems");
         
    g_courseGraph["operating systems"].push_back("data structures");
    g_courseGraph["operating systems"].push_back("computer organization");
    g_courseGraph["programming languages"].push_back("data structures");
    g_courseGraph["programming languages"].push_back("computer organization");

}

vector<string> getAllCourceFrom(GraphType& input)
{
    std::vector<std::string> retvalVec;
   
    for (GraphType::iterator itor = input.begin();  itor != input.end(); itor++) {
        retvalVec.push_back(itor->first);
    }

    for (GraphType::iterator itor = input.begin();  itor != input.end(); itor++) {
        std::vector<string> v = itor->second;
        for(vector<string>::iterator it = v.begin(); it!=v.end(); it++){
            if(find(retvalVec.begin(), retvalVec.end(),*it) == retvalVec.end()) {
                retvalVec.push_back(*it);
            }
        }
    }


   return retvalVec;
}

// test getAllCourceFrom
void TestGetAllCourceFrom(){
    std::vector<std::string>  rst = getAllCourceFrom(g_courseGraph);
    copy(rst.begin(), rst.end(), ostream_iterator<string> (cout, "\n"));  
}

// 得到所有course的入度值
map<string, int>  getAllDegree(GraphType& input){
    map<string, int> degree;
    std::vector<std::string>  courseVec = getAllCourceFrom(input);
    for(vector<string>::iterator it = courseVec.begin(); it!=courseVec.end(); it++){   
       degree[*it]  =  input[*it].size();
    }

    return degree;
}


void TestGetAllDegree(){
   map<string, int>  rst =  getAllDegree(g_courseGraph);
   for(map<string, int>::iterator it = rst.begin(); it != rst.end(); it++)
   {
      cout << "key=" << it->first << ", value=" << it->second << endl;
   }
}

string findZero(std::vector<std::string>&  courseVec, map<string, int>& inputDegree ){ 
  for(vector<string>::iterator it = courseVec.begin(); it!=courseVec.end(); it++){   
       if(inputDegree[*it]  == 0){  // 找到第一个 入度为 0 的就退出了
           return  *it;
       }         
    }
    return "";
}

void TestFindZero()
{
    std::vector<std::string>  courseVec = getAllCourceFrom(g_courseGraph);
    map<string, int>  degree =  getAllDegree(g_courseGraph);
    
    cout << findZero(courseVec, degree) <<endl;
}


void update(string course, std::vector<std::string>&  courseVec,  map<string, int>& inputDegree, GraphType& inputGraph) 
{  
    if(course.empty()){ return;}
    courseVec.erase(remove(courseVec.begin(),courseVec.end(), course), courseVec.end());
    inputDegree[course] = -1; // 完全排除这个course

    for(map<string, int>::iterator it = inputDegree.begin(); it != inputDegree.end(); it++)
    {
      if(inputDegree[it->first] != -1 && find(inputGraph[it->first].begin(),inputGraph[it->first].end(), course) !=  inputGraph[it->first].end() )
      { 
           inputDegree[it->first]--;  // 入度 -1
      }
    }
}


void testUpdate()
{
    std::vector<std::string>  courseVec = getAllCourceFrom(g_courseGraph);
    map<string, int>  degree =  getAllDegree(g_courseGraph);
    update("computer organization",courseVec, degree, g_courseGraph);

   for(map<string, int>::iterator it = degree.begin(); it != degree.end(); it++)
   {
      cout << "before update:";
      cout << "key=" << it->first << ", value=" << it->second << endl;
   }
 
   cout << "after update:";
   copy(courseVec.begin(), courseVec.end(), ostream_iterator<string> (cout, "\n"));  
   for(map<string, int>::iterator it = degree.begin(); it != degree.end(); it++)
   {
      cout << "key=" << it->first << ", value=" << it->second << endl;
   }
}

// 实现依赖课程图的排序
bool topo(GraphType& inputGraph, vector<string>& outputVec)
 {
    vector<string> courseVec  =  getAllCourceFrom(inputGraph);  //得到所有course的vector
    map<string, int>   inputDegree = getAllDegree (inputGraph); // 保存所有 course 的入度情况
  //sort(InputDegree)  // 进行排序,排序按照字符串排序,排序的目的是可能有多个入度相同的,所以总得按照次序来逐个取
    string course;
   do{
        course = findZero(courseVec, inputDegree);  // 找到一个入度为 0的课程
        if(!course.empty())
        {
            outputVec.push_back(course);
            update(course, courseVec, inputDegree, inputGraph);
        }
    }while(course != ""); // 即如果还找得到入度为0 的点就继续,否则就退出了
  
   if(outputVec.size() < courseVec.size()) 
   {
       return false; //该有向图有回路
   }
   else
   {
       return true;
   }
}

int main()
{
   initGraph();

   vector<string> outputVec;
   if(topo(g_courseGraph, outputVec)){
       cout << "After topo sort:" <<endl;
       copy(outputVec.begin(), outputVec.end(), ostream_iterator<string> (cout, "\n")); 
   }
   
   return 0; 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值