遍历 AOV 图的所有结点
巨坑,懒得填了。上个学期的数据结构课设,没用到的算法。
//
// main.cpp
// 教学计划编制系统
//
// Created by 郭子睿 on 2017/3/6.
// Copyright © 2017年 郭子睿. All rights reserved.
//
#include "CourseGraph.hpp"
int main(int argc, const char * argv[]) {
Course A,B,C,D,E,F,G,H,I,J,K,L;
A.No=1;B.No=2;C.No=3;D.No=4;E.No=5;
F.No=6;G.No=7;H.No=8;
I.No=9;J.No=10;
K.No=11;
L.No=12;
A.Credit=2;
B.Credit=3;
C.Credit=4;
D.Credit=3;
E.Credit=2;
F.Credit=3;
G.Credit=4;
H.Credit=4;
I.Credit=7;
J.Credit=5;
L.Credit=2;
A.Name="高等数学";
B.Name="大学物理";
C.Name="数据库";
D.Name="C++";
E.Name="数据结构";
F.Name="计算机组成原理";
G.Name="计算机图形学";
H.Name="大学英语";
I.Name="计算机体系结构";
J.Name="操作系统";
K.Name="Java";
L.Name="人工智能";
B.DirectNo.push_back(1);
C.DirectNo.push_back(1);
C.DirectNo.push_back(2);
D.DirectNo.push_back(1);
E.DirectNo.push_back(3);
E.DirectNo.push_back(4);
F.DirectNo.push_back(11);
G.DirectNo.push_back(3);
H.DirectNo.push_back(3);
H.DirectNo.push_back(6);
J.DirectNo.push_back(9);
K.DirectNo.push_back(9);
L.DirectNo.push_back(9);
L.DirectNo.push_back(10);
L.DirectNo.push_back(1);
CourseGraph AI;
AI.add_course(&A);
AI.add_course(&B);
AI.add_course(&C);
AI.add_course(&D);
AI.add_course(&E);
AI.add_course(&F);
AI.add_course(&G);
AI.add_course(&H);
AI.add_course(&I);
AI.add_course(&J);
AI.add_course(&K);
AI.add_course(&L);
bool FUCK=AI.build_graph();
if(FUCK){
AI.build_tree();
Term T(6,10);
AI.build_path(T,9);
AI.arrange_loose();
cout<<endl<<endl;
AI.arrange_tight();
}
return 0;
}
//
// CourseGraph.hpp
// 教学计划编制系统
//
// Created by 郭子睿 on 2017/3/10.
// Copyright © 2017年 郭子睿. All rights reserved.
//
#ifndef CourseGraph_hpp
#define CourseGraph_hpp
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
//课程———————————————————————————————————————————————————————————————————————————
struct Course{
int No=0;//课程编号
string Name="";//课程名字
int Credit=0;//学分
vector<int> DirectNo;//直接先修课程编号
Course* Link=NULL;//用于建立图的链表存储
Course* LChild=NULL;
Course* RChild=NULL;
Course* Parent=NULL;
Course(){}
Course(const Course& A){
Parent=A.Parent;
No=A.No;
Name=A.Name;
Credit=A.Credit;
for(int i=0;i<A.DirectNo.size();++i)
DirectNo.push_back(A.DirectNo[i]);
}
void operator=(const Course& A){
No=A.No;
Name=A.Name;
Credit=A.Credit;
for(int i=0;i<A.DirectNo.size();++i)
DirectNo.push_back(A.DirectNo[i]);
}
};
//学期———————————————————————————————————————————————————————————————————————————
struct Term{
int Credit;//每学期学分
int CurrentTerm;//当前学期
int M;//当前学期所剩学分
Term(int Credit_,int SumTerm_){
Credit=Credit_;
M=Credit;
CurrentTerm=SumTerm_;
}
Term(const Term& tl){
Credit=tl.Credit;
M=Credit;
CurrentTerm=tl.CurrentTerm;
}
};
//安排———————————————————————————————————————————————————————————————————————————
class CourseGraph{
vector<Course*> Courses;//用于存储课程信息;并用于存储有向图
Course* Tree=NULL;//用于存储有向图
vector<vector<int>> Arrange;
ofstream Save;
public:
CourseGraph(){
Save.open("/Users/guozirui/Desktop/arrangement.txt");
}
~CourseGraph(){
Save.close();
for (int i=0; i<Courses.size(); ++i){//删除 Courses
Course* temp=Courses[i]->Link;
while(Courses[i]->Link!=NULL){
while(temp!=NULL)
temp=temp->Link;
delete temp;
temp=Courses[i]->Link;
}
delete Courses[i];
}
destroy(Tree);//删除 Tree
}
void add_course(Course* temp);//增加课程
bool build_graph();//建图
void build_tree();
void build_tree_part1(Course* Root);
void build_tree_part2(Course* Root,stack<Course*>& TEMP_);
Course* operator[](int i);//按课程编号搜索,返回课程
int return_no(int i);//按课程编号搜索,返回课程在 Courses 里的位置
vector<stack<Course>> caculate_path();
void find_leaf(Course* Root,vector<stack<Course*>>& Way);
void build_path(const Term& T,int Wanted);
void show_arrange(vector<int> C,bool X);
void rank(bool A);//A 为假,升序排列;A 为真,降序排列。
void arrange_tight();//紧密安排
void arrange_loose();//均匀安排
//其他操作——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
void destroy(Course* Root){
if(Root==NULL)
return;
if(Root->LChild==NULL&&Root->RChild==NULL){
delete Root;
Root=NULL;
}
else{
if(Root->LChild!=NULL)
destroy(Root->LChild);
if(Root->RChild!=NULL)
destroy(Root->RChild);
}
}
void swap(vector<int>* a,vector<int>* b){
vector<int> temp;
temp=*a;
*a=*b;
*b=temp;
}
};
#endif /* CourseGraph_hpp */
//
// CourseGraph.cpp
// 教学计划编制系统
//
// Created by 郭子睿 on 2017/3/10.
// Copyright © 2017年 郭子睿. All rights reserved.
//
#include "CourseGraph.hpp"
void CourseGraph::rank(bool A){
if(A){//升序排列;松散安排(因为比较的是剩余学期数,所以剩余学期数越小的安排得越松散)
for(int i=0;i<Arrange.size();++i){
for(int j=(int)Arrange.size()-1;j>i;j--){
if(Arrange[j].back()<Arrange[j-1].back()){
swap(&Arrange[j], &Arrange[j-1]);
}
}
}
}
else{//降序排列;紧密安排
for(int i=0;i<Arrange.size();++i){
for(int j=(int)Arrange.size()-1;j>i;j--){
if(Arrange[j][Arrange[j].size()-2]>Arrange[j-1][Arrange[j].size()-2]){
swap(&Arrange[j], &Arrange[j-1]);
}
}
}
}
}
void CourseGraph::add_course(Course *temp){
Courses.push_back(temp);
}
bool CourseGraph::build_graph(){
for(int i=0;i<Courses.size();++i){//建图
if(Courses[i]->DirectNo.size()==0)//如果该课程没有先决课程
continue;//那么继续
else{//如果该课程有先决课程
for(int j=0;j<Courses[i]->DirectNo.size();++j){
Course* temp=new Course(*Courses[i]);
if(return_no(Courses[i]->DirectNo[j])==-1){
cout<<"课程设置错误!";
return false;
}
Course* temp1=Courses[return_no(Courses[i]->DirectNo[j])];
while(temp1->Link!=NULL)
temp1=temp1->Link;
temp1->Link=temp;
}
}
}
Course* temp=NULL;
for(int i=0;i<Courses.size();++i){
if(Tree==NULL&&Courses[i]->DirectNo.size()==0){
Tree=new Course(*Courses[i]);
temp=Tree;
continue;
}
if(Courses[i]->DirectNo.size()==0){
while(temp->RChild!=NULL)
temp=temp->RChild;
temp->RChild=new Course(*Courses[i]);
}
}
return true;
}
Course* CourseGraph::operator[](int i){
for(int j=0;j<Courses.size();++j)
if(Courses[j]->No==i)
return Courses[j];
return NULL;
}
int CourseGraph::return_no(int i){
for(int j=0;j<Courses.size();++j)
if(Courses[j]->No==i)
return j;
return -1;
}
void CourseGraph::build_tree(){
stack<Course*> TEMP;
for(int L=0;L<Courses.size();++L){
build_tree_part2(Tree,TEMP);
while(!TEMP.empty()){
build_tree_part1(TEMP.top());
TEMP.pop();
}
}
}
void CourseGraph::build_tree_part1(Course *Root){
Course* temp=NULL;
Course* temp1=NULL;
Course* temp2=NULL;
if(Root==NULL)
return;
bool* Ava=new bool[Courses.size()]{false};//用于保存已经安排的课程个数
temp=Root->Parent;
while(temp!=NULL){//用于计算已经选过的课程
Ava[return_no(temp->No)]=true;//将已经选过的课程置为已选
temp=temp->Parent;
}
if(Root->Parent==NULL){//如果该课程没有父母结点
temp=Tree;
while(temp!=NULL){
if(temp!=Root){
if(Root->LChild==NULL){
Ava[return_no(temp->No)]=true;
Root->LChild=new Course(*temp);
Root->LChild->Parent=Root;
temp2=Root->LChild;
}
else{
Ava[return_no(temp->No)]=true;
temp2->RChild=new Course(*temp);
temp2->RChild->Parent=Root;
temp2=temp2->RChild;
}
}
temp=temp->RChild;
}
temp1=Courses[return_no(Root->No)]->Link;
if(temp1==NULL)
return;
while(temp1!=NULL){
if(Root->LChild==NULL){
temp=new Course(*temp1);
if(Ava[return_no(temp->No)]==false){
Ava[return_no(temp->No)]=true;
Root->LChild=temp;
temp->Parent=Root;
temp2=Root->LChild;
}
}
else{
temp=new Course(*temp1);
if(Ava[return_no(temp->No)]==false){
Ava[return_no(temp->No)]=true;
temp2->RChild=temp;
temp2=temp2->RChild;
temp2->Parent=Root;
}
}
temp1=temp1->Link;
}
return;
}
else{
temp1=NULL;
temp2=NULL;
temp=Root->Parent->LChild;//让 temp 指针指向第一个孩子
while(temp==Root)
temp=temp->RChild;//找到 Root 的父母的第一个不是 Root 的孩子
if(temp!=NULL){
temp1=new Course(*temp);//temp1 用于新建结点
Root->LChild=temp1;
Ava[return_no(temp1->No)]=true;
Root->LChild->Parent=Root;
temp=temp->RChild;
temp2=Root->LChild;
while(temp!=NULL){
if(temp==Root){
temp=temp->RChild;
continue;
}
temp1=new Course(*temp);
temp2->RChild=temp1;
temp2->RChild->Parent=Root;
Ava[return_no(temp1->No)]=true;
temp=temp->RChild;
temp2=temp2->RChild;
}
}
temp=Courses[return_no(Root->No)]->Link;
while (temp!=NULL){
if(Root->LChild==NULL){
if(Ava[return_no(temp->No)]!=true){
temp1=new Course(*temp);
Root->LChild=temp1;
Root->LChild->Parent=Root;
temp2=Root->LChild;
}
temp=temp->Link;
}
else{
if(Ava[return_no(temp->No)]!=true){
temp1=new Course(*temp);
temp2->RChild=temp1;
temp2->RChild->Parent=Root;
temp2=temp2->RChild;
}
temp=temp->Link;
}
}
}
}
void CourseGraph::build_tree_part2(Course* Root,stack<Course*>& TEMP_){
if(Root->LChild==NULL)
TEMP_.push(Root);
if(Root->LChild!=NULL)
build_tree_part2(Root->LChild,TEMP_);
if(Root->RChild!=NULL)
build_tree_part2(Root->RChild,TEMP_);
return;
}
void CourseGraph::find_leaf(Course* Root,vector<stack<Course*>>& Way){
if(Root->LChild==NULL&&Root->RChild==NULL){
stack<Course*> temp;
Course* temp1=new Course(*Root);
temp.push(temp1);
Way.push_back(temp);
return;
}
else{
if(Root->LChild!=NULL)
find_leaf(Root->LChild,Way);
if(Root->RChild!=NULL)
find_leaf(Root->RChild,Way);
return;
}
}
void CourseGraph::build_path(const Term& T,int Wanted){
vector<stack<Course*>> Way;
find_leaf(Tree,Way);
int Plus;
if(Wanted>Way.size())
Plus=1;
else
Plus=(int)((float)Way.size()/Wanted+0.5);
for(int i=0;i<Way.size();i=i+Plus){//求出所有路径
Course* temp=Way[i].top();
while(temp->Parent!=NULL){
Course* temp1=new Course(*temp->Parent);
Way[i].push(temp1);
temp=temp->Parent;
}
}
for(int i=0;i<Way.size();i=i+Plus){
Term TL(T);
for(int j=0;j<Way[i].size();j++){
vector<int> C;
C.push_back(0);
while(Way[i].size()!=0){
if(TL.M>=Way[i].top()->Credit){//如果该学期学分还够的话
TL.M-=Way[i].top()->Credit;//就减去该课程学分
C.push_back(Way[i].top()->No);
delete Way[i].top();
Way[i].pop();
}
else{
TL.CurrentTerm--;
if(TL.CurrentTerm==0&&Way[i].size()!=0)
break;
C.push_back(0);
TL.M=TL.Credit;
TL.M-=Way[i].top()->Credit;
C.push_back(Way[i].top()->No);
delete Way[i].top();
Way[i].pop();
}
}
if(Way[i].size()!=0)
continue;
C.push_back(TL.CurrentTerm);
C.push_back(TL.CurrentTerm);
Arrange.push_back(C);
}
}
for(int i=0;i<Way.size();++i){
while(!Way[i].empty()){
delete Way[i].top();
Way[i].pop();
}
Way.pop_back();
}
for(int i=0;i<Arrange.size();++i){
for(int j=1;j<Arrange[i].size()-2;++j){
if(Arrange[i].back()<2)
break;
if(Arrange[i][j]==0||Arrange[i][j]==-1)
continue;
else if(Arrange[i][j-1]!=0&&Arrange[i][j-1]!=-1){
Arrange[i].insert(Arrange[i].begin()+j,-1);
Arrange[i].back()--;
}
}
}
}
void CourseGraph::arrange_tight(){
cout<<"!!!!!!!!!!!!!!!!!!紧密安排!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
Save<<"!!!!!!!!!!!!!!!!!!紧密安排!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
for(int i=0;i<Arrange.size();++i){
cout<<"第"<<i+1<<"种方法";
Save<<"第"<<i+1<<"种方法";
show_arrange(Arrange[i],0);
cout<<endl<<endl;
Save<<endl<<endl;
}
}
void CourseGraph::arrange_loose(){
cout<<"!!!!!!!!!!!!!!!!!!松散安排!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
Save<<"!!!!!!!!!!!!!!!!!!松散安排!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
for(int i=0;i<Arrange.size();++i){
cout<<"第"<<i+1<<"种方法";
Save<<"第"<<i+1<<"种方法";
show_arrange(Arrange[i],1);
cout<<endl<<endl;
Save<<endl<<endl;
}
}
void CourseGraph::show_arrange(vector<int> C,bool X){
if(X){
int k=1;
for(int i=0;i<C.size()-2;++i){
if(C[i]==0||C[i]==-1){
cout<<endl<<"第"<<k<<"学期"<<endl;
Save<<endl<<"第"<<k<<"学期"<<endl;
k++;
}
else{
cout<<"课程编号:"<<Courses[return_no(C[i])]->No<<" "<<"学分:"<<Courses[return_no(C[i])]->Credit<<endl;
Save<<"课程编号:"<<Courses[return_no(C[i])]->No<<" "<<"学分:"<<Courses[return_no(C[i])]->Credit<<endl;
cout<<"课程名称:"<<Courses[return_no(C[i])]->Name<<endl;
Save<<"课程名称:"<<Courses[return_no(C[i])]->Name<<endl;
}
}
}
else{
int k=1;
for(int i=0;i<C.size()-2;++i){
if(C[i]==0){
cout<<endl<<"第"<<k<<"学期"<<endl;
Save<<endl<<"第"<<k<<"学期"<<endl;
k++;
}
else if(C[i]==-1)
continue;
else{
cout<<"课程编号:"<<Courses[return_no(C[i])]->No<<" "<<"学分:"<<Courses[return_no(C[i])]->Credit<<endl;
Save<<"课程编号:"<<Courses[return_no(C[i])]->No<<" "<<"学分:"<<Courses[return_no(C[i])]->Credit<<endl;
cout<<"课程名称:"<<Courses[return_no(C[i])]->Name<<endl;
Save<<"课程名称:"<<Courses[return_no(C[i])]->Name<<endl;
}
}
}
}