Подтвердить что ты не робот

Как удалить элемент стека, который не находится в верхней части стека в С#

К сожалению, элемент можно удалить только из стека, нажав "pop". Стек не имеет метода "удалить" или что-то подобное, но у меня есть стек (да, мне нужен стек!), Из которого мне нужно удалить некоторые элементы между ними.

Есть ли уловка для этого?

4b9b3361

Ответ 1

Если вам нужно удалить элементы, которые не находятся сверху, вам нужно что-то другое, кроме стека.

Попробуйте создать собственную реализацию стека из списка. Затем вы можете реализовать свои собственные функции push и pop (добавить и удалить в списке) и собственную специальную функцию PopFromTheMiddle.

Например

public class ItsAlmostAStack<T>
{
    private List<T> items = new List<T>();

    public void Push(T item)
    {
        items.Add(item);
    }
    public T Pop()
    {
        if (items.Count > 0)
        {
            T temp = items[items.Count - 1];
            items.RemoveAt(items.Count - 1);
            return temp;
        }
        else
            return default(T);
    }
    public void Remove(int itemAtPosition)
    {
        items.RemoveAt(itemAtPosition);
    }
}

Ответ 2

Рассмотрим использование другого контейнера. Может быть, LinkedList. Затем вы можете использовать

AddFirst
AddLast
RemoveLast
RemoveFirst

просто как pop/push из стека, и вы можете использовать

Remove

чтобы удалить любой node из середины списка

Ответ 3

Возможно, будет работать метод расширения, хотя, я подозреваю, что совершенно необходима всякая структура данных.

public static T Remove<T>( this Stack<T> stack, T element )
{
     T obj = stack.Pop();
     if (obj.Equals(element))
     {
         return obj;
     }
     else
     {
        T toReturn = stack.Remove( element );
        stack.Push(obj);
        return toReturn;
     }
}

Ответ 4

В истинном стеке это можно сделать только одним способом -

Поместите все элементы до тех пор, пока вы не удалите тот, который вы хотите, затем нажмите их обратно в стек в соответствующем порядке.

Это не очень эффективно.

Если вы действительно хотите удалить из любого места, я бы рекомендовал создать псевдо-стек из списка, LinkedList или какой-либо другой коллекции. Это даст вам контроль, чтобы сделать это легко.

Ответ 5

Вы можете использовать LinkedList

Удаление списков, вероятно, будет менее эффективным. При удалении по ссылке Стыки, основанные на списках, будут иметь O (N) поиск и O (N) изменение размера. Поиск LinkedList - это O (N), а удаление - O (1). Для удаления по индексу LinkedList должен иметь обход O (N) и O (1), тогда как List имеет обход O (1) (потому что это индексирование) и O (N) удаление из-за изменения размера.

Помимо эффективности, реализация LinkedList будет держать вас в стандартной библиотеке, открывая ваш код для большей гибкости и вы пишете меньше.

Это должно быть способно обрабатывать Pop, Push и Remove

    public class FIFOStack<T> : LinkedList<T>
    {
        public T Pop()
        {
            T first = First();
            RemoveFirst();
            return first;
        }

        public void Push(T object)
        {
            AddFirst(object);
        }

        //Remove(T object) implemented in LinkedList
   }

Ответ 6

Тогда это не стежок? Стек LAST in FIRST out. Вам придется написать пользовательский или выбрать что-то еще.

Ответ 7

   Stack temp = new Stack();
   object x, y;
   While ((x = myStack.Pop()) != ObjectImSearchingFor)
       temp.Push(x);
   object found = x;
   While ((y = temp.Pop()) != null)
      myStack.Push(y);

Ответ 8

Конструктор Stack < > принимает IEnumerable < > в качестве параметра. Таким образом, можно было бы выполнить следующее:

myStack = new Stack<item>( myStack.Where(i => i != objectToRemove).Reverse() );

Это не работает по-разному.

Ответ 9

Трюк, который я использую в волосатых ситуациях, добавляет флаг "устаревший" к элементам в стеке. Когда я хочу "удалить" элемент, я просто поднимаю этот флаг (и очищаю все ресурсы, которые предпринимает объект). Затем, когда элементы Pop() меня просто проверяют, поднят ли флаг, и снова появятся в цикле до тех пор, пока не будет найден не-устаревший элемент.

do 
{  
   obj = mQueue.Pop();  
} while (obj.deprecated);  

Вы можете управлять своим собственным количеством элементов, чтобы узнать, сколько "реальных" элементов все еще находится в очереди, и, очевидно, блокировка должна использоваться, если это необходимо для многопоточного решения.

Я обнаружил, что для очередей, которые имеют постоянный поток через них - предметы толкаются и выскакивают - гораздо эффективнее его обманывать, тем быстрее вы можете получить (заплатив O (1) за удаление элемента из середины) и память разумна, если сохраняемый объект мал, это в основном не имеет значения, если предметы текут в разумном темпе.

Ответ 10

hmmmm...... Я согласен с предыдущими двумя ответами, но если вы хотите взломать свой путь, просто нажмите и сохраните все элементы, пока не дойдете до того, который вы хотите, и повторно нажмите их все

Да, это уродливый, плохо исполняемый, вероятно, странный код, которому потребуется длинный комментарий, объясняющий почему, но вы могли бы это сделать....