0

I am coding a segment tree algorithm in which the nodes of the tree are arrays (it's supposed to represent the frequency of indices, it doesn't actually matter for my problem). Since I need to return an array when querying the tree, I figured I had to use a static variable. But that raises a problem: the total array is overwritten when the query goes down the tree because of recursion.

int* query(int tree[][9], int i, int j, int pos, int qi, int qj){
  if(qi <= i && qj >= j){
    return tree[pos];
  }else if(qi > j || qj < i){
    static int empty[9];
    for (size_t k = 0; k < 9; k++) empty[k] = 0;
    return empty;
  }

  int mid = (i+j)/2;

  int *left  = query(tree,     i, mid, 2*pos+1, qi, qj);
  int *right = query(tree, mid+1,   j, 2*pos+2, qi, qj);

  static int total[9];

  for (size_t k = 0; k < 9; k++) {
    total[k] = left[k] + right[k];
  }

  return total;
}

Geno C
  • 1,401
  • 3
  • 11
  • 26
xedc
  • 91
  • 2
  • 9
  • 3
    An approach I recommend, rather than starting with "I figured I had to use a static variable," start with what you actually need to do, and work from there. That being said, can you describe what the algorithm is supposed to do in enough detail that we can work through it? As is, we know that the current code doesn't work, but we don't really know what it's supposed to do, so we can't help you make it right. – Cort Ammon Jul 29 '20 at 02:17
  • This function is used to query a segment tree. The leaves of that tree are arrays and the nodes that connect them are their sum. It will start at the top of the tree and check if the wanted indices i and j to query are in total overlap (in which case it returns the value at that node) or no overlap (returns an array of zeroes). If there is a partial overlap of the indices, then the search will continue to the left and right nodes of the node being currently checked, then the values of the left and right arrays are summed into the total array and then returned. – xedc Jul 29 '20 at 02:30
  • It would work perfectly if the nodes were just integer values, but since they are arrays, I [think I] have to use static variables or pointers, which results on the problem of the array being overwritten. – xedc Jul 29 '20 at 02:32
  • 1
    This is C++ and we are in 2020. Use [std::array](https://en.cppreference.com/w/cpp/container/array) or [std::vector](https://en.cppreference.com/w/cpp/container/vector) – Thomas Sablik Jul 29 '20 at 03:09
  • 2
    'I think I have to use static': Well, *stop* thinking that. You can't. `static` and recursion do not mix. Overcome your mental block. – user207421 Jul 29 '20 at 03:53

2 Answers2

3

This is C++ and we are in 2020. Use std::array or std::vector

auto query(std::array<std::array<int, 9>, 9> const &tree, int i, int j, int pos, int qi, int qj){
  if(qi <= i && qj >= j){
    return tree[pos];
  }else if(qi > j || qj < i){
    return std::array<int, 9>{};
  }

  int const mid = (i+j)/2;

  auto const left  = query(tree,     i, mid, 2*pos+1, qi, qj);
  auto const right = query(tree, mid+1,   j, 2*pos+2, qi, qj);

  std::array<int, 9> total;

  for (std::size_t k = 0; k < 9; k++) {
    total[k] = left[k] + right[k];
  }

  return total;
}

std::arrays can be used like primitives. They can be copied, returned from functions and passed to functions by value.

Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
  • Thanks! I think it solves my problem. But now I have another problem. I used `std::vector` but now I can't access the elements of `left` and `right`, otherwise I get a `segmentation fault (core dumped)`. I can't use the `[]` operator. – xedc Jul 29 '20 at 13:14
  • @MarlonCendron Why do you use vector instead of array? It sounds like you did something wrong with the vectors. It's nearly impossible to say more without seeing your code. – Thomas Sablik Jul 29 '20 at 13:18
  • I first tried with arrays, but I also got a segmentation fault (I think this happened because of the size, since I need a 10⁶x9 matrix for the tree), so I searched a bit and changed it to vectors. Where do I send my code? Do I create a new question? – xedc Jul 29 '20 at 13:40
  • I found the problem: when there is no overlap in the indices, I made the function return `vector{}`, and I can't access the indices of this vector. So I filled the vector with zeroes: `vector empty; for (size_t k = 0; k < NOTAS; k++) empty.push_back(0); return empty;` – xedc Jul 29 '20 at 13:48
  • @MarlonCendron Yes, that's a new question. – Thomas Sablik Jul 29 '20 at 14:07
1

As Thomas pointed out you could use std::vector or std::array, but if you really want to use old fashioned arrays, I would recommend to pass your array not as return value but as argument (pointer to it or even better a reference) like this:

void query(int tree[][9], int i, int j, int pos, int qi, int qj, int (&ret)[9]])

than you can fill the array inside the function.

There are also possibilities to return a pointer to an array but that can get a mess regarding the memory management.

RomCoo
  • 1,868
  • 2
  • 23
  • 36