面向对象的图形在c ++中的实现

时间:2014-04-15 20:34:46

标签: c++ oop object graph directed-acyclic-graphs

我必须使用图形在c ++上实现WWW的模拟,其中节点是网页,有向边是URL。

在学校,在我们的水平上,我们仍然从面向对象编程开始,所以他们建议使用邻接列表和邻接矩阵来实现,但我不喜欢它们,因为它们是记忆怪物并且非常有限。

问题:
你能提出另一种数据结构(最好是面向对象的东西),它使用指针(作为边缘)到其他节点,我可以动态生成尽可能多的边缘吗?

我已经读过这篇文章,但我找不到任何有用的信息: Object Oriented implementation of graph data structures

1 个答案:

答案 0 :(得分:2)

老实说,只想在一个数据结构中表示这一点,结果会非常低效。实际上,您有一个较小的域名注册商列表,提供查找。比单个哑图更精确的是:

#include <iostream>
#include <memory>
#include <map>
#include <vector>
#include <string>
#include <set>

class Webpage;
class Registrar : public std::enable_shared_from_this<Registrar> {
public:
    std::shared_ptr<Webpage> resolve(const std::string &url);
private:
    std::map<std::string, std::shared_ptr<Webpage>> pages;
};

class Webpage {
public:
    Webpage(std::shared_ptr<Registrar> registrar, const std::string &url) :
        registrar(registrar),
        url(url){
    }

    std::shared_ptr<Webpage> addLink(const std::string &url){
        links.push_back(url);
        return registrar->resolve(url);
    }

    std::vector<std::shared_ptr<Webpage>> resolvePageLinks(){
        std::vector<std::shared_ptr<Webpage>> pages;
        for (auto &linkUrl : links){
            pages.push_back(registrar->resolve(linkUrl));
        }
        return pages;
    }

    std::string getUrl() const{
        return url;
    }
private:
    std::string url;
    std::shared_ptr<Registrar> registrar;
    std::vector<std::string> links;
};

std::shared_ptr<Webpage> Registrar::resolve(const std::string &url){
    auto found = pages.find(url);
    if (found != pages.end()){
        return found->second;
    }
    else{
        auto webpage = std::make_shared<Webpage>(shared_from_this(), url);
        pages.insert({url, webpage});
        return webpage;
    }
}

void printPageHierarchy(std::shared_ptr<Webpage> current, int depth, std::set<std::shared_ptr<Webpage>> &visited){
    std::cout << std::string(3*depth, ' ');
    std::cout << current->getUrl() << std::endl;
    if (visited.find(current) == visited.end()){
        visited.insert(current);
        ++depth;
        for (auto page : current->resolvePageLinks()){
            printPageHierarchy(page, depth, visited);
        }
    }else{
        std::cout << std::string(3*depth, ' ');
        std::cout << "..." << std::endl;
    }
}

void printPageHierarchy(std::shared_ptr<Webpage> current){
    std::set<std::shared_ptr<Webpage>> visited;
    printPageHierarchy(current, 0, visited);
}

int main(){
    auto registrar = std::make_shared<Registrar>();
    auto site1 = registrar->resolve("site1.com");
    site1->addLink("site2.com");
    site1->addLink("site3.com")->addLink("site4.com")->addLink("site1.com");
    std::cout << "From site1.com:" << std::endl;    
    printPageHierarchy(site1);

    std::cout << "_____________\nFrom site3.com:" << std::endl;
    printPageHierarchy(registrar->resolve("site3.com"));
}

这非常简单,显然很少。你的问题让你有点不清楚你的要求究竟是什么。