如何在c++中快速交换列表和向量等容器中的对象

How to quickly swap object in containers such as list and vector in c++

本文关键字:向量 对象 交换 c++ 列表      更新时间:2023-10-16

我想知道C++容器(如list和vector)中的快速交换方法是什么,因为我还没有找到任何内置的交换函数。仅供参考,我想交换对象,而不是整个列表。

例如,假设我们有这样的int序列3 2 4 5,并且它们存储在列表容器(stl)中,我想交换2和4。这是我想出的一个愚蠢的方法:

list<int> numbers;
numbers.push_back(3);
numbers.push_back(2);
numbers.push_back(4);
numbers.push_back(5);
list<int>::iterator item;
item=numbers.begin();
advance(item,2);
int key = *item;
advance(item,-1);
numbers.insert(item,key);
advance(item,1);
numbers.erase(item);

所以,简单地说,我在这里所做的只是"复制、插入和删除",我之所以这么做,是因为我听说列表容器在插入和删除元素方面非常有效,但我确信应该有更好的算法。此外,我还听说有一种与指针相关的常量时间交换方法,所以有人知道它吗

谢谢你帮忙。

您想要std::swap:

list<int>::iterator item1 = numbers.begin();
++item1;
list<int>::iterator item2 = item1;
++item2;
std::swap(*item1, *item2);

使用iter_swap将两个迭代器指向的元素交换到列表中。这样可以交换数据,而不是节点,但这很容易。

#include <list>
#include <iostream>
int main() {
    std::list<int> numbers;
    numbers.push_back(3);
    numbers.push_back(2);
    numbers.push_back(4);
    numbers.push_back(5);
    auto first = std::next(numbers.begin(), 2);
    auto second = std::next(numbers.begin(), 1);
    std::iter_swap(first, second);
    for(int& v : numbers) 
        std::cout << v << ' ';
}

http://coliru.stacked-crooked.com/view?id=a89b3b1ae9400367b6ff194d1b504e58-f674c1a6d04c632b71a62362cfcfc51

如果你想交换节点而不是元素,你可以使用list::splice,尽管它有点欺骗:

int main() {
    std::list<int> numbers;
    numbers.push_back(3);
    numbers.push_back(2);
    numbers.push_back(4);
    numbers.push_back(5);
    std::list<int> temporary;
    auto move_from = std::next(numbers.begin(), 2);
    temporary.splice(temporary.begin(), numbers, move_from, std::next(move_from));
    auto move_to = std::next(numbers.begin(), 1);
    numbers.splice(move_to, temporary);
    for(int& v : numbers) 
        std::cout << v << ' ';
}

您可能正在寻找一种在列表中移动节点的方法,而无需复制实际元素。您可以使用list::splice来完成此操作。当然,对于不是基于节点的向量来说,并没有类似的可能。

类似这样的东西:

list<int>::iterator to = numbers.begin();
++to;
list<int>::iterator which  = to;
++which;
numbers.splice(to, numbers, which);

使用swap怎么样?

using std::swap;
swap(numbers[1], numbers[2]);

其将使用CCD_ 5或ADL来确定适当的交换函数(如果存在为自变量定义的交换函数)。

正如@MooingDuck正确指出的那样,std::list要求您使用迭代器。

std::iter_swap(numbers.begin()+1, numbers.begin()+2);

你也可以使用

using std::swap;
std::list<int>::iterator item(numbers.begin());
std::advance(item, 1);
std::list<int>::iterator other(item);
std::advance(other, 1);
swap(*item, *other);

using std::swap;
swap(*std::next(numbers.begin(), 1), *std::next(numbers.begin(), 2));

std::iter_swap(std::next(numbers.begin(), 1), std::next(numbers.begin(), 2));

使用std::swap(),

int reverse(std::list<int>& list){
    int exchange = 0;
    int move = 0;
    int distance_lo = 0;
    int distance_hi = 0;
    std::list<int>::iterator it_lo = list.begin();
    std::list<int>::iterator it_hi = --list.end();
    while (1) {
        it_lo = list.begin();
        it_hi = --list.end();
        std::advance(it_lo, move);
        std::advance(it_hi, -move);
        distance_lo = std::distance(list.begin(), it_lo);
        distance_hi = std::distance(list.begin(), it_hi);
        if (distance_lo < distance_hi) {
            std::swap(*it_lo, *it_hi);
            exchange++;
        } else {
            break;
        }
        move++;
    }
    return exchange; }

使用std::list::splice(),

int reverse(std::list<int>& list) {
    int exchange = 0;
    int move = 0;
    int distance_lo = 0;
    int distance_hi = 0;
    std::list<int>::iterator it_lo = list.begin();
    std::list<int>::iterator it_hi = --list.end();
    while (1) {
        it_lo = list.begin();
        it_hi = --list.end();
        std::advance(it_lo, move);
        std::advance(it_hi, -move);
        distance_lo = std::distance(list.begin(), it_lo);
        distance_hi = std::distance(list.begin(), it_hi);
        if (distance_lo < distance_hi) {
            std::list<int> tmp;
            tmp.splice(tmp.begin(), list, it_lo);
            tmp.splice(std::next(tmp.begin(),1), list, it_hi);
            it_lo = list.begin();
            it_hi = --list.end();
            std::advance(it_lo, move); //insert before it_lo
            std::advance(it_hi, -move);
            std::advance(it_hi, 1); //insert after it_hi
            list.splice(it_lo, tmp, std::next(tmp.begin(),1));
            list.splice(it_hi, tmp, tmp.begin());
            exchange++;
        } else {
            break;
        }
        move++;
    }
    return exchange; }

希望它能帮助你:)