【问题标题】:FIFO list (moving elements) [C++]FIFO 列表(移动元素)[C++]
【发布时间】:2010-02-03 17:50:19
【问题描述】:

大家晚上好!

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

我的想法是我有一个包含 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]<<" ";
}

任何帮助将不胜感激。提前谢谢你。

【问题讨论】:

  • “将元素向左移动 k 个元素”是什么意思?您的意思是“将第 k 个元素移到队列的前面?”
  • 伙计,这确实是一段丑陋的源代码,即使在 codaddict 清理了一点之后。 -1 不是来自我,但如果是因为代码,我不会感到惊讶。我对未来的建议,因为你似乎正在学习:为读者编写和格式化你的代码,而不是为了你打字时的方便。这将提高您的代码质量,并且更有可能有人会回答您的问题。现在请原谅,我想我要上楼去找开源家伙,告诉他 C++ 有多丑,如果他还在这栋楼里的话。
  • 对不起...原谅我肮脏的代码。

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


【解决方案1】:

我不确定我是否完全理解了您的问题。但看起来您实际上想要旋转数组的内容。

将数组内容向左旋转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]
  • 第三步:反转整个数组:[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);
}

【讨论】:

    【解决方案2】:

    由于您已将其标记为 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);
        }
    }      
    

    如果你想朝另一个方向旋转,这几乎是一个交换前后角色的问题。

    【讨论】:

    • 感谢您的回复。我真的是一个初学者(很难不注意到),而且我从来没有听说过 std::deque。但我会调查一下。谢谢你。 :)
    【解决方案3】:

    看起来你想要左旋转?这应该不是很困难。只需将第一个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 的回答。

    【讨论】:

    • 谢谢你,丹本!这种方法是我试图做的。至于 STL 数据结构,我还没有学过。 :) 再次感谢您。
    【解决方案4】:

    如果您的意思是“将第 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;
    }
    

    【讨论】:

    • 我不认为他是那个意思。在他的例子中,k 是 3。
    【解决方案5】:
    #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
    

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-03
        • 2020-10-07
        • 2016-11-07
        相关资源
        最近更新 更多