Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
algorithms-2010.doc
Скачиваний:
33
Добавлен:
06.12.2018
Размер:
9.83 Mб
Скачать

Стек. Реализация 4 (на основе массива из двух указателей).

Однако, можно поступить и по-другому. Т.к. элементы stack и head имеют один тип, то их можно объединить в один массив объектов соответствующего типа (т.е. типа int* ). Массив, естественно, должен быть длины 2:

int *st4[2];

Здесь следует заметить, что при определении/описании переменных квадратные скобки имеют приоритет больший, чем *, поэтому переменная st4 имеет тип `массив указателей’, а не `указатель на массив’.

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

void StackCreate4(int n, int *st[2] ) {st[1]= st[0] = (int*)malloc(n*sizeof(int));}

а ее вызов будет выглядеть так: StackCreate4(n,st4);

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

void StackAdd4(int v, int * st[2] ) { (*(st[1]++)) = v;}

а ее вызов будет выглядеть так: StackAdd4 (v, st4);

Проверка стека на пустоту выглядит следующим образом :

int StackIsEmpty4 ( int * st[2] ) { return st[1]<=st[0] ; }

Стек. Реализация 5 (на основе указателя на указатель).

У Реализации 4 есть существенный недостаток. Допустим, что стек создан внутри некоторой функции и требуется использовать его вне данной функции. Тогда у нас есть единственная возможность осуществить данную реализацию, это - сделать переменную st4 глобальной или локальной статической. В противном случае, при выходе из данной функции переменная st4 утратит свое существование и указателями st4[0], st4[1] уже нельзя будет пользоваться. Но, как уже писалось, подобный способ реализации является дурным стилем.

Собственно, вся наша проблема состоит в том, что память под переменную st4 отводится и очищается автоматически. В качестве альтернативы, отведение/очистку памяти под указатели можно взять на себя. Для этого следует использовать указатель на указатель на целую переменную:

int **st5;

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

int ** StackCreate5(int n )

{int **st; st = (int**)malloc(2*sizeof(int*));

st[1]= st[0] = (int*)malloc(n*sizeof(int));

}

а ее вызов будет выглядеть так: st5=StackCreate5(n);

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

void StackDelete5(int **st ) { free(st[0]); free(st);}

а ее вызов будет выглядеть так: StackDelete5 (st5);

Если мы хотим уменьшить накладные расходы при отведении памяти и ускорить создание/уничтожение стека, то имеет смысл изменить несколько скорректировать функции StackCreate5 и StackDelete5. Действительно, память можно отвести всего один раз. Размер отведенной памяти должен быть достаточен для хранения (последовательно) массива из двух указателей и для массива из n элементов стека. В таком случае функции отведения/освобождения памяти могут выглядеть следующим образом

int ** StackCreate5x(int n )

{int **st; st = (int**)malloc(2*sizeof(int*)+ n*sizeof(int));

st[1]= st[0] = (int*)(st+2);

}

void StackDelete5x(int **st ) {free(st);}

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