5

我正在尝试用 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;
}
4

3 回答 3

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 )();

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

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

于 2012-05-20T11:30:57.400 回答
0

从您的图表看起来,您似乎想要一棵树,其中节点可以有两个以上的孩子。如果是这种情况,那么 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.
}

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

于 2012-05-20T11:15:19.680 回答
0

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

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());
于 2018-04-02T12:54:08.647 回答