Очередь переместить элемент обратно в конец - PullRequest
1 голос
/ 30 сентября 2019

У меня есть 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 назад кконец строки, так что результатом будет 2, а 1 будет последним значением, подлежащим извлечению из очереди.

Есть идеи? Есть что-то вроде iq.MoveToLast(1)?

Ответы [ 3 ]

4 голосов
/ 30 сентября 2019

Если вы хотите Remove / Add элемент по его значению , вы можете использовать List<T> вместо Queue<T>:

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<T>, вы можете создать temporal List<T>:

  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);
1 голос
/ 30 сентября 2019

Вот подход, который просто манипулирует очередью:

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), но она делает только один проход через очередь.

1 голос
/ 30 сентября 2019

Просто попробуйте:

queue.Enqueue(queue.Dequeue());

Вы не можете Remove элементы из Queue, используя методы, отличные от Dequeue.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...