1

I have a structure s :

struct s{
   int x;
  /********************************************************************
   *  NoOfchild doesn't represent maximum no of children for node s . 
   *  This represent no of children node s have at any given instance . 
   *********************************************************************/      
   int NoOfChild; 
   s  **child;
}

I would like to use ** to declare array of pointers dynamically . Node s is added one by one to array .There is any way to achieve this. This tree is going to use for FpGrowth Algorithm.

                                         *(0) 
                                           |
          _____________________________________________________________
          |                                |                          | 
       [* (1)                             *(2)                      *(3)]
          |                                |                          |
_______________                    _________________        __________________________
|    |    |   |                   |        |       |        |    |    |     |    |   |
[*   *    *   *]                  [*       *       *]      [*    *    *     *    *   *]

** represent Node s . I don't want to declare all children of a node at the same time i.e. I would like to add child node one by one when ever it's required . e.g. o is added as root then node 1 is added as child of root if it requires then node 2 is added and so on .[* * * * ] represents children of a node x .

Edit:
People are assuming NoOfChild as maximum no of a child for a given node that's not true ,Here NoOfChild represents how many children a node have at given instance , it may vary according to requirement or time to time .
Explanation :
Initially node 0 is Initialized so it has zero(0) child .
then node 1 is added as child of node 0 so o->NoOfChild = 1 and 1 ->NoOfChild = 0 ;
then node [*] is added as child of node 1 so 0->NoOfChild = 1 and 1 ->NoOfChild = 1 ;
then 2 is added as child of node 0 so 0->NoOfChild = 2 and 1 ->NoOfChild = 1 ;
and so on .

Edit:
Finally used vector<s*> child .

user3919801
  • 519
  • 1
  • 4
  • 14
  • 5
    Use `vector`, or even `vector`. – Anton Savin Sep 29 '14 at 14:32
  • 2
    If you're doing it in c++ then use a vector or a list, not an array. Save some memory and a headache. – RockOnRockOut Sep 29 '14 at 14:33
  • In C you would use `(s**)malloc(sizeof(s*) * n)` where `n` is the number of elements you need to store, and a similar `realloc()` call when resizing. – cdhowie Sep 29 '14 at 14:33
  • 1
    Yes, it is possible, but it is unnecessarily complicated. It is a tree, not a general graph, so you could use arrays of `s` rather than arrays of `s*`, and avoid useless indirection. Also, containers like `std::vector` will spare you a lot of headaches. – Beta Sep 29 '14 at 14:34
  • @cdhowie This leads to overhead of resizing again and again . – user3919801 Sep 29 '14 at 14:35
  • 2
    @user3919801 Then you can do similar to what `std::vector` does, and allocate more than you need, differentiating "size" (the number of actual elements you have stored) from "capacity" (the number of elements you could fit in the allocation). Of course, you should only take this approach in C. If you are using C++ then you should just use `std::vector` as others have pointed out. – cdhowie Sep 29 '14 at 14:36
  • C and C++ are different languages, and in this case C++ will have very different answers. Unless you are asking for a compare/contrast or know how in one but not the other, you should generally tag only the language you are using/compiling/ – crashmstr Sep 29 '14 at 14:38
  • 2
    A simple idea is to point to the first child an this child points to its next sibling or itself if there is no other child. – tgmath Sep 29 '14 at 14:39
  • @crashmstr removed C . Concept of pointer is same in both language except typecasting . – user3919801 Sep 29 '14 at 14:41
  • The simple answer is `child = new s*[number of children];` but there is a lot of messy, error prone, reallocating, copying, deallocating involved when you need to add more children if you use this design. – Galik Sep 29 '14 at 14:52
  • @user3919801 *pointers* are the same, but C++ has smart pointers as well as dynamic container classes that reduce the need to use raw pointers. i.e. the "natural" C++ solution. – crashmstr Sep 29 '14 at 14:54
  • @Galik Yes you are correct . – user3919801 Sep 29 '14 at 14:56
  • 1
    @AntonSavin Better not using `vector`.It would trigger an [undefined behavior](http://stackoverflow.com/questions/6517231/are-c-recursive-type-definitions-possible-in-particular-can-i-put-a-vectort) – Sérgio Castelani Sep 29 '14 at 15:49
  • @user: If a answer solved your problem, you should mark it as accepted. If you solved your problem yourself, answer your own question. – GingerPlusPlus Oct 02 '14 at 18:18

5 Answers5

3

For general tree data structure you can use :-

 struct tree{
 int element;
 struct tree *firstchild;
 struct tree *nextsibling;
 };

element contains the data to be inserted at the node.

FirstChild contains the firstchild of the node.

nextsibling contains the other child of the same parent node. Example :-

   A

 B  C  D

EF  G     H

then A->firstchild = B; B->nextsibling=C; C->nextsibling=D; B->firstchild=E; E->nextsibling=F; C->firstchild=g; D->firstchild=H;

Other values which are not specified can taken as NULL;

Ajay
  • 4,773
  • 3
  • 23
  • 36
  • 1
    I don't... what? Did you accidentally click save in the middle of writing this answer? – cdhowie Sep 29 '14 at 14:35
  • @Ajay don't want to use firstchild , nextsibling node structure . – user3919801 Sep 29 '14 at 14:44
  • 1
    What was the idea of the original empty answer? Just putting something to be first? – stefaanv Sep 29 '14 at 14:44
  • It looks like the OP is not looking for a binary tree data structure, so you might have to reconsider your answer – smac89 Sep 29 '14 at 14:47
  • Anyway, the tag is now C++ only, so the sanest way is a class with entries NodeData (template) and vector of children. – stefaanv Sep 29 '14 at 14:48
  • @Smac89 it's a generic tree structure. with the help two pointers per node nextsibling and firstchild you can make a generic tree in c language – Ajay Sep 29 '14 at 14:49
  • @Ajay That's my point, there is no guarantee each node will only have 2 child nodes. Even from the OP's diagram this is obvious, making the OP's structure more generic than yours in that sense – smac89 Sep 29 '14 at 14:52
  • @Smac89 General tree can be implemented using two pointers as he suggest but i don't like this node structure . – user3919801 Sep 29 '14 at 14:55
  • @Smac89 you can add more node to my example and should verify the condition. if any problem occur please let me know. For further refernces http://goose.ycp.edu/~dhovemey/spring2007/cs201/info/trees.html – Ajay Sep 29 '14 at 14:55
  • This is a valid way to build a general tree. Its not what the OP is asking for. However I think it is good that alternative answers stand for future readers because the OPs design is not what most C++ programmers would recommend. – Galik Sep 29 '14 at 14:56
  • @Galik What C++ programmers would like to recommend for this tree ? – user3919801 Sep 29 '14 at 14:59
  • 1
  • This is exactly the structure I would use if I wanted to implement this structure in an environment where dynamic memory allocation was not permissible. It is in the vein of [Intrusive](http://stackoverflow.com/questions/5004162/what-does-it-mean-for-a-data-structure-to-be-intrusive) data structures. – Speed8ump Sep 29 '14 at 15:45
0

The first answer is: you don't. Use a container class like everyone in the comments indicated.

The second answer is: dynamic allocation:

void addNewChild(s *into, s* new_child)
{
   s **tmp_s = new s*[into->NoOfChild+1];    ///< will throw if allocation fails

   for(int i=0; i<into->NoOfChild; i++) tmps[i] = into->child[i];  ///< use a memcpy instead
   tmps[into->NoOfChild++] = new_child;

   s **del_s = into->child;
   into->child = tmp_s;
   delete[] del_s;
}

And finally: don't do this. Use std::vector<s> or std::vector<s*> depending on how many parents a child can have.

Speed8ump
  • 1,307
  • 10
  • 25
  • And finally use std::vector or std::vector :p In mining we don't know how many child one can have in advance , it's all depends on input data . – user3919801 Sep 29 '14 at 15:45
  • I would suggest the use of `std::vector` because vector replicates the object which are `push_back()`-ed. If `s` is a class for a tree-like structure, copying the object itself would be a pure hell (because an `s` object contains a vector of other `s` objects ...) – Rerito Sep 29 '14 at 15:48
  • In C++ if you are doing something that could be done with the standard containers you need to justify why you can't use them for your application. They are "the way", and those who wander aimlessly from the way are feared and pitied. :) – Speed8ump Sep 29 '14 at 15:50
  • `vector`is a [bad idea](http://stackoverflow.com/questions/6517231/are-c-recursive-type-definitions-possible-in-particular-can-i-put-a-vectort) – Sérgio Castelani Sep 29 '14 at 15:53
  • Huh...learned something new today. Apparently `struct s { ...; vector child; }` is explicitly illegal according to the C++03 standard. It's also a bad idea because adding a new child can cause a flood of reallocations. The new move semantics (X++11 I think) could limit that effect, but it doesn't really matter as it appears to still be UB even in the C++14 standard. – Speed8ump Sep 29 '14 at 16:15
  • @user3919801 "In mining we don't know how many child one can have in advance , it's all depends on input data." Which is explicitly the use case vector exists to handle. – Speed8ump Oct 02 '14 at 16:52
0

A plain c version:

struct node
{
    int key;
    int noOfChild;
    struct node** childrenArray;
};

struct node* newNode(int key, int noOfChild)
{
    int i;
    struct node* node = (struct node*) malloc(sizeof(struct node));
    node->key = key;
    node->noOfChild = noOfChild;
    node->childrenArray = (struct node**) malloc(noOfChild * sizeof(struct node*));
    for(i=0;i<noOfChild;i++)
    {
        node->childrenArray[i] = NULL;
    }
    return(node);
}
arunmoezhi
  • 3,082
  • 6
  • 35
  • 54
0

Since you tagged c++:

#include <vector>
#include <memory>
#include <algorithm>
#include <iostream>

template <class ValueType>
class VariadicTree
{
public:
    VariadicTree(const ValueType& value) : m_value(value), m_size(0)
    {
    }

    VariadicTree<ValueType>& addNode(const ValueType& value)
    {
        m_children.emplace_back(new VariadicTree<ValueType>(value));
        ++m_size;
        return *m_children.back();
    }

    bool leaf()
    {
        return std::all_of(m_children.begin(), m_children.end(),
                           [&](const std::unique_ptr<VariadicTree<ValueType>>& ptr)
                              {return ptr == nullptr;});
    }

    size_t size()
    {
        return m_size;
    }

    const ValueType& value()
    {
        return m_value;
    }

private:
    size_t m_size;
    const ValueType& m_value;
    std::vector<std::unique_ptr<VariadicTree<ValueType>>> m_children;
};

int main()
{
    VariadicTree<int> root(5);
    auto& c1 = root.addNode(4);
    auto& c2 = root.addNode(6);
    auto& c3 = root.addNode(2);

    auto& c11 = c1.addNode(2);

    std::cout << root.leaf() << "\n";
    std::cout << c11.leaf() << "\n";
    std::cout << root.size() << "\n";
    std::cout << c1.size() << "\n";
    std::cout << c11.size() << "\n";

    return 0;
}

Ownership can probably be handled more elegantly but this should do for demonstration purposes.

Veritas
  • 2,150
  • 3
  • 16
  • 40
0

I solved using

struct s{
   int x;
   vector<s*> child ;
}

This helps more , since all pointers/references is managed by STL .

user3919801
  • 519
  • 1
  • 4
  • 14