我想更改std::list
列表和值的示例
A B C D E F G
3 2 1 2 1 3 2
排序后我希望收到的内容:
A B D C F E G
3 2 2 1 3 1 2
所以,简单A > B
=无所事事,但C < D
=交换它们并转到E
比较。
我不知道如何交换邻居元素。
所以,我想继续前进到1步good
元素
答案 0 :(得分:2)
您可以使用两个迭代器轻松完成此操作:
void biswap(std::list<int> &l)
{
if (l.size() < 2)
return;
auto it2 = l.begin();
auto it1 = it2++;
auto e = l.end();
for (;;)
{
if (*it1 < *it2)
std::swap(*it1, *it2);
it1 = it2++;
if (it2 == e)
return;
it1 = it2++;
if (it2 == e)
return;
}
}
注意:如果你没有使用C ++ 11,因此调用size()
可能会产生很大的开销,你可以用它替换它(当然用auto
代替void biswap(std::list<int> &l)
{
auto it2 = l.begin();
auto e = l.end();
if (it2 == e)
return;
auto it1 = it2++;
if (it2 == e)
return;
for (;;)
// ... the rest as before
}
的所有用法显式类型):
{{1}}
答案 1 :(得分:1)
您可以使用标准算法std::adjacent_find
来查找第一个&lt;第二,然后交换它们。
例如
#include <iostream>
#include <algorithm>
#include <list>
#include <functional>
#include <iterator>
int main()
{
std::list<int> l = { 3, 2, 1, 2, 1, 3, 2 };
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
auto it = std::adjacent_find( l.begin(), l.end(), std::less<int>() );
if ( it != l.end() ) std::swap( *it, *std::next( it ) );
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
}
输出
3 2 1 2 1 3 2
3 2 2 1 1 3 2
或者如果你想在第一次&lt;第二,你可以使用以下代码
#include <iostream>
#include <algorithm>
#include <list>
#include <functional>
#include <iterator>
int main()
{
std::list<int> l = { 3, 2, 1, 2, 1, 3, 2 };
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::list<int>::iterator it = l.begin();
while ( ( it = std::adjacent_find( it, l.end(), std::less<int>() ) ) != l.end() )
{
std::swap( *it, *std::next( it ) );
}
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
}
输出
3 2 1 2 1 3 2
3 2 2 1 3 2 1
答案 2 :(得分:1)
这给出了所需的结果,并且它切换了“好”元素的比较,正如您所要求的那样:
#include <list>
#include <iostream>
using namespace std;
template<typename Type>
void print(const list<Type> & l)
{
for (auto element : l) cout << element << " ";
cout << endl;
}
int main(int argc, const char *argv[])
{
list<int> l = {3,2,1,2,1,3,2};
print(l);
auto it = l.begin();
while(std::next(it) != l.end())
{
if (*it < *std::next(it))
{
std::swap(*it, *std::next(it));
++it;
}
++it;
}
print(l);
return 0;
}
执行结果:
3 2 1 2 1 3 2
3 2 2 1 3 1 2
答案 3 :(得分:1)
如果您没有C ++ 11支持,使用2个迭代器的简单C ++ 03解决方案可能是:
#include <iostream>
#include <algorithm>
#include <list>
void swapNeighbours(std::list<int>& l) {
std::list<int>::iterator it = l.begin();
std::list<int>::iterator prev = it++;
while (prev != l.end() && it != l.end()) {
// swap if needed:
if (*prev < *it)
std::swap(*prev, *it);
// move 2 times forward:
if (++it == l.end())
break;
prev = it++;
}
}
然后(基于你的例子),如果你这样做:
void print(const std::list<int>& l) {
std::list<int>::const_iterator i;
for (i = l.begin(); i != l.end(); ++i) {
std::cout << *i << ' ';
}
std::cout << std::endl;
}
int main() {
std::list<int> l;
l.push_back(3); l.push_back(2); l.push_back(1); l.push_back(2);
l.push_back(1); l.push_back(3); l.push_back(2);
print(l);
swapNeighbours(l);
print(l);
}
然后是:
A B C D E F G
3 2 1 2 1 3 2
将进行以下比较:A < B
? (不)C < D
? (是的,交换)E < F
? (是的,交换)产生输出:
3 2 2 1 3 1 2
答案 4 :(得分:1)
如果您想要做的只是成对遍历和交换元素,如果第一个小于第二个,那么您可以例如像这样使用std::adjacent_find
:
using std::swap;
for (auto it = std::begin(l); it != std::end(l); it = std::adjacent_find(it, std::end(l), std::less<int>{})) {
swap(*it, *std::next(it));
}
这将使数字列表3 2 1 2 1 3 2
排列为:
3 2 2 1 3 2 1
但是, 与您预期的结果3 2 2 1 3 1 2
相同,我没有理解为什么您不想交换最后一对{ {1}}和其他人一样吗?
如果您想要的是用于排序的不稳定模式,那么就没有简单的解决方案。相反,你必须对个别元素使用特殊处理。