Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Рекурсивные алгоритмы.doc
Скачиваний:
3
Добавлен:
05.11.2018
Размер:
400.9 Кб
Скачать

Int Maximum(int a[10], int l, int r)//заголовок ф-ии

{//a-исходный массив, l-индекс 1-го эл-та, r-индекс //последнего эл-та

if (l==r) return a[l]; //если массив состоит из 1-го //эл-та, то он и есть max

int m=(l+r)/2;//делим массив на 2 подмассива

int u=Maximum(a,l,m);//ищем в 1-ом максимальный эл-т

int v=Maximum(a,m+1,r);//во 2-ом также ищем //максимальный эл-т

if (u>v) return u; else return v;//сравнивая их, //возвращаем максимальный

}

-------------------------------------------------------------------------------------------------------

Программа 2 (Рисование меток) (Имя файла: line.cpp) :

-------------------------------------------------------------------------------------------------------

//*******************************************************

//Подключаемые заголовочные файлы

#include <stdio.h> //стандартный ввод-вывод

#include <conio.h>//для ф-ии getch() и т. д.

#include <ctype.h>//для ф-ии isdigit()

#include <string.h>//работа со строками

#include <stdlib.h>//стандартная библиотека (для ф-ии //atoi(),exit(1))

#include <graphics.h>//работа с графикой

#include <dos.h>//для ф-ии delay()

//*******************************************************

//объявление глобальных переменных

int stepen;//число 2^n

int lastx;//абсцисса текущей метки

//*******************************************************

//Основная функция main()

void main()

{

int Error();//прототип ф-ии запроса и проверки на //неверный ввод

void Rule(int, int, int);//прототип рекурсивной ф-//ии, вызывающей Mark(x,h)

int i,n;//i-счетчик цикла, n-показатель степени 2

while(1) // цикл проверки введенного n в диапазоне

{

n=Error(); // вызов ф-ии запроса и прис-е рез-та

if (n>=1 && n<=8) break;// диапазон

}

stepen=2;

for (i=1;i<n;i++) stepen=stepen*2;//цикл подсчета //степени 2^n

int gdriver = DETECT, gmode;//переменные для //инициализации граф. режима

initgraph(&gdriver,&gmode, "");//инициализация граф. //режима

if (graphresult()!=0) //проверка на ошибку

{

clrscr();

printf("\nОшибка инициализации графики!!!");

getch();

exit(1); //выйти из программы в случае ошибки

}

setcolor(10);//установка св.-зел. цвета рисования

//рисование левой границы линейки

line(0,getmaxy()-200,0,getmaxy()-210-10*n);

setcolor(11);//установка св.-сер. цвета рисования

Rule(0,stepen,n);//вызов рекурсивной ф-ии

setcolor(10);//установка св.-зел. цвета рисования

//рисование верхней границы линейки

line(0,getmaxy()-210-10*n,lastx+getmaxx()/stepen, getmaxy()-210-10*n);

//рисование нижней границы линейки

line(0,getmaxy()-200,lastx+getmaxx()/stepen, getmaxy()-200);

//рисование правой границы линейки

line(lastx+getmaxx()/stepen,getmaxy()-200, lastx+getmaxx()/stepen,getmaxy()-210-10*n);

setcolor(5);//установка роз. цвета рисования

//вывод сообщения

outtextxy(getmaxx()/2-80,getmaxy()-100,"Press any key for quit");

getch();//задержка

delay(1000);

closegraph(); //закрытие графического режима

return;

}

//*******************************************************

//ф-ия запроса и проверки (защита от неверных нажатий)

int Error()//заголовок ф-ии

{

int i;

char str[10]; //вводимая строка

int str_int[2]; //массив из 2 целых значений

clrscr();//очистка экрана

// печать строки на экран

printf("\n\t\tВведите показатель степени 2 разрешения 1/2^n (1-8): ");

gets(str);//ф-ия ввода строки с клавиатуры

i=1;

if (strlen(str)>2) return 0;

while (i<=strlen(str))//цикл преобразования кодов //символов из char в int,

{//а также анализ на код не цифры

str_int[i-1]=(int)str[i-1];//в эл-ты массива //str_int поместить преобразованные в тип int коды //введенных символов

if (isdigit(str_int[i-1])==0) return 0;//выйти из //ф-ии с передачей 0, если это код не цифры

i++;

}

return atoi(str);//ф-ия преобразования введенной //строки в целое число типа int, а также возвращение //этого рез-та в главную ф-ию main()

}

//*******************************************************

//рекурсивная ф-ия, вызывающая Mark(x,h)

void Rule (int l, int r, int h)//заголовок ф-ии

{//l-условная абсцисса левой границы линейки

// r-условная абсцисса правой границы линейки 2

// h-высота самой длинной метки

void Mark (int, int);//прототип ф-ии рисования меток

int m=(l+r)/2;//делим линейку пополам

if (h>0) //если высота метки не нулевая, то

{

Rule(l,m,h-1); //вызов ф-ии из самой себя (рекурсия), //сначала работаем в левой части линейки

Mark(m,h); //вызов ф-ии рисования метки

Rule(m,r,h-1);//вызов ф-ии из самой себя (рекурсия), //потом работаем в правой части линейки

}

}

//*******************************************************

//ф-ия рисования меток

void Mark (int x, int p)//заголовок ф-ии

{//x-коэффициент абсциссы метки, p-коэффициент высоты //метки

lastx=getmaxx()/stepen*x;//в глоб. перем. заносим //текущую абсциссу метки

//рисуем метку

line(lastx,getmaxy()-200,lastx,getmaxy()-200-p*10); return;//возврат из ф-ии

}

-------------------------------------------------------------------------------------------------------

Программа 3 (Ханойские башни) (Имя файла: han_gr_3.cpp) :

-------------------------------------------------------------------------------------------------------

//*******************************************************

//Подключаемые заголовочные файлы

#include <stdio.h> //стандартный ввод-вывод

#include <conio.h>//для ф-ии getch() и т. д.

#include <ctype.h>//для ф-ии isdigit()

#include <string.h>//работа со строками

#include <stdlib.h>//стандартная библиотека (для ф-ии //atoi(),exit(1))

#include <graphics.h>//работа с графикой

#include <dos.h>//для ф-ии delay()

//*******************************************************

//объявление глобальных переменных

struct zap //структура, состоящая из

{ int y1,y2;//ординат верхнего и нижнего угла объекта

};

zap arr_A[14],arr_B[14],arr_C[14];//3 массива(3 //столбика) из структур

int i; //счетчик цикла

char ch; //код символа

FILE *st1;//указатель на файл st1

int w=54;//доп. переменная для рисования дисков

//*******************************************************

//Основная функция main()

void main()

{

void Move_Disks(int, char, char, char);//прототип //функции получения решения

void Graph_disk (int, char, char, char);//прототип //ф-ии графического представления решения

int Error(); //прототип ф-ии запроса и проверки //на неверные символы

int r; //кол-во дисков

int e; //кол-во перемещений (шагов)

while(1)// цикл проверки введенного r в диапазоне

{

r=Error();// вызов ф-ии запроса и прис-е рез-та

if (r>=1 && r<=14) break; // диапазон

}

for (i=1,e=2;i<r;i++) e=e*2;//цикл подсчета кол-ва //перемещений e по формуле 2^n-1

e--;

st1=fopen("res.txt","w+");//создание или открытие //файла res.txt

// печать строки в файл, на который указывает st1

fprintf(st1,"\t\tРешение задачи о Ханойских башнях для %d дисков:\n\n",r);

Move_Disks(r,'A','C','B');//вызов рекурсивной ф-ии //решения

// печать строки в файл, на который указывает st1

fprintf(st1,"\nТребуется %d перемещений!",e);

fclose(st1); //закрытие файла

Graph_disk(r,'A','C','B');//вызов ф-ии //графического представления решения

return;//выход из главной ф-ии

}

//*******************************************************

//Описание функции получения решения (рекурсивная)

//заголовок ф-ии с параметрами

void Move_Disks (int n, char Source, char Dest, char Temp)

{

if (n==1) //если имеется только 1 диск, то это //элементарно

{

fprintf(st1,"Переставить диск номер 1 со столбика %c на столбик %c\n",Source,Dest);

}

else //иначе:

{//сначала перемещаем n-1 диск со столбика A на //столбик B, используя столбик C как вспомогательный

Move_Disks(n-1,Source,Temp,Dest);//вызов процедуры из //самой себя, или рекурсия

fprintf(st1,"Переставить диск номер %d со столбика %c на столбик %c\n",n,Source,Dest);

//затем перемещаем n-1 диск со столбика B на столбик C, //используя столбик A как вспомогательный

Move_Disks(n-1,Temp,Dest,Source);//вызов процедуры из //самой себя, или рекурсия

return;//возврат из ф-ии

}

}

//*******************************************************

//ф-ия запроса и проверки (защита от неверных нажатий)

int Error()//заголовок ф-ии

{

char str[10]; //вводимая строка

int str_int[2]; //массив из 2 целых значений

clrscr();//очистка экрана

// печать строки на экран

printf("\n\t\tВведите количество дисков (без пробелов!) (1-14): ");

gets(str);//ф-ия ввода строки с клавиатуры

i=1;

if (strlen(str)>2) return 0;

while (i<=strlen(str))//цикл преобразования кодов //символов из char в int, а также анализ на код не цифры

{ str_int[i-1]=(int)str[i-1];//в эл-ты массива //str_int поместить преобразованные в тип int коды //введенных символов

if (isdigit(str_int[i-1])==0) return 0;//выйти из //ф-ии с передачей 0, если это код не цифры

i++;

}

return atoi(str);//ф-ия преобразования введенной //строки в целое число типа int, а также возвращение //этого рез-та в главную ф-ию main()

}

//*******************************************************

//ф-ия прорисовки шагов

void Graph_disk(int n, char S, char D, char T)//заголовок

{

void Graph_steps(int, char, char, char);//прототип //рекурсивной граф. ф-ии

int Klav_getch();//прототип ф-ии нажатий 'n' и 'q'

int gdriver = DETECT, gmode;//переменные для //инициализации граф. режима

initgraph(&gdriver,&gmode, "");//инициализация граф. //режима

if (graphresult()!=0) //проверка на ошибку

{

clrscr();

printf("\nОшибка инициализации графики!!!");

getch();

exit(1); //выйти из программы в случае ошибки

}

//сообщения на экран

printf("\t\tРешение задачи о Ханойских башнях для %d дисков:",n);

printf("\n\n\n\tЖмите:\n\t n - для просмотра очередного шага");

printf("\n\t q - для выхода (результат см. в файле res.txt)\n");

setcolor(10);//установка светло-зеленого цвета

rectangle(0,20,getmaxx(),getmaxy());//обрамление экрана

setfillstyle(1,5);//установка сплошного розового стиля //заливки

//рисование 3-х столбиков с обозначением A,B,C

bar(getmaxx()/4-40,200,getmaxx()/4-39,getmaxy()-40);

outtextxy(getmaxx()/4-42,getmaxy()-20,"A");

bar(getmaxx()/4*2,200,getmaxx()/4*2+1,getmaxy()-40);

outtextxy(getmaxx()/4*2-2,getmaxy()-20,"B");

bar(getmaxx()/4*3+40,200,getmaxx()/4*3+41,getmaxy()-40);

outtextxy(getmaxx()/4*3+38,getmaxy()-20,"C");

setfillstyle(1,11);//установка сплошного светло-серого //стиля заливки

int o=68; //доп. переменная для рисования дисков

char stroka[3]; //строка, которая будет содержать номер //рисуемого диска

i=1;

while (i<=n) //цикл заполнения массивов ординат

{

arr_A[n-i].y1=getmaxy()-o+4;//ордината верхнего угла //диска

arr_A[n-i].y2=getmaxy()-o+12;//ордината нижнего угла //диска

arr_B[n-i].y1=getmaxy()-o+4;

arr_B[n-i].y2=getmaxy()-o+12;

arr_C[n-i].y1=getmaxy()-o+4;

arr_C[n-i].y2=getmaxy()-o+12;

//нач. прорисовка дисков с уменьшением диаметра на //столбике A

bar(getmaxx()/4-36-w,arr_A[n-i].y1,getmaxx()/4-39+w-4, arr_A[n-i].y2);

itoa(n+1-i,stroka,10);//преобразование номера диска в //строку stroka

//вывод номера диска слева от диска

outtextxy(getmaxx()/4-36-w-17,getmaxy()-o+5,stroka);

w=w-4;//радиус вышележащего(след.)диска уменьшаем на 4

o=o+12;//изменяем ординаты углов вышележащего(след.) //диска

i++;

}

o=0;

setfillstyle(1,0);//установить сплошную черную заливку

o=Klav_getch(); // при нажатии 'n'

if (o==1) Graph_steps(n,S,D,T);// вызвать ф-ию

cleardevice();//залить экран

//выдать сообщение

outtextxy(getmaxx()/2-80,getmaxy()/2,"Press any key for quit");

getch();//задержка

delay(1000);

closegraph(); //закрытие графического режима

return;//возврат из ф-ии

}

//*******************************************************

//рекурсивная граф. ф-ия

void Graph_steps(int n, char S, char D, char T) //заголовок ф-ии

{

void Analizing(int, char, char);//прототип ф-ии //перемещения дисков

int Klav_getch();//прототип ф-ии нажатий 'n' и 'q'

if (n==1) //если имеется только 1 диск, то это //элементарно(с A на C)

{

Analizing(n,S,D);//вызвать ф-ию перемещения дисков

Klav_getch(); //вызвать ф-ию на нажатия 'n' и 'q'

}

else//иначе

{//сначала перемещаем n-1 диск со столбика A на //столбик B, используя столбик C как вспомогательный

Graph_steps(n-1,S,T,D);//вызов процедуры из самой //себя, или рекурсия

Analizing(n,S,D);//вызвать ф-ию перемещения дисков

Klav_getch();//вызвать ф-ию на нажатия 'n' и 'q'

//затем перемещаем n-1 диск со столбика B на //столбик C, используя столбик A как вспомогательный

Graph_steps(n-1,T,D,S);//вызов процедуры из самой //себя, или рекурсия

return;//возврат из ф-ии

}

}

//*******************************************************

//ф-ия перемещения дисков

void Analizing(int n, char S, char D) //заголовок ф-ии

//n-номер переносимого диска, S-откуда переносить, D-//куда переносить

{ void *ukaz; //указатель на объект для ф-ии //getimage/putimage

switch(S)

{//диск переносится со столбика A

case 'A' : switch(D)

{//на столбик B

case 'B' : {//сохраняем в памяти //объект(диск и его номер) на столбике A, ординаты берем //из соотв. массива

getimage(getmaxx()/4-120,arr_A[n-1].y1,getmaxx()/4+11,arr_A[n-1].y2,ukaz);

setfillstyle(1,0);

//стираем его со столбика A

bar(getmaxx()/4-120,arr_A[n-1].y1,getmaxx()/4+11,arr_A[n-1].y2);

setfillstyle(1,5);

//снова прорисовываем часть //столбика A, где был диск

bar(getmaxx()/4-40,arr_A[n-1].y1,getmaxx()/4-39,arr_A[n-1].y2);

//начиная с низа столбика B до его //верхушки ищем свободное место для переносимого диска, //анализируя цвет

for (i=1;i<=164;i=i+4) if (getpixel(getmaxx()/4*2,getmaxy()-55-i)==5)

{//если оно найдено,то

//в соотв. эл-т //массива запоминаем новые ординаты переносимого диска

arr_B[n-1].y1=getmaxy()-55-i-8;

arr_B[n-1].y2=getmaxy()-55-i;

setfillstyle(1,0);

//стираем часть //столбика B, куда будет перенесен диск

bar(getmaxx()/4*2,arr_B[n-1].y1,getmaxx()/4*2+1,arr_B[n-1].y2);

//и, наконец, //вставляем из памяти объект в найденное место

putimage(getmaxx()/4*2-80,arr_B[n-1].y1,ukaz,1);

break;

}

} break;

//далее все аналогично

//на столбик C

case 'C' : {getimage(getmaxx()/4-120,arr_A[n-1].y1,getmaxx()/4+11,arr_A[n-1].y2,ukaz);

setfillstyle(1,0);

bar(getmaxx()/4-120,arr_A[n-1].y1,getmaxx()/4+11,arr_A[n-1].y2);

setfillstyle(1,5);

bar(getmaxx()/4-40,arr_A[n-1].y1,getmaxx()/4-39,arr_A[n-1].y2);

for (i=1;i<=164;i=i+4) if (getpixel(getmaxx()/4*3+40,getmaxy()-55-i)==5)

{

arr_C[n-1].y1=getmaxy()-55-i-8;

arr_C[n-1].y2=getmaxy()-55-i;

setfillstyle(1,0);

bar(getmaxx()/4*3+40,arr_C[n-1].y1,getmaxx()/4*3+41,arr_C[n-1].y2);

putimage(getmaxx()/4*3+40-80,arr_C[n-1].y1,ukaz,1);

break;

}

} break;

} break;

//диск переносится со столбика B

case 'B' : switch(D)

{//на столбик A

case 'A' : {getimage(getmaxx()/4*2-80,arr_B[n-1].y1,getmaxx()/4*2+51,arr_B[n-1].y2,ukaz);

setfillstyle(1,0);

bar(getmaxx()/4*2-80,arr_B[n-1].y1,getmaxx()/4*2+51,arr_B[n-1].y2);

setfillstyle(1,5);

bar(getmaxx()/4*2,arr_B[n-1].y1,getmaxx()/4*2+1,arr_B[n-1].y2);

for (i=1;i<=164;i=i+4) if (getpixel(getmaxx()/4-40,getmaxy()-55-i)==5)

{

arr_A[n-1].y1=getmaxy()-55-i-8;

arr_A[n-1].y2=getmaxy()-55-i;

setfillstyle(1,0);

bar(getmaxx()/4-40,arr_A[n-1].y1,getmaxx()/4-39,arr_A[n-1].y2);

putimage(getmaxx()/4-120,arr_A[n-1].y1,ukaz,1);

break;

}

} break;

//на столбик C

case 'C' : {getimage(getmaxx()/4*2-80,arr_B[n-1].y1,getmaxx()/4*2+51,arr_B[n-1].y2,ukaz);

setfillstyle(1,0);

bar(getmaxx()/4*2-80,arr_B[n-1].y1,getmaxx()/4*2+51,arr_B[n-1].y2);

setfillstyle(1,5);

bar(getmaxx()/4*2,arr_B[n-1].y1,getmaxx()/4*2+1,arr_B[n-1].y2);

for (i=1;i<=164;i=i+4) if (getpixel(getmaxx()/4*3+40,getmaxy()-55-i)==5)

{

arr_C[n-1].y1=getmaxy()-55-i-8;

arr_C[n-1].y2=getmaxy()-55-i;

setfillstyle(1,0);

bar(getmaxx()/4*3+40,arr_C[n-1].y1,getmaxx()/4*3+41,arr_C[n-1].y2);

putimage(getmaxx()/4*3+40-80,arr_C[n-1].y1,ukaz,1);

break;

}

} break;

} break;

//диск переносится со столбика C

case 'C' : switch(D)

{//на столбик A

case 'A' : {getimage(getmaxx()/4*3+40-80,arr_C[n-1].y1,getmaxx()/4*3+40+51,arr_C[n-1].y2,ukaz);

setfillstyle(1,0);

bar(getmaxx()/4*3+40-80,arr_C[n-1].y1,getmaxx()/4*3+40+51,arr_C[n-1].y2);

setfillstyle(1,5);

bar(getmaxx()/4*3+40,arr_C[n-1].y1,getmaxx()/4*3+41,arr_C[n-1].y2);

for (i=1;i<=164;i=i+4) if (getpixel(getmaxx()/4-40,getmaxy()-55-i)==5)

{

arr_A[n-1].y1=getmaxy()-55-i-8;

arr_A[n-1].y2=getmaxy()-55-i;

setfillstyle(1,0);

bar(getmaxx()/4-40,arr_A[n-1].y1,getmaxx()/4-39,arr_A[n-1].y2);

putimage(getmaxx()/4-120,arr_A[n-1].y1,ukaz,1);

break;

}

} break;

//на столбик B

case 'B' : {getimage(getmaxx()/4*3+40-80,arr_C[n-1].y1,getmaxx()/4*3+40+51,arr_C[n-1].y2,ukaz);

setfillstyle(1,0);

bar(getmaxx()/4*3+40-80,arr_C[n-1].y1,getmaxx()/4*3+40+51,arr_C[n-1].y2);

setfillstyle(1,5);

bar(getmaxx()/4*3+40,arr_C[n-1].y1,getmaxx()/4*3+41,arr_C[n-1].y2);

for (i=1;i<=164;i=i+4) if (getpixel(getmaxx()/4*2,getmaxy()-55-i)==5)

{

arr_B[n-1].y1=getmaxy()-55-i-8;

arr_B[n-1].y2=getmaxy()-55-i;

setfillstyle(1,0);

bar(getmaxx()/4*2,arr_B[n-1].y1,getmaxx()/4*2+1,arr_B[n-1].y2);

putimage(getmaxx()/4*2-80,arr_B[n-1].y1,ukaz,1);

break;

}

} break;

} break;

}

return;//возврат из ф-ии

}

//*******************************************************

//ф-ия на нажатия 'n' и 'q'

int Klav_getch()//заголовок ф-ии

{

w=0;

while(1) //цикл анализа нажатой клавиши

{

ch=getch();//принять от клавиатуры символ

switch(ch)

{

case 'q': i=1 ; break; //выход из цикла //производится,только если была

case 'n':{i=1;w=1;} break;//нажата 'n' или 'q'

default : i=0 ;

}

if (i==1) break;

}

if (w==0) //если нажата 'q', то

{

setfillstyle(1,0);

cleardevice(); //залить экран

//выдать сообщение

outtextxy(getmaxx()/2-80,getmaxy()/2,"Press any key for quit");

getch(); //задержка до нажатия

delay(1000);

closegraph(); //закрыть граф. режим

exit(1);//прервать выполнение программы

}

return 1;//если нажата 'n', то возвратить значение 1

}

-------------------------------------------------------------------------------------------------------