Структура данных «стек»

Стек — это упрощенный вариант связанного списка. Новые узлы могут добавляться в стек и удаляться из стека только сверху. По этой причине, стек часто называют структурой вида последним пришелпервым обслужился (LIFO). На стек ссылаются через указатель на верхний элемент стека. Связывающий элемент в последнем узле стека установлен равным NULL, чтобы пометить границу стека.

Графическое представление стека с несколькими узлами показано на рис. 1.4. Следует отметить, что стеки и связанные списки представляются идентично. Разница между стеком и связанными списками в том, что вставку и удаление в связанных списках можно выполнять в любом месте, а в стеке только сверху.

Рис. 1.4. Графическая иллюстрация стека

Примеры. Программа работает с простым стеком целых чисел. Программа выполняет три действия на выбор: 1) помещает значение в стек (функция push), 2) извлекает значение из стека (функция pop), и 3) завершает работу.

#include "stdafx.h"

#include<stdlib.h>

#include<malloc.h>

#include<stdio.h>

struct stackNode

{

int data;

struct stackNode *nextPrt;

};

typedef struct stackNode STACKNODE;

typedef STACKNODE * STACKNODEPTR;

void push(STACKNODEPTR *, int);

int pop(STACKNODEPTR *);

int isEmpty(STACKNODEPTR);

void printStack(STACKNODEPTR);

void instruc(void);

void main()

{

STACKNODEPTR stackPtr = NULL;

int choice, value;

instruc();

printf("? ");

scanf("%d", &choice);

while (choice!=3)

{

switch (choice)

{

case 1:

printf("Enter an integer >> ");

scanf("%d", &value);

push (&stackPtr, value);

printStack(stackPtr);

break;

case 2:

if (!isEmpty(stackPtr))

printf("the popped value is %d \n", pop(&stackPtr));

printStack(stackPtr);

break;

default:

printf("Error enter\n");

instruc();

break;

}

printf("? ");

scanf("%d", &choice);

}

printf("End \n");

}

void instruc(void)

{

printf("1 - dobavit\n");

printf("2 - delete\n");

printf("3 - exit\n");

}

void push(STACKNODEPTR *topPtr, int info)

{

STACKNODEPTR newPtr;

newPtr = new STACKNODE;

if (newPtr!= NULL)

{

newPtr ->data = info;

newPtr ->nextPrt = * topPtr;

*topPtr = newPtr;

}

else

printf("%d Error not memori\n", info);

}

int pop(STACKNODEPTR *topPtr)

{

STACKNODEPTR tempPtr;

int popValue;

tempPtr = *topPtr;

popValue = (*topPtr) ->data;

*topPtr = (*topPtr) ->nextPrt;

free(tempPtr);

return popValue;

}

void printStack(STACKNODEPTR currentPtr)

{

if (currentPtr == NULL)

printf("Error not stack\n\n");

else

{

printf("Stack is:>> \n");

while (currentPtr!= NULL)

{

printf("%d -> ", currentPtr ->data);

currentPtr = currentPtr ->nextPrt;

}

printf("\n");

}

}

int isEmpty (STACKNODEPTR topPtr)

{

return topPtr == NULL;

}

В данном примере основные функции, используемые при работе со стеками — push и pop. Функция push создает новый узел и помещает его на вершину стека. Функция pop удаляет верхний узел стека, освобождает память, которая была выделена изъятому узлу, и возвращает изъятое значение.

Программа работает с простым стеком целых чисел. Программа выполняет три действия на выбор: 1) помещает значение в стек (функция push), 2) изымает значение из стека (функция pop), и 3) завершает работу.

Функция push помещает новый узел на вершину стека. В выполнении функции можно выделить три этапа:

1. Создание нового узла посредством вызова malloc, при этом указателю newPtr присваивается адрес блока выделенной памяти; переменной newPtr -> data присваивается значение, которое необходимо поместить в стек; и указателю newPtr->nextPtr присваивается NULL.

2. Указателю newPtr->nextPtr присваивается *topPtr (указатель на вершину стека); связывающий элемент newPtr теперь указывает на узел, который был верхним до этого.

3. *topPtr присваивается значение newPtr; *topPtr теперь указывает на новую вершину стека. Операции, включающие в себя *topPtr, меняют значение stackPtr в main.

а)
б)

Рис. 1.5. Графическая иллюстрация выполнения функции push

Наглядное представление о том, как происходит выполнение функции push показано на рис. 1.5. На рис. 1.5, а изображен стек и новый узел перед выполнением функции push. Пунктирные линии на рис. 1.5, б иллюстрируют шаги 2 и 3 выполнения функции push, в результате которых узел, содержащий 12, становится новой вершиной стека.

Функция pop удаляет верхний узел стека. Отметим, что перед тем как вызвать функцию pop, функция main определяет, не пуст ли стек. В выполнении функции pop можно выделить пять основных этапов:

1. Указателю tempPtr присваивается *topPtr (tempPtr будет использован для освобождения ненужной памяти).

2. Переменной popValue присваивается значение (*topPtr)->data (сохраняется значение, находившееся в верхнем узле).

3. *topPtr присваивается (*topPtr)->nextPtr (*topPtr присваивается адрес нового верхнего узла).

4. Освобождается память, на которую указывает tempPtr.

5. Вызывающей функции возвращается значение popValue (в примере программы это функция — main).

Выполнение функции pop проиллюстрировано на рис. 1.6. На рис. 1.6, а показано состояния стека после предыдущей операции push. На рис. 1.6, б выделены указатели tempPtr, указывающий на первый узел стека, и *topPtr, указывающий на второй узел. Для освобождения указанной tempPtr памяти вызывается функция free.

а)
б)

Рис. 1.6. Графическая иллюстрация выполнения функции pop

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

На стеке выделяется пространство для автоматических переменных при каждом вызове функции. Когда происходит возврат от вызванной функции к вызывающей, пространство автоматических переменных функции удаляется из стека, и эти переменные становятся для программы неизвестными.

Компиляторы используют стеки в процессе вычисления выражений и создания кода машинного языка.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: