【问题标题】:Queue move item back to the end队列将项目移回末尾
【发布时间】:2019-09-30 11:07:51
【问题描述】:

我有一个System.Collection.Generic.Queue<int> 和下面的示例代码

Queue<int> iq = new Queue<int>();
iq.Enqueue(1); // 1
iq.Enqueue(2); // 1 2
iq.Enqueue(3); // 1 2 3

//move 1 to the end of the line here

int i = iq.Dequeue(); // 2 3

我想移动值(访问按值1回到行尾,这样结果是21将是最后一个可出列的值。

有什么想法吗?有没有类似iq.MoveToLast(1) 的东西?

【问题讨论】:

  • 出队,入队,完成。还是必须是原子的?
  • @Fildor 我需要按值访问。一项要求也可能是将2 移回
  • 好的。那是一个不同的故事。然后,您需要一个按索引访问的集合。
  • 看来你想要List&lt;int&gt; 而不是Queue&lt;int&gt;: int index = id.IndexOf(2); if (index &gt;= 0) {id.RemoveAt(index); id.Add(2);}
  • 如果你想保持 Enqueue 和 Dequeue 为“API”,你可以包装一个 List 并相应地实现方法。然后你可以添加一个“MoveToEnd”方法。

标签: c# queue


【解决方案1】:

如果你想Remove/Add按其项,你可以使用List&lt;T&gt;而不是Queue&lt;T&gt;

List<int> id = ...

int itemToMove = 2;

int index = id.IndexOf(itemToMove);

// If we have item found we should put it at the end
if (index >= 0) {
  id.Add(id[index]);
  id.RemoveAt(index);
}

如果你必须使用 Queue&lt;T&gt;,你可以创建一个temporal List&lt;T&gt;

  Queue<int> iq = ...

  int itemToMove = 2;

  // Create temporal list
  var list = iq.ToList();

  // process items in it
  int index = list.IndexOf(itemToMove);

  if (index >= 0) {
    list.Add(list[index]);
    list.RemoveAt(index);
  }

  // enqueue items back into queue in the desired order
  iq.Clear();

  foreach (var item in list)
    iq.Enqueue(item);

最后,你可以实现一个扩展方法

  public static partial class QueueExtensions {
    public static void MoveToLast<T>(this Queue<int> queue, T itemToMove) {
      if (null == queue)
        throw new ArgumentNullException(nameof(queue)); 

      var list = queue.ToList();

      int index = list.IndexOf(itemToMove);

      if (index < 0)
        return; // Nothing to do

      list.Add(list[index]);
      list.RemoveAt(index);

      queue.Clear();

      foreach (var item in list)
        queue.Enqueue(item);
    }
  }

那你就可以放

 iq.MoveToLast(1);

【讨论】:

    【解决方案2】:

    试试吧:

    queue.Enqueue(queue.Dequeue());
    

    您不能使用Dequeue 以外的方法从QueueRemove 元素。

    【讨论】:

    • 我需要按价值访问。一项要求也可能是将 2 移回 - 所以 Enqueue/Dequeue 不起作用
    【解决方案3】:

    这是一种仅操纵队列的方法:

    public static void MoveElementToBack<T>(Queue<T> queue, T elementToMove)
    {
        T item = default;
        bool found = false;
    
        for (int i = 0, n = queue.Count; i < n; ++i)
        {
            var current = queue.Dequeue();
    
            if (!found && current.Equals(elementToMove))
            {
                item  = current;
                found = true;
            }
            else
            {
                queue.Enqueue(current);
            }
        }
    
        if (found)
            queue.Enqueue(item);
    }
    

    这始终是一个O(N) 操作,但它只使一个通过队列。

    【讨论】:

      猜你喜欢
      • 2014-05-19
      • 2020-04-13
      • 1970-01-01
      • 2020-04-07
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      相关资源
      最近更新 更多