FIFO列表(移动元素)[C ++]

时间:2010-02-03 17:50:20

标签: c++ data-structures list queue fifo

晚上好,人们!

我正在尝试解决一个相当简单的问题,但是......好吧,似乎我做不到。 :)

我的想法是我有一个带有n个元素的FIFO列表(FIFO队列),并给它一个值k(k

但是,我无处可去。

这是我到目前为止所写的:

#include <iostream>
using namespace std;

void move (int a[100], unsigned n, unsigned k) {
        int t[100];
        unsigned i;
        for (i=0; i<=n-1; i++) t[i]=a[i];
        for (i=0; i<=k-1; i++) a[i]=a[i+k-1];
        for (i=k; i<=n-1; i++) a[i]=t[i+1];
}

int main () {
        int a[100];
        unsigned k, n, i;
        cout<<"n; k= "; cin>>n>>k;
        for (i=0; i<=n-1; i++) cin>>a[i];
        move (a, n, k);
        for (i=0; i<=n-1; i++) cout<<a[i]<<" ";
}

非常感谢任何帮助。提前谢谢。

6 个答案:

答案 0 :(得分:2)

我不确定我是否完全理解了你的问题。但看起来你有效地想要旋转数组的内容。

将数组内容向左旋转k次。您可以执行以下操作:

  • 反转前K个元素。
  • 扭转剩余的N-K元素。
  • 反转整个阵列。

示例:

  

N = 5,K = 3,并且阵列= [1 2 3 4 5]

  • 第1步:反转前3个元素: [3 2 1 4 5]
  • 第2步:反转剩下的2 要素:[3 2 1 5 4]
  • 第3步:反转整个阵列:[4 5 1 2 3]

C ++函数也是如此:

void move (int a[100], int n, int k) {
        int t[100];
        int i,j;
        for (i=k-1,j=0; i>=0; i--,j++) t[j]=a[i];
        for (i=n-1; i>=k; i--,j++) t[j]=a[i];
        for (i=n-1,j=0; i>=0; i--,j++) a[j]=t[i];
}

在恒定空间中执行此操作的更好方法是进行原位反转:

void arr_rev(int a[100], int start, int end) {
        int temp;

        for(;start<end;start++,end--) {
                temp = a[start];
                a[start] = a[end];
                a[end] = temp;
        }
}

void move2 (int a[100], int n, int k) {
        arr_rev(a,0,k-1);
        arr_rev(a,k,n-1);
        arr_rev(a,0,n-1);
}

答案 1 :(得分:1)

看起来你想要左旋?这应该不是很困难。只需将第一个k元素出列,将剩余的n-k元素向左移动(可能将它们放在临时数组的开头),然后在第一个k添加按顺序结束。

以这种方式修改代码可能如下所示:

void move (int a[100], unsigned n, unsigned k) {
        int t[100];
        unsigned i;
        for (i=k; i<=n-1; i++) t[i-k]=a[i];
        for (int x=0; x<=k-1; x++) t[i++-k]=a[x];
}

由于这仍然是丑陋的,你可能会重写它以使逻辑更清晰,但我会将其作为练习。

这也假设您不允许使用STL数据结构;如果不是这样,请参阅Jerry Coffin的回答。

答案 2 :(得分:1)

由于您已将其标记为C ++,我将假设您正在使用它。在这种情况下,您几乎肯定会使用std::deque而不是数组来存储数据。另外,队列通常有“前”和“后”,所以“左”并没有多大意义。

假设(仅仅是为了争论)你想要的是从队列的后面取出k个元素并将它们移到前面,你可以做类似的事情:

typedef std::deque<your_type> data;

void push_to_front(data &d, int k) { 
    if (k > d.size())
        return;
    for (int i=0; i<k; i++) {
        data::value_type v = d.pop_back();
        d.erase(d.back());
        d.push_front(v);
    }
}      

如果你想向另一个方向旋转,那就是交换正面和背面角色的问题。

答案 3 :(得分:0)

如果您的意思是“将第k个元素移动到队列的前面”,那么这是一种方法:

void move( int *a, unsigned n, unsigned k )
{ 
    int t; // To store the temporary for the k'th element 

    t = a[ k ];

    // Shift all the elements to the right by one.
    for( unsigned i = k; i > 0; --i )
        a[ i ] = a[ i - 1 ];

    // Put the k'th element at the left of the queue.
    a[ 0 ] = t;
}

答案 4 :(得分:0)

#include <iostream>
#include <list>
template <typename T>
void Rotate(std::list<T>& list, int k){
    for(int i=0; i<k; ++i){
        T tmp(list.back());
        list.pop_back();
        list.push_front(tmp);
    }
}
int main(){
    std::list<int> ints;
    ints.push_back(1); ints.push_back(2);
    ints.push_back(3); ints.push_back(4);
    Rotate(ints,2);
    for(std::list<int>::const_iterator i = ints.begin(); i!=ints.end(); ++i)
        std::cout << *i << std::endl;
    return 0;
}

将输出:

3
4
1
2

答案 5 :(得分:0)

这个问题很老了,但现在似乎最简单的解决方案是依赖 std::rotate。复杂度是线性的,但取决于第一个和最后一个之间的距离。所以如果你需要旋转 1 个元素,复杂度是 O(1),对于 3,它是 O(3)。