1

我有一张 (xi,f(xi)) 的地图,我的 f(xi) 也在严格增加。我需要以这种方式交换密钥和 val

我的功能的输入:

一张地图

//keys :  x0,       x1,     x2,     ...,        xn
// vals :  f(x_0)   f(x1),  f(x2),  ...,        f(xn)

我的函数的输出:一张地图

// key : left_val f(x_0)    f(x1),  ...,        f(xn-1)
// vals : x0,       x1,     x2,     ...,        xn

(这里left_val是一个输入参数,我知道它低于f(x0))。我知道我可能没有使用正确的结构,但我真的需要 log(n) 插入和有序键的唯一性......

您将如何有效地实现这一点(即不复制地图)?

提前致谢。

4

2 回答 2

4

这是一种不寻常的情况,因为您想要更改std::map键,这通常是禁止的,以避免会破坏排序的更改。如果您有信心自己确保此不变量,则可以修改std::map如下:

#include <iostream>
#include <map>

int main()
{
    typedef std::map<double, double> Mdd;

    Mdd m;
    m[1] = 4;
    m[2] = 6.5;
    m[3] = 7.2;
    m[4] = 9.3;
    m[5] = 12;

    double x = 2.3;

    for (Mdd::iterator i = m.begin(); i != m.end(); ++i)
    {
        double old_second = i->second;
        i->second = i->first;
        const_cast<double&>(i->first) = x;
        x = old_second;
    }

    for (Mdd::const_iterator i = m.begin(); i != m.end(); ++i)
        std::cout << i->first << "->" << i->second << '\n';
}

输出:

2.3->1
4->2
6.5->3
7.2->4
9.3->5

所有这些都是const_cast用来坚持对密钥的写访问权。严格来说,我怀疑标准在这种骇客之后不需要实现工作,但实际上我无法想象一个不需要的实现。你需要决定你想用最终值做什么x- 在你的问题中f(xn)......我已经按照你的问题的建议丢弃了它。

就效率而言,这会按顺序依次传递map,如果希望使用这样的容器,这是不可避免的。没有映射的复制或额外的堆分配。转换之后,根据上面关于标准不保证支持的警告,您可以期望有一个“正常”的有效映射,在其中插入和删除元素是安全的。

于 2013-05-07T07:11:12.460 回答
1

将新条目插入新映射时,使用二分搜索算法进行插入。每次插入都是 O(log n),重新创建地图的总时间应该是 O(n log n)。

于 2013-05-07T06:48:44.817 回答