Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lektsia_12_Spiski_steki_ocheredi.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
410.98 Кб
Скачать
    1. Динамический стек

Динамический стек — это линейный односвязный список. Работа с этим списком осуществляется по соответствующему принципу: новый элемент кладется на вершину стека, то есть вставляется перед первым элементом списка, и при необходимости взять элемент из стека выбирается значение первого элемента, указатель стека смещается на следующий элемент, а "использованный" элемент удаляется.

Стек реализован в виде класса, поля и методы которого представлены в листинге 8.22.

Листинг 8.22. Класс стека, реализованный динамически

class MyStack

{

Node top;

public void Push(object data) // положить в стек

public object Pop() // взять из стека

public bool IsEmpty() // проверка на пустоту

class Node // узел

}

Развернутый вариант кода класса:

Листинг 8.23. Класс стека, реализованный динамически

namespace SpaceStack

{

class MyStack

{

Node top;

public void Push(object data)

//положить в стек

{

top = new Node(top, data);

}

public object Pop() // взять из стека

{

if (top == null) throw new

InvalidOperationException();

object result = top.data;

top = top.next;

return result;

}

public bool isEmpty() // проверка на пустоту

{

return top == null;

}

class Node // узел

{

public Node next;

public object data;

// конструктор

public Node(Node next, object data)

{

this.next = next;

this.data = data;

}

}

}

}

Следует обратить внимание на то, что метод Pop() — извлечения элемента из стека — внутри себя не делает проверки на пустоту стека. Дело в том, что эта метод должна вызываться только в том случае, когда заранее известно, что стек не пуст. В том случае, когда проверкой (метод IsEmpty) установлено, что стек пуст, решение о дальнейших действиях должно приниматься в вызывающем контексте.

В примере объявляется класс MyStack, принадлежащий пространству имен SpaceStack. Полное имя этого класса — SpaceStack.Stack. Этот класс содержит несколько членов: поле top, два метода Push и Pop, а также вложенный класс Node. Класс Node в свою очередь содержит три члена: поля next и data, а также конструктор. Если исходный код примера хранится в файле MyStack.cs, команда

csc /t:library MyStack.cs

компилирует текст в виде библиотеки, если код не имеет метода Main() и создает сборку с именем MyStack.dll.

В программе C# возможность обращения к открытым типам и членам, содержащимся в конкретной сборке, реализуется посредством ссылки на эту сборку во время компиляции программы. Если в программе используется класс SpaceStack.MyStack, содержащийся в сборке MyStack.dll , то можно решить следующую задачу.

Пример 8.1. Для иллюстрации вышесказанного решим следующую задачу: проверить правильность расстановки скобок в арифметическом выражении.

По правилам записи арифметических выражений первой должна закрываться последняя открывающая скобка, и число открывающих и закрывающих скобок должно совпадать. Будем считать, что в выражении используются три вида скобок: круглые, квадратные и фигурные.

Примечание. Не составит труда, изменив тип информационного поля на string, добавить еще несколько видов скобок, например, операторные скобки begin и end.

Ошибки, которые могут встретиться при расстановке скобок:

  • несоответствие открывающей и закрывающей скобок, например: {a×[b+c)};

  • непарные скобки, то есть открывающих скобок больше, чем закрывающих (или наоборот).

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

Метод BracketTest, приведенная в листинге 8.24, реализует этот алгоритм и возвращает значения:

  • –1, если скобки расставлены правильно;

  • 0, если не хватает закрывающих скобок;

  • номер позиции в строке, на которой стоит "неправильная" скобка.

Листинг 8.24. Проверка скобок в арифметическом выражении

static int BracketTest(string a)

{

char[] begBracket = { '(', '[', '{' };

char[] endBracket = { ')', ']', '}' };

MyStack myStack = new MyStack();

int lenA = a.Length;

bool error = false;

int result = -1;

int i = -1;

do

{

if (isBracket(begBracket, a[++i]))

myStack.Push(a[i]);

else

if (isBracket(endBracket, a[i]))

if (!myStack.isEmpty())

switch (myStack.Pop())

{

case '(':

if (a[i]!=')')

{result =i; error = true;}

break;

case '[':

if (a[i]!=']')

{result =i; error = true;}

break;

case '{':

if (a[i]!='}')

{result =i; error = true;}

break;

}

else

{ error = true; result = i; }

}

while (!error && (i != lenA-1));

if (!myStack.isEmpty() || error)

result = i;

return result;

}

Для вызова процедуры достаточно написать одну строчку кода:

Console.WriteLine(BracketTest("{aaa(bbb)cc[ss[]}"));

Для данной строки на экране будет напечатано число 17. Это означает, что в 17-ой позиции строки ошибка – напечатана скобка }, а должна быть сначала скобка ].

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]