Мы все читали об или услышали о классе стека, но многие из нас, вероятно, никогда не находили причину использовать объект LIFO. Мне любопытно услышать о решениях для реального мира, которые использовали этот объект и почему.
http://msdn.microsoft.com/en-us/library/system.collections.stack.aspx
Я недавно видел пример, где программист использовал стек для отслеживания его текущую позицию при пересечении иерархического источника данных. Когда он спустил иерархию, он продвинул свой идентификатор положения на стеке и когда он попятился, он вытолкал объекты от стека. Я думал, что это было очень efficent способ отслеживать его текущую позицию в гигантской иерархии. Я никогда не видел это прежде.
У кого-либо еще есть какие-либо примеры?
Для предоставления конкретного примера освещения того, какие другие люди комментируют: для реализации интерпретатора Z-машины следует использовать три разных стека. Стек вызовов и пара разных видов стеков объекта. (Здесь можно найти конкретные требования . ) Обратите внимание, что, как и все эти примеры, при использовании стека не требуется строго , это очевидный выбор.
Стек вызовов отслеживает рекурсивные вызовы подпрограмма, в то время как стек объекта используется для отслеживания внутренних элементов.
-121--3048022-Я использовал их, чтобы отслеживать действия отмена и повторов.
Я использую интерфейс что-то вроде этого:
interface ICommand
{
void Execute();
void Undo();
string Description { get; }
}
Отмена и повторение - это оба типа . [ICommand>
. Затем я создаю конкретный класс для данного действия. В конструкторе класса я передаю любую информацию, к которой мне нужно будет держать. Execute
выполняет действие первоначально, а также повторно, это; Отменить
Уменьшить это, очевидно. Это работает так:
Я обнаружил, что вы должны позаботиться о том, что вы действительно отменяете, что было сделано. Например, скажем, у вас есть UI с двумя списками, и у каждого в нем есть пять элементов. Ваши действия могут быть нажимают кнопку, чтобы переместить все в левом списке в правильный список (так что теперь имеет десять, а левый список имеет ноль).
Действие отмены , чтобы переместить все обратно; Действие отмены состоит в том, чтобы вернуться только пять, которые вы на самом деле двинулись и оставили других.
Стеки используются для оценки выражений (например, в калькуляторе или компиляторе), сначала выражение преобразуется в RPN, затем для оценки используется простая стековая машина. Это работает следующим образом, когда вы видите, что операнд нажимает на стек. Когда вы видите операнд, нажимающий на стек и вычисляющий его.
example
5 6 + 3 *
steps-
see 5 push 5
see 6 push 6
see + pop 2 times and apply + get 11 push 11
see 3 push 3
see * pop 2 times and apply get 33 push 33
result is on the top of the stack.
Если у вас есть рекурсивный алгоритм, вы обычно можете переписать их с помощью стека. (Поскольку рекурсивные алгоритмы неявно уже используют стек)
можно проверить исходные данные последовательности, которые требуют сбалансированных маркеров. Думать LISP:
(+ (- 3 2) (+ (+ 4 5) 11))
, Когда вы поражаете открытие paren:
stack.Push("(")
Затем, когда вы поражаете закрытие paren:
stack.Pop()
, Если существуют какие-либо маркеры, оставленные в вашем стеке, когда вы сделаны, это не сбалансировано.
можно стать более необычными и проверить надлежащее вложение в исходных данных как HTML. В высоко изобретенном примере:
//see opening body
stack.Push("body")
//see opening div
stack.Push("div")
//see opening p
stack.Push("p")
///see closing div
if(!stack.Pop().Equal("div")){
//not balanced
}
Я использовал стеки для обработки изображений, где "язык обработки" должен быть указан в URL. Форма, основанная на стеке, позволяет представить дерево операций в простой для разбора, легко продуманной форме.
See:
http://www.hackification.com/2008/10/29/stack-based-processing-part-1/
and
http://www.hackification.com/2008/10/29/stack-based-processing-part-2/
В одном реальном использовании класс генератора PostScript имеет состояние «Current_Font», используемый в качестве шрифта для любых операций, которые рисуют текст. Иногда функция должна временно устанавливать шрифт, но тогда он вернется к тому, как он был. Мы могли бы просто использовать временную переменную для сохранения и восстановления шрифта:
def draw_body
old_font = ps.get_font
ps.set_font('Helvetica 10')
draw_top_section
draw_bottom_section
ps.set_font(old_font)
end
, но к третьему раз вы сделали, вы захотите перестать повторять себя. Итак, давайте позвольте объекту PS сохранить и восстановить для нас шрифт:
class PS
def save_font
old_font = get_font
end
def restore_font
set_font(old_font)
end
end
Теперь вызывающий абонент становится:
def draw_body
ps.save_font
ps.set_font('Helvetica 10')
draw_top_section
draw_bottom_section
ps.restore_font
end
, который работает нормально, пока мы не будем использовать один и тот же рисунок внутри одного из подпрограмм, вызываемых Draw_Page:
def draw_top_section
ps.save_font
ps.set_font('Helvetica-bold 14')
# draw the title
ps.restore_font
# draw the paragraph
end
, когда вызовы Draw_top_section «Save_Font», он забивает шрифт, который был сохранен Draw_Page. Пришло время использовать стек:
def PS
def push_font
font_stack.push(get_font)
end
def pop_font
set_font(font_stack.pop)
end
end
и в абонентах:
def draw_top_section
ps.push_font
ps.set_font('Helvetica-bold 14')
# draw the title
ps.pop_font
# draw the body
end
есть возможности возможны дополнительные уточнения, например, имеющие класс PS автоматически сохранить и восстановить шрифт, но не стоит переходить в тех, кто будет видеть значение стек.
Я нахожу стеки вполне полезные в многопотативных репликациях, чтобы отслеживать статусы в моде обратного времени ...
Каждый поток ставит сообщение о состоянии в синхронизированном общий стек, и у вас есть вид «крошко» произошло.
Не совсем .NET Но ... Это мое оппозиция =)
API Всемирного банка довольно крут. Google использует его в результатах поиска. Мои любимые реализации - картограммы на worldmapper .
(источник: worldmapper.org )
AbstractResultSet
, который (как и AbstractQueue) реализует все методы, создав UnsupportedOperationException (Eclipse автоматически генерирует эти методы за долю секунды). AbstractResultSet
. Подкласс может переопределять только методы, которые требуется реализовать. Вот реализация глубокого сравнения, где стек используется для трека пути к сравниваемому текущему объекту.
C # реализация глубокого/рекурсивного сравнения объектов в .net 3,5
Я также использовал его в подобных типах кода, работающих с генерацией операторов xpath для определенных xml-узлов.
Чтобы обеспечить конкретный пример освещения того, какие другие люди комментируют: для реализации интерпретатора Z-машины следует использовать три разных стека. Стек вызовов и пара разных видов стеков объекта. (Специфические требования могут быть найден здесь . ) Обратите внимание, что, как и все эти примеры, при использовании стека не требуется строго , это очевидный выбор.
Стек вызовов отслеживает рекурсивные вызовы подпрограмма, в то время как стек объекта используется для отслеживания внутренних элементов.