【问题标题】:how to build a tree structure in C++ using std::map如何使用 std::map 在 C++ 中构建树结构
【发布时间】:2012-05-20 10:58:53
【问题描述】:

我正在尝试用 C++ 编写一种树状结构。就像每棵树都有树枝和树叶一样。一个分支可以包含其他分支以及叶子。 现在我的实现要求每个分支和叶子具有不同的功能。举个例子。 取树形结构

                                          Root                                             
                                |                          |                             
                             Branch1                     Branch2                     Branch3
      |                |                |
    Leaf1            Leaf2           Branch4

现在每个叶子和分支都有一个不同的函数要执行,所以叶子1将有一个名为leaf1_func的函数,叶子2将有一个叶子2_func,分支4有一个分支4_func。

我最初尝试实现复合设计模式。但这意味着我将拥有与叶子一样多的课程。但由于我有大量的树叶和树枝,我想避免创建更多的课程。我意识到这是一个不寻常的情况,但希望有人能在这方面帮助我。在不创建太多类的情况下实现这棵树的最佳方法是什么。

我也在使用 map STL 容器来存储数据,我想使用这个树实现来解决 TSP 问题。

#include <cstdlib>
#include <iostream>
#include <map>

using namespace std;

int n=4;
int min=1, max=10;




struct graph
{
int nodes;//total no. of nodes or vertices namely cities
std::map<std::pair<int,int>, int> graphMap;//an object that links a pair of vertices   
};


void directed_Graph(graph);

void directed_Graph(graph G)
{
//int n = G->nodes; //city count
int i, j;
for(i = 0; i <= n-1; i++)
{
    for(j = 0; j <= n-1; j++)
    {
        if(i!=j)
        {
            G.graphMap[std::make_pair(i,j)] = (rand()%10)+1;
            //cout<<G.graphMap[std::make_pair(i,j)]<<"\n";
        }

        else
        {
            G.graphMap[std::make_pair(i,j)] = 0;
        }

    }
}
}


int main(int argc, char** argv) 
{
graph g;
g.nodes = 4;

directed_Graph(g);

return 0;
}

【问题讨论】:

  • 引用的文本块是怎么回事?这是作业吗?
  • @Potatoswatter,不,这不是功课,我想建议如何避免使用这些功能

标签: c++ map tree


【解决方案1】:

具有相同签名的不同函数仍然具有相同的类型。即使函数完全不相关,您也可以通过使用void *(类型擦除)来存储随机数据的树,然后在到达叶节点后类型转换回已知的实际类型。

struct node {
    void (*fptr)(); // pointer to any function taking no args, no return
    void *data; // pointer to anything, need to cast before using
};

void f() { std::cout << "hello"; }
void g() { std::cout << "world"; }

node a = { f, f };
node b = { g, g };

a.fptr();
static_cast< void (*)() >( b.data )();

您还可以使用带有继承的虚方法,并在树中存储指向基类类型的指针。这取决于节点到底是什么。

这些都与它进入图表的事实无关。

【讨论】:

  • 没关系,你能帮我了解一下树实现的动态方式和并行它吗?
  • @visanio_learner 好吧,如果您已经选择了可行的树实现,那么除非您有充分的理由,否则更改它是没有意义的。您在上面显示的内容很好,除了顶点是int,因此不涉及任何功能。编辑:哦,但你应该调用 graphMap.size() 而不是变量int nodes;
  • 我的代码中没有涉及 func,我知道,我想从专家那里获得想法,我如何使用我使用 map(stl 容器)创建的图实现树结构我希望你现在已经理解我的问题了……你还建议我 maultimap 很好,我同意。
  • @visanio_learner 有很多方法可以实现树,每种方法都适用于不同的算法和应用程序。您选择了一种好方法,但是如果没有您正在做的事情,就无法说出哪种方法最好。看来你已经解决了图形问题,你需要一个函数问题的答案,这是分开的。无论哪种方式,我都需要更多细节才能给出更好的答案。
  • 我需要为我现在创建的这个图构建一棵树,三叉树结构对我有好处吗,因为我有很多根节点本身的子节点,如果我的 n 值为 5城市问题,那我可能有 4 个孩子……我应该用什么?三叉树是否足以解决我的问题
【解决方案2】:

从您的图表看来,您似乎想要一棵树,其中节点可以有两个以上的子节点。如果是这种情况,那么 STL 容器将不适合您。它们是自平衡二叉树。

如果你对二叉树没问题,那么有几种方法可以做到这一点。首先是编写函数,然后将函数指针或函子存储在树中。

#include <set>

int foo( ) {
  return 5;
}

std::set< int (*)( ) > my_set;
my_set.insert( &foo );

这种方法的问题是所有函数都必须具有相同的类型,即采用相同的参数并具有相同的返回类型。更重要的是,虽然它们可以定义不同的行为,但它们不能保持状态,即不能将数据存储在函数指针中。

正如您所提到的,第二个选项是编写类。如果您需要改变节点的行为,那么最好的方法是定义一个接口并使用多态性。

#include <set>
#include <iostream>

struct base {
  virtual void print( ) const = 0;
};

struct derived1 : public base {
  void print( ) const { std::cout << "derived1" << std::endl; }
};

struct derived2 : public base {
  void print( ) const { std::cout << "derived2" << std::endl; }
};

std::set< base* > my_set;

my_set.insert( new derived1( ));
my_set.insert( new derived2( ));

您没有说是否需要强制某些行为成为叶子而其他行为是内部节点,或者是否需要以特定方式对节点进行排序,但是如果您这样做了,那么您可以通过创建自定义小于函数:

bool operator < ( base const * const b1, base const * const b2 ) {
  // Figure out which is less here.
}

同样,如果您需要的不是二叉树,那么您就不走运了。而且,无论是函数还是类,您都需要编写一些代码来实现存储在每个节点中的行为。

【讨论】:

  • 我看不出这是如何产生树状结构的。
  • 我认为 OP 甚至不知道 STL 在“幕后”使用树。对他来说,这是一个无关紧要的实现细节。
  • @OliCharlesworth,看看我已经编辑了我的查询,看看我的编码到目前为止我已经使用#include 完成了,我不需要'set' stl 容器,我看到 map 是一种方法有效地存储数据。
  • @Potatoswatter:在许多意义上,它一个实现细节。 std::setstd::map 不会向用户公开父子关系,因此如果您想要一棵可以以类似树的方式操作的实际树,它们就没有用处。
  • @Oli:是的,这很公平。我想我有点过于关注有序存储的想法,而对树结构本身的关注不够,正如你所指出的,这似乎是这里的主要问题。
【解决方案3】:

如果树的深度有限,可以这样描述它:

typedef std::map<std::string, double> action_map_t;
typedef std::map<std::string, action_map_t> objid_map_t;
typedef std::map<std::string, objid_map_t> objtype_map_t;

//....等这里是深度== 3

objtype_map_t m_mapTooltipDuration;
m_mapTooltipDuration[objtype][objid][action] = atof(duration.c_str());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 2012-04-09
    • 2018-07-01
    相关资源
    最近更新 更多