【问题标题】:Move a range of elements within array without extra memory?在没有额外内存的情况下移动数组中的一系列元素?
【发布时间】:2017-05-11 19:51:06
【问题描述】:

基本上我有一个这样的数组:[1, 2, 3, 9, 9, 4, 5, 6, 7]

我想将[1, 2, 3] 部分移动到[4, 5, 6, 7] 之前,如下所示:[9, 9, 1, 2, 3, 4, 5, 6, 7],同时保留数组其余部分的顺序。

一个简单的方法是分配一个临时数组以适应[1, 2, 3],同时我将数组的其余部分向左移动,但我想这样做而不消耗任何额外的内存。这可能吗?也许一些交换技术?

编辑:澄清一下,它是一个大的 STL 数组,额外的内存是指没有额外的大堆分配,临时变量很好。

EDIT2:我正在为任何给定数组和其中的任何范围寻找解决方案

【问题讨论】:

  • 先展示你的作品。请给出原型。当你说没有额外的内存时,你会允许一个 for 循环有一个索引变量和一个交换变量,还是你的意思是“没有任意大的临时空间分配”?这是用于 std 容器还是 C 数组?

标签: c++ arrays memory swap


【解决方案1】:

使用std::rotate,像这样:

#include <iostream>
#include <algorithm>

int main () {
    std::vector<int> v = {1, 2, 3, 9, 9, 4, 5, 6, 7};
    for (auto i : v) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    std::rotate(v.begin (), v.begin () + 3, v.begin () + 5);
    for (auto i : v) {
        std::cout << i << " ";  
    }
    std::cout << std::endl;
}

输出:

1 2 3 9 9 4 5 6 7 
9 9 1 2 3 4 5 6 7 

【讨论】:

    【解决方案2】:

    你想交换两个数字,而不使用临时,这是可能的,像这样:

    /**
    * Swap the parameters without a temp variable.
    * Warning! Susceptible to overflow/underflow.
    * @param a The first parameter.
    * @param a The second parameter.
    */
    void swapNoTemp(int& a, int& b)
    {
        a -= b;
        b += a;// b gets the original value of a
        a = (b - a);// a gets the original value of b
    }
    

    但是当我讨论 here 时,应该非常谨慎地使用它(我认为谨慎和记忆增益之间的权衡是不公平的)。


    使用此功能的主要功能示例:

    int main()
    {
        int a[] = {1, 2, 3, 9, 9, 4, 5, 6, 7};
        swapNoTemp(a[0], a[2]);
        swapNoTemp(a[0], a[4]);
        swapNoTemp(a[1], a[3]);
        for(int i = 0; i < 9; ++i)
            std::cout << a[i] << " ";
        std::cout << std::endl;
        return 0;
    }
    

    输出:

    Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp 
    Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
    9 9 1 2 3 4 5 6 7 
    

    对于另一种方法,使用 XOR,请检查我的链接或 answer 中的 cmets。


    另一种通用的方法是使用std::rotate,如answer所示。

    【讨论】:

    • std::copy 覆盖目标没有的元素?还有针对任意数组和范围的通用交换解决方案吗?
    • @KaiserJohaan 好点,更新了!有一个带异或的,但我仍然不建议你使用它,原因仍然是我在帖子中所说的。答案已更新!
    【解决方案3】:

    或者更著名和更快的异或选项:

    void swap(int &a, int &b) {
        b ^= a;
        a ^= b;
        b ^= a;
    }
    

    【讨论】:

    • 对,从我的链接中的comments 复制粘贴,doomista 说:“这是防溢出的。但根据wiki,编译器优化可以在使用额外时产生更快且内存等效的解决方案变量,所以我想这是迄今为止最好的解决方案,当你不在装配级别工作时。”。 +1
    • 更快的 XOR 选项 -- 前几天看到一个演示表明这比现代 C++ 编译器在交换两个整数。
    猜你喜欢
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 2011-09-03
    • 2017-09-04
    • 2016-05-23
    • 1970-01-01
    • 2021-10-04
    相关资源
    最近更新 更多