如何映射数组元素以选择二叉树节点?

时间:2017-12-06 16:19:16

标签: c++ arrays sorting

我有一个长度为n的数组。我想对数组元素进行排序,以便我的新数组元素像

arr[0] = arr[n/2]
arr[1] = arr[n/4]
arr[2] = arr[3n/4]
arr[3] = arr[n/8]
arr[4] = arr[3n/8]
arr[5] = arr[5n/8] 

依旧......

我尝试过使用矢量。

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

bool myfunc (int l, int r)
{
        int m = (l+r)/2;
        return m;
}

int main()
{
    std::vector<int> myvector = {3,1,20,9,7,5,6,22,17,14,4};
    std::sort (myvector.begin(), myvector.end(), myfunc);

    for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    return 0;

}

因此,对于长度为11的数组,我希望

myvector[0] = arr[5]
myvector[1] = arr[2]
myvector[2] = arr[8]
myvector[3] = arr[0]
myvector[4] = arr[3]
myvector[5] = arr[6]
myvector[6] = arr[9]
myvector[7] = arr[1]
myvector[8] = arr[4]
myvector[9] = arr[7]
myvector[10] = arr[10]

我的问题是,myfunc的函数定义应该是什么,这样我得到预期的输出

bool myfunc (int l, int r)
    {
            int m = (l+r)/2;
            //Cant figure out this logic
    }

我尝试过调试器,但这绝对没有帮助定义函数!任何线索都会受到赞赏。

1 个答案:

答案 0 :(得分:1)

看起来你想要一个以数组形式存储的二叉搜索树(BST),使用通常用于存储堆的相同内部表示。

预期输出是一个数组,使得基于一个索引形成一个树,其中对于任何一个基于索引的x,x的左节点在索引2 * x,而x的右节点在索引2 * X + 1。此外,没有间隙,这意味着使用了数组的每个成员,最多为N.(它是一个完整的二叉树)由于c ++使用从零开始的索引,因此您需要小心这个基于一的索引。

这种表示树的方式非常适合存储堆数据结构,但对于要插入内容的二叉搜索树来说非常糟糕,从而破坏了完整性,并迫使您进入非常昂贵的重新平衡。

您要求从排序数组索引到此数组格式的映射。我们可以使用递归函数构建它。这个递归函数将完成与构建二叉树所需的工作量完全相同的工作量,事实上,它几乎与编写该函数的方式完全相同,因此这不是最佳方法。我们正在做整个问题所需的工作,只是想出一个中间步骤。

这里的特别说明是我们不想要中位数。我们希望确保左子树形成一个完美的二叉树,以便它适合阵列而没有间隙。因此,它必须具有2,减1节点的功率。正确的子树可能只是完整的。

int log2(int n) {
    if (n > 1)
        return 1 + log2(n / 2);
    return 0;
}

// current_position is the index in bst_indexes
void build_binary_tree_index_mapping(std::vector<int> &bst_indexes, int lower, int upper, int current_position=0) {
    if (current_position >= bst_indexes.size())
        return;

    int power = log2(upper - lower);
    int number = 1 << (power); // left subtree must be perfect
    int root = lower + number - 1;

    // fill current_position
    // std::cout << current_position << " = " << root << std::endl;
    bst_indexes[current_position] = root;

    if (lower < root) {
        // fill left subtree
        int left_node_position = (current_position + 1) * 2 - 1;
        build_binary_tree_index_mapping(bst_indexes, lower, root - 1, left_node_position);
    }

    if (root < upper) {
        // fill right subtree
        int right_node_position = (current_position + 1) * 2 + 1 - 1;
        build_binary_tree_index_mapping(bst_indexes, root + 1, upper, right_node_position);
    }
}

这给了我{7,3,9,1,5,8,10,0,2,4,6}作为索引映射。它与你的不同,因为你在树的左下方留下了空格,我确保数组完全填满,所以我不得不将底行移开,然后BST属性需要重新排序所有内容。

作为旁注,为了使用这种映射,首先必须对数据进行排序,这与整个问题的复杂性大致相同。

此外,使用std :: binary_search http://en.cppreference.com/w/cpp/algorithm/binary_search,已排序的向量已经为您提供了进行二进制搜索的更好方法。