【问题标题】:inorder traversal of a b-tree (c++)b树的中序遍历(c ++)
【发布时间】:2011-05-18 21:54:20
【问题描述】:

我正在为我目前正在学习的一门课程制作 B 树(或者它是 B 树?)。我大部分都正确实施(我认为)。但是,我无法确定中序遍历。这是我的主要功能:

Tree<char, 5>* tree = new Tree<char, 5>();

char entries[] = {'a', 'g', 'f', 'b', 'k', 'd', 'h', 'm', 'j', 'e', 's', 
                  'i', 'r', 'x', 'c', 'l', 'n', 't', 'u', 'p' };

for (int i = 0; i < 20; i++) {
    tree->insert(entries[i]);
    cout << i << ":\t";
    tree->inorder();
    cout << endl;
}

所以我创建了一个包含字符的 5 路 btree。我将每个字符插入到树中,然后显示每次迭代的中序遍历以进行调试。这是我得到的输出:

0:  a
1:  ag
2:  afg
3:  abfg
4:  abffgk
5:  abdgfgk
6:  abdgfghk
7:  abdgfghkm
8:  abdgfghjjkm
9:  abdefghjjkm
10: abdefghjjkms
11: abdefghimjkms
12: abdefghimjkmrs
13: abdefghimjkmrrsx
14: abccdefghimjkmrrsx
15: abccdefghimjklmsrsx
16: abccdefghimjklmnrsx
17: abccdefghimjklmnrstx
18: abccdefghimjklmnrstux
19: abccdefghimjjklmmnprstux

在几乎所有这些字符中,一些字符是重复的,但在插入之间不一致,所以(对我而言)似乎没有重复数据进入。我似乎无法理解它,但这是我的顺序方法:

template <class Record, int order>
void Tree<Record, order>::inorder()
{
    inorder(root);
}

template <class Record, int order>
void Tree<Record, order>::inorder(Node<Record, order> *current)
{
    for (int i = 0; i < current->count+1; i++) {
        if (current->branch[i])
            inorder(current->branch[i]);
        if (i < order-1 && current->data[i])
            cout << current->data[i];
    }
}

在我的节点实现中,count 是树中“数据”(每个字符)的数量。 count+1 将是非叶节点从节点上脱落的分支数。 branch 是下一组节点的数组,data 是字符数组。

这是我的 Node 实现:

template <class Record, int order>
struct Node
{
    int count;
    Record data[order - 1];
    Node<Record, order>* branch[order];
    Node() : count(0) {}
};

这是用于插入的所有内容:

template <class Record, int order>
ErrorCode Tree<Record, order>::insert(const Record& new_entry)
{
    Record median;
    Node<Record, order> *right_branch, *new_root;
    ErrorCode result = push_down(root, new_entry, median, right_branch);

    if (result == overflow) {
        new_root = new Node<Record, order>();
        new_root->count = 1;
        new_root->data[0] = median;
        new_root->branch[0] = root;
        new_root->branch[1] = right_branch;
        root = new_root;
        result = success;
    }

    return result;
}

template <class Record, int order>
ErrorCode Tree<Record, order>::push_down(
                Node<Record, order> *current,
                const Record &new_entry,
                Record &median,
                Node<Record, order> *&right_branch)
{
    ErrorCode result;
    int position;

    if (current == NULL) {
        median = new_entry;
        right_branch = NULL;
        result = overflow;
    }
    else {
        if (search_node(current, new_entry, position) == success)
            result = duplicate_error;
        else {
            Record extra_entry;
            Node<Record, order> *extra_branch;
            result = push_down(current->branch[position], new_entry, 
                                extra_entry, extra_branch);
            if (result == overflow) {
                if (current->count < order - 1) {
                    result = success;
                    push_in(current, extra_entry, extra_branch, position);
                }
                else
                    split_node(current, extra_entry, extra_branch, position, 
                                right_branch, median);
            }
        }
    }

    return result;
}

template <class Record, int order>
void Tree<Record, order>::push_in(Node<Record, order> *current, 
                const Record &entry,
                Node<Record, order> *right_branch,
                int position)
{
    for (int i = current->count; i > position; i--) {
        current->data[i] = current->data[i-1];
        current->branch[i+1] = current->branch[i];
    }

    current->data[position] = entry;
    current->branch[position+1] = right_branch;
    current->count++;
}

【问题讨论】:

  • 请向我们展示 Node 数据结构 - 我不明白为什么 branch 显然是 count + 1 元素长。显示结构比试图描述它更清晰。另外,'order'模板参数控制什么?
  • 订单模板参数控制我们正在使用的树的顺序。在这种情况下,一个 5 路树 (Tree* tree = new Tree)。现在添加节点......
  • @greggory.hz 你能澄清一下“计数”是什么意思吗?是增加的分支数量吗?或“数据”元素的数量?或者是其他东西?我认为 count 的使用方式可能存在错误,但如果不知道“插入”如何使用它就很难判断。
  • @greggory.hz 你能提供插入的代码吗(如果它不是太大的话)我认为第二个错误与'count'和你的for循环有关
  • 有点多,但我已经添加了插入代码

标签: c++ traversal b-tree


【解决方案1】:

嘿,我想我们是同一个班的。我刚完成我的,我在你的中序遍历中看到了问题,新的也是。在那一秒如果:

if (i < order-1 && current->data[i])
cout << current->data[i];

它是为了订单而不是节点中当前有多少数据,所以它会吐出一点额外的数据。我将其更改为i&lt;current-&gt;data,现在它工作得很好。 ^^b 刚刚结束。如果它不适合你,对不起。 ^^;

【讨论】:

  • 所以对于 i data,我得到一个编译器错误......因为 i 是一个 int 而 current->data 是一个指针(数组)。但是,您为我指明了正确的方向。我将其更改为 i count 并且效果很好!感谢您的帮助:)(也许编辑您的答案以反映我所做的更改)
【解决方案2】:

您的问题是您的 for 循环从 0 变为 count(包括)但您的 Node::data 数组未在 data[count] 处定义,它仅定义为 data[count-1] 所以最后一个你的那个循环的迭代总是得到垃圾,有时可能是非零并且不显示,但有时可能是随机字符。

当“i == order”像这样时,您需要对代码进行特殊处理

if (current->branch[i])
    inorder(current->branch[i]);
if (i < order-1 && current->data[i])
    cout << current->data[i];

【讨论】:

  • 如果我从 for 循环条件中取出 +1,它并不总是打印所有字符。例如,在第 4 次迭代中,我得到了“abf”,在第 19 次迭代中,我得到了“abcdefj”。大多数(不是全部)其他迭代都同样短,但这两个最容易一目了然。
  • @greggory.hz 您的 inorder 代码假设它可以使用 'i' 访问分支数组和数据数组,因此当 count = 4 时,您将访问数据中的无效位置但您将拥有一个有效的分支位置。
  • 我明白你在说什么了!谢谢你的sn-p。这摆脱了错误的 0。但是我仍然有重复字符的问题。 (同时更新问题)
猜你喜欢
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 2012-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-16
相关资源
最近更新 更多