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

40.Типи даних

Тип даних — характеристика, яку явночи неявно надано об'єкту (змінній,функції, полю запису, константі,масиву тощо). Тип даних визначає множину припустимих значень, формат їхнього збереження, розмір виділеної пам'яті та набір операцій, які можна робити над даними.

Машинні типи даних

У всіх комп'ютерах, основаних на цифровій електроніці, інформація на найнижчому рівні представляється у вигляді бітів (із значенням 0 або 1). Найменша адресована одиниця інформації називаєтьсябайт (зазвичай як октет, який містить 8 бітів). Одиниця інформації, яка оброблюється інструкціями машинного коду, називається словом (станом на 2006 рік, зазвичай по 32 або 64 біти). Більшість інструкцій сприймають слово як двійкове число, щоб 32-бітне слово могло бути представлене беззнаковим цілим числом від 0 до 232 − 1, або знакове ціле від − 231 до 231 − 1. Через наявність доповнюючого коду, машині не потрібно розрізняти знакове та беззнакове числа для більшості випадків.

Існує спеціальний набір арифметичних інструкцій, які використовують різні представлення бітів у слова, для операцій з рухомою крапкою.

Прості типи даних

Мови програмування представляють деякі прості типи даних(або примітивні), як базові блоки для програм та спеціалізованіших складних типів даних. Зазвичай прості типи даних включають числові (кілька цілих та дійсних типів), логічний (булевий), символьний та байтовий.

Числові типи даних

Цілі числа

Цілі числа(англ.integer) не можуть містити у собі дріб. Для від'ємного числа треба ставити знак мінус (-) перед значенням (числом). Неможна використовувати кому у введені такого числа, бо інакше буде викликана синтаксична помилка. Приклади цілих чисел:

  • 42

  • 10000

  • −233000

  • −100

Дійсні числа

Дійсні числа можуть містити у собі як цілі, так і дробові значення з точкою відокремлення від цілої частини. Для від'ємного числа треба ставити знак мінус (-) перед значенням (числом). Приклади дійсних чисел:

  • 20.0005

  • 99.9

  • −5000.12

  • −9999.9991

Складні типи даних

Складні типи даних — це типи, які складаються з елементів, що відносяться до простих типів. До складних типів даних відносяться: масиви; множини; рядки; записи; файли; динамічні змінні; вказівники; лінійні списки (стеки, черги); нелінійні списки (двійкові дерева, несиметричні дерева, тексти, графи); процедурний тип; об'єкти[1].

Рядки

Рядки(англ.string) — нечисловий тип даних, та використовується для збереження букв та слів. Усі рядки складаються з символів. Рядки можуть містити цифри та числа, але все одно будуть оброблятися як текст. Приклади рядків:

  • «A»

  • «Hello World»

  • «Телефон»

  • «Мені 99 років»

  • «1.2.3.4.5.6.7.8.9»

У деяких мовах програмування кількість символів у рядку може бути обмежена, у інших довжина рядка може обмежуватись лише кількістю пам'яті у комп'ютері. Можуть бути також порожні рядки.

Діапазон числових типів даних

Кожне числовий тип даних має мінімальне та максимальне значення, яке називають діапазон значень. Важливо знати діапазон значень, особливо, коли працюєш з «маленькими» типами даних, оскільки у них можна зберігати лише значення у вузькому діапазоні. Спроба внести число, більше за доступний діапазон може призвести до помилок періоду компіляції/виконання, або до неправильних підрахунків (через відкидання) залежно від мови програмування, яка використовується.

Діапазон змінних оснований на кількості байтів відведених для збереження значення. Цілі типи даних зазвичай здатні зберігати 2n значень (де n — це кількість байтів, що еквівалентно до 28n бітів). Для інших типів даних (напр. дійсних чисел) діапазон заплутаніший, та залежить від методу зберігання інформації у ньому. Існують також типи даних, які не викоритовують весь байт, напр. булеві, яким потрібен лише один біт, і представляє собою двійкове значення (хоча на практиці використовується весь байт, то 7 бітів залишаються невикористаними).

Ключові слова у мові Паскаль є:

And

Asm

Array

Begin

Case

Const

Constructor

Destructor

Div

Do

Downto

Else

End

File

For

Function

Goto

If

Implementation

In

Inline

Interface

Label

Mod

Nil

Not

Object

Of

Or

Packed

Procedure

Program

Record

Repeat

Set

Shl

Shr

String

Then

To

Type

Unit

Until

Uses

Var

While

With

Xor

Стандартні директиви та зарезервовані слова в програмі можуть

використовуватися лише за своїм прямим призначенням, і не можуть бути використані у будь-якій іншій якості.

45.Перемикальні директиви включають і вимикають можливості компілятора. Вони можуть бути локальними або глобальними.     * Локальні директиви можуть перебувати де-небудь у тілі програми. Вони впливають тільки на частину компіляції.     * Глобальні директиви повинні знаходитися перед розділом описів програми або модуля. Вони впливають на всю компіляцію. Ви можете групувати кілька перемикачів, розділяючи їх комами. Наприклад: {$ F +, $ R +, $ E-, $ D-}

Директива

Назва

Назва українською

$ A

Align Data

Байтове вирівнювання

$ B

Boolean Evaluation

Булева оцінка

$ D

Debug Information

Отладочная інформація

$ F

Force Far Calls

Далекий тип дзвінка

$ G

Generate 80286 Code

Інструкції 286

$ I

Input / Output-Checking

Перевірка вводу / виводу

$ K

Smart Callbacks

Підпрограми повторного виклику

$ L

Local Symbol Information

Інформація про символи

$ N

80x87 Numeric Coprocessor

$ P

Open String Parameters

Відкриті строкові параметри

$ Q

Overflow Checking

Перевірка переповнення

$ R

Range-Checking

Перевірка діапазону

$ S

Stack-Overflow Checking

Перевірка переповнення стека

$ T

Typed-Pointer Checking

Перевірка типів покажчиків

$ V

Var-String Checking

Перевірка строкових параметрів

$ W

Windows Stack Frame

Windows

Область стека

$ X

Extended Syntax

Розширений синтаксис

$ Y

Symbol Reference Information

Інформація про символи

Цикли

У більшості задач, що зустрічаються на практиці, необхідно робити багаторазове виконання деякої дії. Такий багаторазово повторювана ділянка обчислювального процесу називається циклом.

Якщо заздалегідь відома кількість необхідних повторень, то цикл називається арифметичним. Якщо ж кількість повторень заздалегідь невідомо, то говорять про ітераційний цикл.

В ітераційних циклах виробляється перевірка деякої умови, і в залежності від результату цієї перевірки відбувається або вихід з циклу, або повторення виконання тіла циклу. Якщо перевірка умови виробляється перед виконанням блоку операторів, то такий ітераційний цикл називається циклом із предусловием (цикл "поки"), а якщо перевірка виробляється після виконання тіла циклу, те це цикл із постусловием (цикл "до").

Особливість цих циклів полягає в тім, що тіло циклу з постусловием завжди виконується хоча б один раз, а тіло циклу з предусловием може жодного разу не виконатися. У залежності від розв'язуваної задачі необхідно використовувати той чи інший вид ітераційних циклів.

Цикл з передумовою

Цикл з передумовою — цикл, що виконується доки істинна деяка умова, вказана перед його початком. Ця умова перевіряється до початку виконання тіла циклу, тому тіло може бути не виконане жодного разу (якщо умова з початку хибна). У більшості процедурних мов програмування здійснюється за допомогою інструкції while, звідси його друга назва — while-цикл. На мові Паскаль цикл з передумовою має наступний вигляд:

while <умова> do

begin

<тіло циклу>

end;

На мові Сі:

while(<умова>)

{

<тіло циклу>

}

Цикл з післяумовою

Цикл з післяумовою — цикл, в якому умова перевіряється після виконання тіла циклу. Звідси випливає, що тіло циклу завжди виконується хоча б один раз. У мові Паскаль такий цикл здійснює інструкціяrepeat..until; у Сі — do…while. На мові Паскаль цикл з післяумовою має наступний вигляд:

repeat

<тіло циклу>

until <умова>

На мові Сі:

do

{

<тіло циклу>

}

while(<умова>)

У трактуванні умови циклу з післяумовою в різних мовах є розбіжності. У Паскалі і мовах похідних від нього умова такого циклу трактується як умова виходу (цикл завершується, коли умова істинна), а в Сі та його нащадках — як умова продовження (цикл завершується, коли умова хибна).

58.

K-вершинно-зв'язний граф

K-реберно-зв'язний граф

Вначале опишем типы данных:

#define N 12; // Количество вершин графа.

typedef struct zveno *svqz;

typedef struct zveno

{

int Key; //Вершина графа.

svqz Sled; // Указатель на следующую смежную вершину.

} Leader;

svqz beg[N]; // Описание типа списков смежности.

  1. Построение списков смежности, соответствующих данному ориентированному графу.

  2. Перед первым обращением к функции MakeGraph (создание графа) необходима инициализация списков смежности:

for (i=0;i<N;i++) beg[i] = NULL;

void MakeGraph (svqz beg[N])

// Построение списков смежности beg графа.

{

int x,y;

svqz ukzv,uzel; //Рабочие указатели.

cout<<"Вводите начало дуги: ";

cin>>x;

while (x!=0)

{

cout<< "Вводите конец дуги: ";

cin>>y;

AddGraph (x,y,beg);

cout<< "Вводите начало дуги: "; cin>>x;

}

}

    2. Вывод содержимого списков смежности, соответствующих ориентированному графу.

void PrintGraph (svqz beg[N])

{

int i;

svqz ukzv; //Рабочий указатель.

for (i=1;i<N;i++)

{

cout<<i<<" ...";

ukzv = beg[i];

if (ukzv==NULL) cout<<"Пустойсписок!\n";

else {

while (ukzv!=NULL)

{ cout<< (*ukzv).Key; ukzv = (*ukzv).Sled; }

cout<<endl; }

}

}

    Теперь рассмотрим реализацию унарных операций [1, с.22] на графе.

    3. Добавление дуги (x,y) (если ее не было!) к спискам смежности, соответствующим ориентированному графу.

void AddGraph (int x, int y, svqz beg[N])

{

svqz ukzv,uzel; //Рабочие указатели.

if (beg[x]!=NULL)

{

Poisk (beg[x],y,&ukzv);

if (ukzv==NULL)

{ // Добавление элемента в конец списка,

// заданного указателем beg[x].

uzel = new (Leader);

(*uzel).Key = y; (*uzel).Sled = NULL; ukzv = beg[x];

while ((*ukzv).Sled!=NULL)

ukzv = (*ukzv).Sled;

(*ukzv).Sled = uzel;

}

}

else

{

beg[x] = new (zveno);

(*beg[x]).Key = y; (*beg[x]).Sled = NULL;

}

}

    4. Удаление дуги между двумя заданными вершинами графа, представленного списками смежности (заметим, что вершины, инцидентные дуге, из графа не удаляются).

void DeleteGraph (int x, int y, svqz beg[N])

{

svqz ukzv;

if (beg[x]!=NULL)

//Удаление звена из списка без заглавного звена.

{ //Вершины в графе есть.

Poisk (beg[x],y,&ukzv);

if (ukzv!=NULL) Udalenie (&beg[x],&ukzv);

else cout<<"Такой дуги в графе нет!\n";

}

else cout<<"Списокпуст!\n";

}

void Poisk (svqz uksp, int ment, svqz *res)

// Поиск звена с информационным полем ment в

// однонаправленном списке uksp. *res - указатель

// на найденное звено или NULL.

{

svqz q;

*res = NULL; q = uksp;

while ((q!=NULL)&&(*res==NULL))

{ if ((*q).Key==ment) *res = q;

q = (*q).Sled; }

}

void Udalenie (svqz *ukstr, svqz *zv)

// Удаление звена, на которое ссылается указатель *zv,

// из однонаправленного списка, заданного указателем *ukstr.

{

svqz ukzv,z;

if (((**ukstr).Sled==NULL)&&(*zv==*ukstr))

// В списке - один элемент!

{ *ukstr = NULL; delete zv; }

else

if (*zv==*ukstr) // Удаляемый элемент - первый.

{ *ukstr = (**ukstr).Sled; delete zv; }

else {

z = *ukstr; ukzv = (**ukstr).Sled;

while (ukzv!=*zv)

{ z = ukzv; ukzv = (*ukzv).Sled; }

(*z).Sled = (*(*zv)).Sled; delete zv;

}

}

    Отметим, что удаление вершины v из графа G приводит к подграфу, содержащему все вершины графа G за исключением v, и все ребра графа G, не инцидентные v. Заметим, что при данном представлении графа удаление вершин становится достаточно громоздким.

    Приведем программу, демонстрирующую работу перечисленных выше функций.

    Пример. Построение списков смежности, соответствующих ориентированному графу, вывод их на экран, добавление и удаление дуг.

#include <iostream.h>

#define N 12 //Количество вершин графа.

#define TRUE 1

#define FALSE 0

typedef struct zveno *svqz;

typedef struct zveno

{

int Key; //Вершинаграфа.

svqz Sled; //Указатель на следующую смежную вершину.

} Leader;

class Spisok {

private:

svqz beg[N]; //Описание типа списков смежности.

svqz res; //Указатель на найденное звено.

void Poisk (svqz,int);

void Udalenie (svqz *);

public:

Spisok ();

svqz GetPoisk () { return res; }

void MakeGraph ();

void AddGraph (int,int);

void DeleteGraph (int,int);

void PrintGraph ();

};

void main ()

{

Spisok A;

int x; // Началодуги.

int y; // Конец дуги.

A.MakeGraph (); // Построение списков смежности.

// Вывод списков смежностей.

cout<<"Представление графа списками смежности\n";

A.PrintGraph (); cout<<endl;

// Добавление дуги к графу.

cout<<"Добавим к графу новую дугу...\n";

cout<<"Введите начало дуги: "; cin>>x;

cout<<"Введите конец дуги: "; cin>>y;

A.AddGraph (x,y);

cout<<"Представление графа списками смежности\n";

A.PrintGraph (); cout<<endl;

//Удаление дуги из графа.

cout<<"Удалим из графа заданную дугу...\n";

cout<<"Введите начало дуги: "; cin>>x;

cout<<"Введите конец дуги: "; cin>>y;

A.DeleteGraph (x,y);

cout<<"Представление графа списками смежности\n";

A.PrintGraph (); cout<<endl;

}

void Spisok::Poisk (svqz uksp,int ment)

// Поиск звена с информационным полем ment в

// однонаправленном списке uksp. res - указатель

// на найденное звено или NULL.

{

svqz q;

res = NULL; q = uksp;

while ((q!=NULL)&&(res==NULL))

{ if ((*q).Key==ment) res = q; q = (*q).Sled; }

}

void Spisok::AddGraph (int x,int y)

// Добавление дуги (x,y) (если ее не было!) в граф,

// представленный списками смежности beg .

{

svqz ukzv,uzel; // Рабочие указатели.

if (beg[x]!=NULL)

{

Poisk (beg[x],y);

if (GetPoisk()==NULL)

{ //Добавление элемента в конец списка, заданного указателем beg[x].

uzel = new (Leader);

(*uzel).Key = y; (*uzel).Sled = NULL; ukzv = beg[x];

while ((*ukzv).Sled!=NULL)

ukzv = (*ukzv).Sled;

(*ukzv).Sled = uzel; }

}

else { beg[x] = new (zveno);(*beg[x]).Key = y; (*beg[x]).Sled = NULL; }

}

void Spisok::MakeGraph ()

// Построение списков смежности beg графа.

{

int x,y;

cout<<"Вводите начало дуги: "; cin>>x;

cout<<"Вводите конец дуги: "; cin>>y;

while (x!=0)

{

AddGraph (x,y);

cout<< "Вводите начало дуги: "; cin>>x;

cout<<"Вводите конец дуги: "; cin>>y;

}

}

void Spisok::Udalenie (svqz *ukstr)

//* Удаление звена, на которое ссылается указатель res,

// из однонаправленного списка, заданного указателем *ukstr

{

svqz ukzv,z;

if (((**ukstr).Sled==NULL)&&(res==*ukstr)) //В списке - один элемент!

{ *ukstr = NULL; delete res; }

else if (res==*ukstr) // Удаляемый элемент - первый.

{ *ukstr = (**ukstr).Sled; delete res; }

else {

z = *ukstr; ukzv = (**ukstr).Sled;

while (ukzv!=res) { z = ukzv; ukzv = (*ukzv).Sled; }

(*z).Sled = (*res).Sled; delete res; }

}

void Spisok::DeleteGraph (int x,int y)

// Удаление дуги (x,y) из списков смежности beg.

{

if (beg[x]!=NULL)

// Удаление звена из списка без заглавного звена.

{ // Вершины в графе есть.

Poisk (beg[x],y);

if (GetPoisk()!=NULL) Udalenie (&beg[x]);

else cout<<"Такой дуги в графе нет!\n"; }

else cout<<"Списокпуст!\n";

}

void Spisok::PrintGraph ()

{

svqz ukzv; // Рабочийуказатель.

for (int i=1;i<N;i++)

{ cout<<"..."<<i; ukzv = beg[i];

if (ukzv==NULL) cout<<" Пустойсписок!\n";

else {

while (ukzv!=NULL) { cout<<(*ukzv).Key; ukzv = (*ukzv).Sled; }

cout<<endl; }

}

}

Spisok::Spisok() { for (int i=0;i<N;i++) beg[i] = NULL; }

64.В теорії графів,задача про найкоротший шлях полягає в знаходженні шляхуміж двома вершинами (або вузлами) такого, що сума ваг ребер з яких він складається мінімальна. Прикладом може бути знаходження найкоротшого шляху між двома пунктами на дорожній мапі; в цьому випадку, вершини являють собою пункти, а ребра відтинки дороги із вагами рівними часу необхідному для подолання цього відтинку.

Формально, маємо зважений граф (це набір вершин V і ребер E з дійсно-значимою функцією вагиf : ER), і заданим елементом v з V, знайти шлях P з v до v' з V такий, що

Граф з 6 вершинами і 7 ребрами

найменша серед усіх шляхів, що зв'язують v з v' .

Така задача іноді згадується як Задача про найкоротший шлях між парою вершин, щоб відрізнити від наступних узагальнень:

  • Задача про найкоротші шляхи з одного входом, тут ми маємо знайти найкоротші шляхи між вхідною вершиною v та всіма іншими вершинами графа.

  • Задача про найкоротші шляхи з одним виходом, тут ми маємо знайти найкоротші шляхи з усіх вершин графа до однієї вихідної v. Може бути зведена до задачі з одним входом шляхом зміни на зворотні ребер графа.

  • Задача про найкоротші шляхи для всіх пар, тут ми маємо знайти найкоротші шляхи між кожною парою вершин v, v' в графі.

Ці узагальнення мають значно дієвіші алгоритми ніж спрощений підхід із запуском алгоротма пошуку найкоротшого шляху між всіми значимими парами вершин.

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