【问题标题】:Print heap array in tree format以树格式打印堆数组
【发布时间】:2014-01-05 19:41:58
【问题描述】:

所以我一直在尝试实现一种算法来以树格式输出堆数组。为了 例如,如果我有一个像 A[10,6,8,2,4,3,6,0,1,3,2,2,1,0,2] 这样的数组,我希望输出为:

10-----6-----2-----0
    |     |     |--1
    |     |--4-----3
    |           |--2   
    |--8-----3-----2
          |     |--1
          |--6-----0
                |--2

更新:解决了我的问题,我为感兴趣的人提供了代码的答案。

【问题讨论】:

  • 我会使用 char 矩阵来保存输出,因此您可以随机写入输出缓冲区。然后你可以有一个像int render(rootNode, x, y) 这样的函数,它在(x,y) 处绘制一个子树并返回输出的“高度”。您可以递归地使用它来构建树。
  • 嗯,这实际上可以解决问题。考虑到可以从数组大小知道行/列和父位置,对矩阵进行操作肯定会使工作更容易。不过,这可能太耗费内存。
  • so just the basic hint on how I should do this 那么你需要指导,那就试试聊天室或论坛吧!

标签: c++


【解决方案1】:

一种可能的解决方案是将占位符插入到数组中,从而形成一个 MxN 矩阵。然后你可以简单地循环它,在每行之后插入一个换行符并缩进具有占位符的单元格。

【讨论】:

  • 这是一个有趣的方法。我会尽量绕开它。
【解决方案2】:

这个 C++11 程序以稍微不同的格式输出堆:

//              10              
//      ||--------------||      
//       6               8      
//  ||------||      ||------||  
//   2       4       3       6  
//||--||  ||--||  ||--||  ||--||
// 0   1   3   2   2   1   0   2

#include<iostream>
#include<vector>
#include<sstream>
#include<string>
#include<cmath>
#include<iomanip>

// http://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c
// will be used to compute height of the heap
size_t IntegerLogarithm2(size_t arg) {
  size_t logarithm = 0;
  while (arg >>= 1) ++logarithm;
  return logarithm;
}   

// will be used to compute number of elements at the level i
size_t IntegerPower2(size_t arg) {
  if(arg)
    return (size_t)2 << (arg-1);
  else
    return 1;
}   

// returns total line length for the level
size_t LineLength(size_t level, size_t item_width, size_t spaces_between) {
  return IntegerPower2(level) * (item_width + spaces_between) - spaces_between;
}   

int main()
{
  // The input heap array
  std::vector<int> A = {10, 6, 8, 2, 4, 3, 6, 0, 1, 3, 2, 2, 1, 0, 2};
  // The heap array split by levels
  std::vector<std::vector<int> > levels;

  // Height of the heap
  size_t levels_number = IntegerLogarithm2(A.size() + 1);
  levels.resize(levels_number);

  // Now fill the levels
  for (size_t i = 0; i < levels.size(); ++i) {
    size_t elements_number = IntegerPower2(i);
    levels[i].resize(elements_number);
    for (size_t j = elements_number - 1, p = 0; p < elements_number; ++j, ++p)
      levels[i][p] = A[j];
  }   

  if (levels_number < 1) return 0;

  int magnitude = (abs(A[0]) <= 1 ? 1 : abs(A[0]));
  size_t tab_width = (size_t)floor(log(double(magnitude)) / log(10.0)) + 1;
  // size_t longest_line = LineLength(levels_number - 1, tab_width, tab_width);
  std::vector<std::string> text;
  text.reserve(levels_number * 2 - 1); 

  // Do the aligned output to the strings array
  for (size_t i = 0; i < levels_number; ++i) {
    size_t outer_space_width = IntegerPower2(levels_number - 1 - i) - 1;
    size_t inner_space_width = outer_space_width * 2 + 1;
    std::string outer_space(outer_space_width * tab_width, ' ');
    std::string inner_space(inner_space_width * tab_width, ' ');

    std::ostringstream line;
    line << outer_space;

    if (i > 0) {
      std::ostringstream branchline;
      std::string joint(tab_width, '|');
      std::string branch(inner_space_width * tab_width, '-');

      branchline << outer_space;

      if (levels[i].size() > 0) {
        branchline << joint;
      }

      bool isline = true;
      for (size_t j = 1; j < levels[i].size(); ++j, isline = !isline) {
        if(isline)
          branchline << branch << joint;
        else
          branchline << inner_space << std::setfill(' ') <<
              std::setw(tab_width) << joint;
      }

      branchline << outer_space;
      text.push_back(branchline.str());
    }

    if (levels[i].size() > 0) {
      line << std::setfill(' ') << std::setw(tab_width) << levels[i][0];
    }

    for (size_t j = 1; j < levels[i].size(); ++j) {
      line << inner_space << std::setfill(' ') <<
          std::setw(tab_width) << levels[i][j];
    }

    line << outer_space;
    text.push_back(line.str());
  }

  // Output the text
  for (auto& i : text)
    std::cout << i << std::endl;

  return 0;
}

是的,比最初看起来更难。有效地执行了 Sebastian Dressler 的建议。

【讨论】:

  • 如您所见,实现具有良好格式的算法实际上比看起来更难。
  • 只有当最后一行子元素足够大以填满该行时才有效。不过最好的答案。你真的为此付出了一些努力,我很感激。
  • 说实话,我的目标不是稳健。在处理堆时,用 +/- 无穷大填充最后一行是一种常见的技术。最后一行可以填充为满,然后在打印阶段可以忽略无限值。
【解决方案3】:

这是最终的实现。格式随数字长度缩放。

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>

std::string do_padding (unsigned index, unsigned mlength){
  std::string padding;
  if (int((index-1)/2) != 0){
    return (int((index-1)/2) % 2 == 0) ?
    (do_padding(int((index-1)/2),mlength) + std::string(mlength+4,' ') + " ")  :
    (do_padding(int((index-1)/2),mlength) + std::string(mlength+3,' ') + " |") ;
  }
  return padding;
}


void printer (std::vector<int> const & tree, unsigned index, unsigned mlength){
  auto last = tree.size() - 1 ;
  auto  left = 2 * index + 1 ;
  auto  right = 2 * index + 2 ;
  std::cout << " " << tree[index] << " ";
  if (left <= last){
    auto llength = std::to_string(tree[left]).size();
    std::cout << "---" << std::string(mlength - llength,'-');
    printer(tree,left,mlength);
    if (right <= last) {
      auto rlength = std::to_string(tree[right]).size();
      std::cout << "\n" << do_padding(right,mlength) << std::string(mlength+ 3,' ') << " | ";
      std::cout << "\n" << do_padding(right,mlength) << std::string(mlength+ 3,' ') << " └" <<
      std::string(mlength - rlength,'-');
      printer(tree,right,mlength);
    }
  }
}


void print_tree (std::vector<int> & tree){
  unsigned mlength = 0;
  for (int & element : tree){
    auto clength = std::to_string(element).size();
    if (clength > mlength) {
      mlength = std::to_string(element).size();
    }
  }
  std::cout <<  std::string(mlength- std::to_string(tree[0]).size(),' ');
  printer(tree,0,mlength);
}

int main() {
  std::vector<int> test;
  for(auto i =0; i<50; ++i){
    test.push_back(rand() % 1000 + 1);
  }
  std::make_heap(test.begin(),test.end());
  std::cout << "\n";
  print_tree(test);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 2013-10-25
    • 1970-01-01
    • 2013-01-31
    • 2012-10-01
    相关资源
    最近更新 更多