【问题标题】:Circular permutation with two iterators具有两个迭代器的循环置换
【发布时间】:2014-12-17 18:07:51
【问题描述】:

我需要对列表进行循环排列,例如我有:(a,b,c,d,e) 我想要 (e,a,b,c,d)。但我没有成功,这是我尝试过的:

#ifndef ALGORITHME_H
#define ALGORITHME_H

template<typename I>  
void permutationCirculaire(I first, I last) {
    typename std::iterator_traits<I>::value_type firstElement = *first;
    typename std::iterator_traits<I>::value_type res;
    I tmp = first;

    for (++first; tmp != last; ++tmp) {
        *first = *tmp;
        std::cout << "tmp : " << *tmp << ", first : " << *first << std::endl;
        ++first;
    }


}

#endif

我明白了: tmp:a,第一:a tmp:a,第一:a tmp:a,第一:a tmp:a,第一:a tmp:a,第一:a

我不知道为什么,我的主要:

#include <iostream>
#include <list>
#include "algorithme.h"

using namespace std;

int main() {    
    list<char> liste;
    liste.push_back('a');
    liste.push_back('b');
    liste.push_back('c');
    liste.push_back('d');
    liste.push_back('e');

    cout << "( ";
    for (list<char>::iterator it = liste.begin(); it != liste.end(); ++it) {
        cout << *it << " ";
    }
    cout << ") " << endl;

    cout << "Permutation : " << endl;
    permutationCirculaire(liste.begin(),liste.end());

    cout << "( ";
    for (list<char>::iterator it = liste.begin(); it != liste.end(); ++it) {
        cout << *it << " ";
    }
    cout << ") " << endl;

    return 0; 
}

如果你知道为什么不犹豫......

【问题讨论】:

  • (e,a,b,c,d,e) 真的是(a,b,c,d,e) 的循环排列吗?无论如何,请参阅std::rotate
  • 是的 :)。我需要实施我的解决方案,但我没有成功 ><.>
  • 我不知道排列可以添加元素。
  • 哦,对不起,我的错:(e,a,b,c,d)更好,我将编辑我的第一篇文章。我感觉我用的是同一个指针……

标签: c++ iterator iterator-traits


【解决方案1】:

正如jaunchopanza 所提到的,rotate 是您应该使用的。

所以替换这个:

cout << ") " << endl;

cout << "Permutation : " << endl;
permutationCirculaire(liste.begin(),liste.end());

cout << "( ";

有了这个:

rotate(liste.begin(), advance(liste.begin(), liste.size() - 1), liste.end());

注意通过更改advance 调用中的数字来调整您旋转的字符数。
size() - 1 旋转

a、b、c、d、e

e、a、b、c、d

如果你使用 2 而不是 size() - 1 你会得到:

c、d、e、a、b

还要考虑:next_permutationprev_permutation,如果您不想做除了旋转以外的事情。

【讨论】:

    【解决方案2】:

    如果您只需将最后一个元素移到列表的前面,您可以使用:

    liste.push_front(liste.back());
    list.pop_back();
    

    如果你真的想使用一个使用迭代器的函数,我会向后遍历列表并交换将最后一个元素放在前面的元素。

    template<typename I>  
    void permutationCirculaire(I first, I last)
    {
        --last;  // move last to the last element
        while(first != last)
        {
            iter_swap(last, last - 1);
            --last;
        }
    }
    

    【讨论】:

      【解决方案3】:

      以前的答案是您应该做的。特别是您的代码,有几个问题;一个是:在你的 for 循环中,你先递增并在 temp != last 处终止,如果你有大小为 1 的列表会发生什么?您的第一个 == 结束并且您执行 *first = *temp 还会将您的 cout 语句移到 *first = *temp 之前的一行,这样您就可以在输出中得到您想要的。

      【讨论】:

        【解决方案4】:

        我终于成功纠正了我的问题,这是我的解决方案,谢谢大家的帮助:

        template<typename I>  
        void permutationCirculaire(I first, I last) {
            typename std::iterator_traits<I>::value_type current = *first;
            typename std::iterator_traits<I>::value_type save = *(--last);
        
            for(; first != last; ++first) {
                current = *first;
                *first = save;
                save = current;
            }
            *first = save;
        }
        

        再次对错误感到抱歉。

        【讨论】:

          猜你喜欢
          • 2013-10-07
          • 2019-05-02
          • 2016-08-27
          • 1970-01-01
          • 1970-01-01
          • 2014-10-23
          • 1970-01-01
          • 1970-01-01
          • 2019-01-22
          相关资源
          最近更新 更多