Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
21-34_ПР-ИЕ.doc
Скачиваний:
13
Добавлен:
28.08.2019
Размер:
328.19 Кб
Скачать

Преобразования строк

Зачастую требуется преобразовать число в строку и наоборот. Используем для этого функции sprintf и sscanf. Например, так:

char str[50];

int i=15;

int j;

sprintf(str, "%d", i); // Записать в str строковое представление i

sscanf(str, "%d", &j); // Записать в j число, содержащееся в строке str

sprintf(str, "i=%d and j=%d", i, j);

// содержимое str: "i=15 and j=15"

26. Абстрактные линейные структуры данных: Стеки, очереди. Основные операции со структурами данных. Добавление, извлечение компонентов.

Cтек Стек - такой последовательный список с переменной длиной, включение и исключение элементов из которого выполняются только с одной стороны списка, называемого вершиной стека. Применяются и другие названия стека - магазин, функционирующая по принципу LIFO (Last - In - First- Out - "последним пришел - первым исключается"). Примеры стека: винтовочный патронный магазин, тупиковый железнодорожный разъезд для сортировки вагонов.

Основные операции над стеком - включение нового элемента (английское название push - заталкивать) и исключение элемента из стека (англ. pop - выскакивать).

Полезными могут быть также вспомогательные операции:

  • определение текущего числа элементов в стеке;

  • очистка стека;

  • неразрушающее чтение элемента из вершины стека, которое может быть реализовано, как комбинация основных операций:

x:=pop(stack); push(stack,x);

Для наглядности рассмотрим небольшой пример, демонстрирующий принцип включения элементов в стек и исключения элементов из стека. На рис. 4 (а,б,с) изображены состояния стека:

  • а). пустого;

  • б-г). после последовательного включения в него элементов с именами 'A', 'B', 'C';

  • д, е). после последовательного удаления из стека элементов 'C' и 'B';

  • ж). после включения в стек элемента 'D'.

Рис. 4: Включение и исключение элементов из стека

[Статическая реализация стека на основе массива]

При представлении стека в статической памяти для стека выделяется память, как для вектора. В дескрипторе этого вектора кроме обычных для вектора параметров должен находиться также указатель стека - адрес вершины стека. Указатель стека может указывать либо на первый свободный элемент стека, либо на последний записанный в стек элемент. (Все равно, какой из этих двух вариантов выбрать, важно в последствии строго придерживаться его при обработке стека.) В дальнейшем мы будем всегда считать, что указатель стека адресует первый свободный элемент и стек растет в сторону увеличения адресов.

При занесении элемента в стек элемент записывается на место, определяемое указателем стека, затем указатель модифицируется таким образом, чтобы он указывал на следующий свободный элемент (если указатель указывает на последний записанный элемент, то сначала модифицируется указатель, а затем производится запись элемента). Модификация указателя состоит в прибавлении к нему или в вычитании из него единицы (помните, что наш стек растет в сторону увеличения адресов.

Операция исключения элемента состоит в модификации указателя стека (в направлении, обратном модификации при включении) и выборке значения, на которое указывает указатель стека. После выборки слот, в котором размещался выбранный элемент, считается свободным.

Операция очистки стека сводится к записи в указатель стека начального значения - адреса начала выделенной области памяти.

Определение размера стека сводится к вычислению разности указателей: указателя стека и адреса начала области.

Пример класса простейшего варианта стека:

#include <iostream>

using namespace std;

typedef char TObject; // Синоним типа объекта блока.

typedef TObject *TPObject; // Синоним типа указателя на объект блока.

class Data // Абстрактный класс данных.

{

public:

virtual ~Data() {}

virtual void Push(const TObject) = 0; // Поместить данные.

virtual TObject Pop() = 0; // Изъять данные.

};

class Stack : public Data // Класс стека.

{

const size_t m_Size; // Размер стека в блоках (константа).

TPObject m_pBottom; // Дно стека.

TPObject m_pTop; // Вершина стека.

public:

Stack(const size_t = 1); // Конструктор (единый).

~Stack() { delete[] m_pBottom; }

void Push(const TObject); // Добавление объекта в стек.

TObject Pop(); // Получение объекта из стека.

};

Stack::Stack(const size_t Size)

: m_Size(Size)

{

if (!m_Size)

{

cout << "Ошибка! Неверный размер стека." << endl;

exit(-4);

}

if (!(m_pBottom = m_pTop = new TObject[m_Size]))

{

cout << "Ошибка! Недостаточно памяти." << endl;

exit(-1);

}

}

void Stack::Push(const TObject Ob) // Помещение в стек.

{

// Проверка наличия свободных блоков в стеке.

if (m_pTop < m_pBottom + m_Size)

*(m_pTop++) = Ob; // Запись объекта.

else

{

cout << "Ошибка! Стек заполнен." << endl;

exit(-2);

}

}

TObject Stack::Pop() // Взятие из стека.

{

// Проверка наличия объектов в стеке.

if (m_pTop > m_pBottom)

return *(--m_pTop); // Чтение объекта.

else

{

cout << "Ошибка! Стек пуст." << endl;

exit(-3);

}

}

[Динамическая реализация стека на основе односвязного списка]

Стек представляется как линейный список, в котором включение элементов всегда производятся в начала списка, а исключение - также из начала. Для представления его нам достаточно иметь один указатель - top, который всегда указывает на последний записанный в стек элемент. В исходном состоянии (при пустом стеке) указатель top - пустой. Процедуры StackPush и StackPop сводятся к включению и исключению элемента в начало списка. Обратите внимание, что при включении элемента для него выделяется память, а при исключении - освобождается.