4.7 编译顺序

     《程序员面试金典》(第六版)习题:仅为记录一下以加强印象,不为商业用途,如有侵权请联系删除。以下源码和解释参考了书中源码以及解释。
     拓扑排序法首先将项目的依赖关系构建为一张有向图,如果项目 a a a依赖于项目 b b b,则有一条由节点 b b b指向 a a a的有向边。根据项目之间的依赖关系,依照以上规则建立节点之间的有向图。然后首先将图中没有入边的节点拿出来,拿出的顺序没有要求,再将以之前拿出的节点为出射节点的边拿掉。再迭代以上过程直到图中没有节点位置

//拓扑排序法
class Project
{
    private:
        string name;
        int dependencies;
        vector<Project> *children;
        unordered_map<string, Project> *hashMap;
    public:
        Project(string str="")
        {
            name = str;
            dependencies = 0;
            children=new vector<Project>();
            hashMap=new unordered_map<string, Project>();
        }
        void addNeighbor(Project &node)
        {
            if (hashMap->find(node.getName())==hashMap->end())
            {
                node.increDependencies();
                children->push_back(node);
                hashMap->emplace(node.getName(), node);
            }
        }
        string getName()
        {
            return name;
        }
        void increDependencies()
        {
            dependencies++;
        }
        void decreDependencies()
        {
            dependencies--;
        }
        vector<Project>* getChildren()
        {
            return children;
        }
        int getDependencies()
        {
            return dependencies;
        }
        void setDependencies(int value)
        {
            dependencies=value;
        }
        void setChildren(vector<Project>* value)
        {
            children = value;
        }
};

class Graph
{
    private:
        vector<Project> *nodes;
        unordered_map<string, Project> *hashMap;
        int nodeNum;
    public:
        Graph()
        {
            nodes=new vector<Project>();
            hashMap=new unordered_map<string, Project>();
            nodeNum = 0;
        }
        Project& getOrCreateNode(string str)
        {
            if (hashMap->find(str) == hashMap->end())
            {
                nodeNum++;
                Project node(str);
                nodes->push_back(node);
                hashMap->emplace(node.getName(), node);
            }
            return hashMap->at(str);
        }
        void addEdge(string startname,string endname)
        {
            /*Project &start = getOrCreateNode(startname);
            Project &end = getOrCreateNode(endname);
            start.addNeighbor(end);*/
            getOrCreateNode(startname).addNeighbor(getOrCreateNode(endname));
        }
        vector<Project>* getNodes()
        {
            return nodes;
        }
        int getNodeNum()
        {
            return nodeNum;
        }
        unordered_map<string, Project>* gethashMap()
        {
            return hashMap;
        }
        void setNodes()
        {
            for (int i = 0; i < nodes->size(); i++)
            {
                nodes->at(i).setDependencies(hashMap->at(nodes->at(i).getName()).getDependencies());
                nodes->at(i).setChildren(hashMap->at(nodes->at(i).getName()).getChildren());
            }
        }
};

int addNonDependent(Project* order,vector<Project>& projects, int offset)
{
    for (Project project : projects)
    {
        if (project.getDependencies() == 0)
        {
            order[offset] = project;
            offset++;
        }
    }
    return offset;
}

Project* orderProjects(vector<Project> &projects)
{
    int size = projects.size();
    Project *order=new Project[size];
    int endOfList = addNonDependent(order, projects, 0);
    int toBeProcessed = 0;
    while (toBeProcessed<size)
    {
        if (endOfList == 0)
            return nullptr;
        Project &current = order[toBeProcessed];
        for (Project& project : (*current.getChildren()))
        {
            project.decreDependencies();
        }
        endOfList= addNonDependent(order, (*current.getChildren()), endOfList);
        toBeProcessed++;
    }
    return order;
}

Graph buildGraph(vector<string> projects, vector<pair<string, string>> dependencies)
{
    Graph myGraph;
    for (string str : projects)
    {
        myGraph.getOrCreateNode(str);

    }
    for (pair<string, string> dependency : dependencies)
    {
        string first = dependency.first;
        string second = dependency.second;
        myGraph.addEdge(first, second);
    }
    myGraph.setNodes();
    return myGraph;
}

Project* findBuildOrder(vector<string> projects, vector<pair<string, string>> dependencies)
{
    Graph graph = buildGraph(projects, dependencies);
    return orderProjects(*graph.getNodes());
}
//测试程序
int main()
{
	vector<pair<string, string>> dependencies;
	pair<string, string> p1("f", "c");
	pair<string, string> p2("f", "b");
	pair<string, string> p3("f", "a");
	pair<string, string> p4("c", "a");
	pair<string, string> p5("b", "a");
	pair<string, string> p6("a", "e");
	pair<string, string> p7("b", "e");
	pair<string, string> p8("d", "g");
	dependencies.push_back(p1);
	dependencies.push_back(p2);
	dependencies.push_back(p3);
	dependencies.push_back(p4);
	dependencies.push_back(p5);
	dependencies.push_back(p6);
	dependencies.push_back(p7);
	dependencies.push_back(p8);
	vector<string> projects;
	projects.push_back("a");
	projects.push_back("b");
	projects.push_back("c");
	projects.push_back("d");
	projects.push_back("e");
	projects.push_back("f");
	projects.push_back("g");
	Project* p=findBuildOrder(projects,dependencies);
	cout << "The true order is:"<< endl;
	for (int i = 0; i < 7; i++)
	{
		cout << p[i].getName() << endl;
	}
}
 
图1. 测试结果

     深度优先搜索方法从通过节点间的依赖关系建立起来的图中的任意一个节点开始深度优先搜索,当遇到没有孩子的节点(没有出射边)或所有孩子节点状态不为 b l a n k blank blank的节点时,将该节点入栈并将该节点状态设置为 c o m p l e t e complete complete。完成整个深度优先搜索后,从栈顶到栈顶即为项目的编译顺序。

//DFS方法
enum State { complete, partial, blank };

class Project
{
private:
    string name;
    State state;
    vector<Project*>* children;
    unordered_map<string, Project*>* hashMap;
public:
    Project(string str = "")
    {
        name = str;
        state = blank;
        children = new vector<Project*>();
        hashMap = new unordered_map<string, Project*>();
    }
    void addNeighbor(Project* node)
    {
        if (hashMap->find(node->getName()) == hashMap->end())
        {
            children->push_back(node);
            hashMap->emplace(node->getName(), node);
        }
    }
    string getName()
    {
        return name;
    }
    vector<Project*>* getChildren()
    {
        return children;
    }
    State getState()
    {
        return state;
    }
    void setState(State value)
    {
        state = value;
    }
    void setChildren(vector<Project*>* value)
    {
        children = value;
    }
};

class Graph
{
private:
    vector<Project*>* nodes;
    unordered_map<string, Project*>* hashMap;
    int nodeNum;
public:
    Graph()
    {
        nodes = new vector<Project*>();
        hashMap = new unordered_map<string, Project*>();
        nodeNum = 0;
    }
    Project* getOrCreateNode(string str)
    {
        if (hashMap->find(str) == hashMap->end())
        {
            nodeNum++;
            Project *node=new  Project(str);
            nodes->push_back(node);
            hashMap->emplace(node->getName(), node);
        }
        return hashMap->at(str);
    }
    void addEdge(string startname, string endname)
    {
        getOrCreateNode(startname)->addNeighbor(getOrCreateNode(endname));
    }
    vector<Project*>* getNodes()
    {
        return nodes;
    }
    int getNodeNum()
    {
        return nodeNum;
    }
    unordered_map<string, Project*>* gethashMap()
    {
        return hashMap;
    }
    void setNodes()
    {
        for (int i = 0; i < nodes->size(); i++)
        {
            //nodes->at(i).setState(hashMap->at(nodes->at(i).getName()).getState());
            nodes->at(i)->setChildren(hashMap->at(nodes->at(i)->getName())->getChildren());
        }
    }
};
bool doDFS(Project* project, stack<Project*>* order)
{
    cout <<"Go into project: " << project->getName() <<", It has "<<project->getChildren()->size()<<" children."<<endl;
    if (project->getState() == partial)
    {
        cout << "return2323232323" << endl;
        return false;
    }
    if(project->getState() == blank)
    {
        project->setState(partial);
        if (project->getChildren()->size() != 0)
        {
            for (Project*  pro : (*project->getChildren()))
            {
                if (!doDFS(pro, order))
                    return false;
            }
        }
        cout << "Push project: "<< project->getName() <<endl;
        project->setState(complete);
        order->push(project);
    }
    cout << "Return from project: " << project->getName() <<endl;
    return true;
}

stack<Project*>* orderProjects(vector<Project*> * projects)
{
    stack<Project*> *order=new stack<Project*>();
    for (Project* project : *projects)
    {
        if (project->getState() == blank)
        {
            if (!doDFS(project, order))
                return nullptr;
        }
    }
    return order;
}

Graph buildGraph(vector<string> projects, vector<pair<string, string>> dependencies)
{
    Graph myGraph;
    for (string str : projects)
    {
        myGraph.getOrCreateNode(str);

    }
    for (pair<string, string> dependency : dependencies)
    {
        string first = dependency.first;
        string second = dependency.second;
        myGraph.addEdge(first, second);
    }
    myGraph.setNodes();
    return myGraph;
}

stack<Project*>* findBuildOrder(vector<string> projects, vector<pair<string, string>> dependencies)
{
    Graph graph = buildGraph(projects, dependencies);
    return orderProjects(graph.getNodes());
}
//测试程序
int main()
{
	vector<pair<string, string>> dependencies;
	pair<string, string> p1("f", "c");
	pair<string, string> p2("f", "b");
	pair<string, string> p3("f", "a");
	pair<string, string> p4("c", "a");
	pair<string, string> p5("b", "a");
	pair<string, string> p6("a", "e");
	pair<string, string> p7("b", "e");
	pair<string, string> p8("d", "g");
	dependencies.push_back(p1);
	dependencies.push_back(p2);
	dependencies.push_back(p3);
	dependencies.push_back(p4);
	dependencies.push_back(p5);
	dependencies.push_back(p6);
	dependencies.push_back(p7);
	dependencies.push_back(p8);
	vector<string> projects;
	projects.push_back("a");
	projects.push_back("b");
	projects.push_back("c");
	projects.push_back("d");
	projects.push_back("e");
	projects.push_back("f");
	projects.push_back("g");
	stack<Project*>* p=findBuildOrder(projects,dependencies);
	cout << "The true order is:"<< endl;
	cout << "p->size()=" << p->size() << endl;
	int stackSize = p->size();
	for (int i = 0; i < stackSize; i++)
	{
		cout << p->top()->getName() << endl;
		p->pop();
	}
}
 
图1. 测试结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qqssss121dfd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值