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

15.8.2. Нерекурсивное решение. Стек в виде массива

#define DEEP 20 // Максимальная глубина стека

void hanoi(short a, // Исходная площадка

short b, // Площадка - цель

short n){ // Число дисков

short stack[DEEP][3],

i; // Индикатор уровня стека

bool fl; // false – стек пуст. Конец вычислений

fl = true;

i = -1;

while(fl){

if(n > 1){ // Заполнение стека

i++;

stack[ i ][0] = a;

stack[ i ][1] = b;

stack[ i ][2] = n;

// Подготовить первое обращение

b = 6-a-b;

n--;

}else{

if(i >= 0){ // Стек не пуст

// Печать вершины уровня 1

printf(" %2hd %2hd\n", a, b);

// Извлечь данные из стека

a = stack[ i ][0];

b = stack[ i ][1];

n = stack[ i ][2];

// Печать "корня"

printf(" %2hd %2hd\n", a, b);

// Подготовить второе обращение

a = 6-a-b;

n--;

// Убрать вершину из стека

i--;

}else{ // Стек пуст

fl = 0;

}

}

} // End while

// Печать последней вершины

printf(" %2hd %2hd\n", a, b);

} // End hanoi

15.8.3. Нерекурсивное решение. Стек в виде списка

Причем:

- элемент стека – произвольная структура;

- операции над стеком позволяют организовать в программе произвольное число стеков.

Файл hanoi.cpp. Главная процедура и процедура решения "ханойской башни".

#include <stdio.h>

#include <stdlib.h>

#include "stek.h" // Заголовочный файл для операций над стеком

int main( ){

short n;

void hanoi(short, short, short); // Прототип функции hanoi

printf("\n\nЧисло дисков:"); scanf("%hd", &n);

printf("\nПерестановки\n");

hanoi(1, 2, n );

}// End main

/* Ханойская башня */

void hanoi(short a, // Исходная площадка

short b, // Площадка - цель

short n){ // Число дисков

typedef struct{ // Содержимое элемента стека. В стек не помещается

short a, b, n;

} Cont;

Cont* cont; // Указатель на содержимое. Помещается в стек

bool fl = true; // false – конец вычислений

void* ident; // Идентификатор стека

ident = init( ); // Операция размещения стека

if(ident == NULL){ // Нет памяти под управляющие элементы стека

printf("\n\nНет памяти под стек \"Ханой\"\n\n");

exit(0); // Выход из программы. Это обработка ошибки

}

while(fl){

if(n > 1){ // Помещение в стек

cont=new Cont; // Размещение содержимого

if(cont == NULL){ // Нет памяти под содержимое элемента

printf("\n\nНет памяти под элемент стека \"Ханой\"\n\n");

exit(0);// Тоже обработка ошибки

}

// Заполнение содержимого элемента стека

cont->a = a; cont->b = b; cont->n = n;

//Поместить указатель на элемент в стек

if(push((CTRL*)ident, cont)){

printf("\n\nНет памяти под стек \"Ханой\"\n\n");

exit(0);// Обработка ошибки

}

// Опуститься на 1 уровень

b = 6-a-b; // Подготовка следующего содержимого элемента

n--;

}else{ // Печать переноса диска и извлечение из стека

printf(" %2hd %2hd\n", a, b);

// Получить указатель на элемент "вершины"

cont = (CONT*)top((CTRL*)ident);

if(cont == NULL){ // Стек пуст

fl = 0;

}else{ // Извлечение содержимого и печать переноса диска

a = cont->a; b = cont->b; n = cont->n;

printf(" %2hd %2hd\n", a, b);

// Опуститься на 1 уровень

a = 6-a-b; // Подготовка следующего элемента

n--;

delete cont;// Освободить память "верхнего" элемента

// Извлечь "вершину" стека. Освободить память

if(pop((CTRL*)ident)){ // Ошибка при извлечении

printf("\n\nОшибка при извлечении из стека\"Ханой\"\n\n");

exit(0); // Обработка ошибки

}

}

}

} // End while

finish((CTRL*)ident); // Освободить память из под стека

} // End hanoi

Файлы stek.h и stek.cpp. Операции над стеком.

// stek.h

// Типы данных

struct Stek{ // Стек указателей на элементы

Stek* prev; // Указатель на предыдущий элемент стека

void* cont; // Указатель на содержимое элемента

};

struct Ctrl{ // Управляющие переменные

Stek* tek, // Указатель на текущий элемент стека

*prev; // Указатель на предыдущий элемент стека

};

/* Прототипы функций */

void* init( ); // Разместить и инициализировать управляющие

// переменные

bool push(Ctrl* ident, void* cont) // Поместить в стек указатель на

// элемент

void* top(Ctrl* ident); // Прочесть информацию "вершины" стека

bool pop(Ctrl* ident); // Удалить "вершину" стека

void finish(Ctrl* ident); // Очистить стек и освободить память под

// управляющие переменные

// stek.cpp

#include "stek.h"

#include <stdlib.h>

// Инициализация стека

void* init( ){

Ctrl* ident;

ident = new Ctrl; // Размещение управляющих переменных

if(ident != NULL){ // Проверка выделения памяти

ident->prev = ident->tek = NULL;

}

return ident;

} // End init

// Поместить указатель на элемент в стек

bool push(Ctrl* ident, void* cont){

ident->tek = new Stek; // Выделение памяти под указатель

if(ident->tek == NULL){ // Проверка выделения памяти

return true;

}else{ // Включение элемента в список

ident->tek->prev = ident->prev; ident->tek->cont = cont;

ident->prev = ident->tek;

return false;

}

} // End push

// Прочесть "вершину" стека

void* top(Ctrl* ident){

if(ident->tek == NULL){ // Стек пуст. Ошибка!

return NULL;

}else{ // Возврат указателя на содержимое элемента

return ident->tek->cont;

}

} // End top

// Удалить "вершину" стека

bool pop(Ctrl* ident){

if(ident->tek == NULL){ // Стек пуст. Ошибка!

return true;

}else{

ident->prev = ident->tek->prev; free(ident->tek);

ident->tek = ident->prev; return false;

}

} // End pop

// Освободить память под стек и управляющие переменные

void finish(Ctrl* ident){

if(ident != NULL){

while(ident->tek != NULL){ //

ident->prev = ident->tek->prev;delete ident->tek;

ident->tek = ident->prev;

}

delete ident;

}

} // End finish

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