Главная страница

Шпаргалка по языку СИ. Конспект Лекций «программирование На Языке Высокого Уровня Си» П. Конспект лекций для студентов высших учебных заведений, обучающихся по специальности 230102. 65 Автоматизированные системы обработки информации и управления


Скачать 1.25 Mb.
НазваниеКонспект лекций для студентов высших учебных заведений, обучающихся по специальности 230102. 65 Автоматизированные системы обработки информации и управления
АнкорШпаргалка по языку СИ
Дата26.05.2022
Размер1.25 Mb.
Формат файлаpdf
Имя файлаКонспект Лекций «программирование На Языке Высокого Уровня Си» П.pdf
ТипКонспект лекций
#550544
страница10 из 15
1   ...   7   8   9   10   11   12   13   14   15
Деревья
Дерево – одна из наиболее распространённых структур данных, используемых в программировании. Формально дерево определяется рекурсивно
следующим образом: это конечное множество Т, состоящее из одного или более узлов таких, что:
1.
Имеется один узел, называемый корнем дерева.
2.
Остальные узлы, исключая корень, содержатся в m≥0 попарно непересекающихся множествах Т
1
, Т
2
,….Т
m
, каждое из которых в свою
162
очередь является деревом. При этом деревья Т
1
, Т
2
,….Т
m называются поддеревьями (потомками) данного корня.
Поддеревья некоторой вершины еще иногда называют кустами, а конечные вершины дерева из которых больше не выходит ни одной связи (т.е. для такого узла m=0), называют листьями.
Наиболее распространены в программировании бинарные (двоичные) деревья, в которых каждый узел может иметь не более двух потомков.
Рекурсивное определение бинарного дерева задает его как корень и два бинарных поддерева: левое и правое, – причем любое из них может быть пустым. Бинарные деревья используются как структура данных в том случае, когда в каждой точке процесса должно быть принято одно из двух возможных решений. Например, они применяются для синтаксического анализа, поиска, сортировки, управления базами данных и в других приложениях.
Пример 37. Приведем пример бинарного дерева (рис.44), которое может использоваться для вычисления алгебраического выражения (A*B+C*D)/(B*C), если двигаться от листьев дерева к корню.
Бинарные деревья наиболее часто используются в программировании. Это основывается на том факте, что любое дерево может быть приведено к бинарному. Основное правило такого преобразования: левая ветвь каждого узла соединяет его с первым узлом следующего уровня, а правая – с другими узлами следующего уровня (братьями). Рис.45 демонстрирует первый шаг преобразования дерева A к его бинарному представлению. На втором шаге тоже самое делается с поддеревом B и т.д.
163
/
+
*
*
*
B
C
B
C
A
D
Рис.44. Пример бинарного дерева

Рис.45. Шаг преобразования дерева к бинарному
Бинарное дерево на языке Си может быть описано следующими структурами данных:
struct tree
{
int info;
//информационное поле
tree ltree,rtree;
//указатели на левое и правое поддерево
}
К бинарным деревьям применяют следующие типовые операции:
1.
Создание нового бинарного дерева, состоящего из одного узла с информационным полем .
2.
Создание нового левого или правого «сына» (узла) для текущего узла.
3.
Чтение информационного содержимого узла.
4.
Определение указателя на левое или правое поддерево.
5.
Удаление куста или листа дерева.
6. Удаление левого или правого поддерева для узла.
7.
Обход дерева.
8. Сравнение деревьев.
9.
Соединение деревьев.
Пример 40. Рассмотрим реализацию основных процедур и функции для работы с деревьями.
tree MakeTree(tree node, int x)
{
if(node.value == NULL)
{
tree* p = new tree;
B
1
B
2
B
N
A
. . .
B
1
B
2
B
N
A
B
B
3
. . .
164


p->value = x;
node = *p;
}
else
{
if((node).value > x) MakeTree(*node.pleft, x);
else MakeTree(*node.pright, x);
}
return node;
}
void SetLeft (tree *p,int x) // создание левого сына для узла с указателем p
{
*p->ltree = NewNode(x);
}
void SetRight(tree *p,int x) // создание правого сына для узла с указателем p
{
*p->rtree = NewNode(x);
}
int GetInfo (tree *p) // чтение значения информационного поля узла p
{
if (p != NULL) return p->info;
else return(0);
}
tree GetLeftTree (tree *p)
// выдать значение указателя на левое поддерево
// узла p
{
if (p != NULL) return *p->ltree;
//else return(NULL);
}
tree GetRightTree (tree *p) //выдать значение указателя на правое поддерево
// узла p
{
if (p != NULL) return *p->ltree;
// else return (tree)NULL;
}
void DelLeaf (tree *p) // Удалить в дереве «лист»
{
if (p != NULL) free(p);
}
Рассмотрим более подробно задачу обхода дерева. Обход дерева – это последовательный обход всех узлов дерева. Фактически во время обхода нужно составить список всех узлов дерева. Поскольку дерево по определению является рекурсивной структурой данных, то и обход дерева как правило осуществляется рекурсивно. Существует три способа рекурсивного обхода бинарного дерева: обход с префиксным порядком; обход с инфиксным порядком; обход с суффиксным (или постфиксным) порядком.
165

Префиксный порядок обхода дерева определяется в виде списка узлов следующим образом:
Если дерево не пусто, то префиксный порядок это:
1.
Корень дерева.
2.
Узлы левого поддерева в префиксном порядке.
3.
Узлы правого поддерева в префиксном порядке.
Например, пусть дано дерево, указанное вна рис. примере 48, тогда префиксный обход дерева это следующая последовательность узлов: /
+*AB*CD*BC. Иногда префиксный порядок называют обходом дерева сверху
вниз.
Инфиксный порядок обхода дерева определяется в виде списка узлов следующим образом:
Если дерево не пусто, то инфиксный порядок это:
1.
Узлы левого поддерева в инфиксном порядке.
2.
Корень дерева.
3.
Узлы правого поддерева в инфиксном порядке.
Для нашего примера это будет: A*B+C*D/B*C
Суффиксный порядок обхода дерева определяется в виде списка узлов следующим образом:
Если дерево не пусто, то суффиксный порядок это:
1.
Узлы левого поддерева в суффиксном порядке.
2.
Узлы правого поддерева в суффиксном порядке.
3.
Корень дерева.
Для нашего примера это будет: AB*CD*+BC*/. Суффиксный порядок обхода иногда называют обходом дерева снизу вверх.
Заметим, что инфиксный порядок обхода бинарного дерева в нашем примере совпал с самим алгебраическим выражением, только без скобок, суффиксный порядок – совпал с ОПЗ выражения, а результат префиксного обхода является обратным инфиксному, т.е. сначала указывается операция, затем операнды, – именно так записываются функции и процедуры на языке Паскаль.
166

С обходом дерева как правило совмещаются некоторые действия над проходимой вершиной. Например, в случае суффиксного обхода, можно совместить обход с операцией удаления куста дерева.
void PrefixObhod (tree *p)
{
if (p !=NULL) // Если дерево не пусто, то префиксный порядок это:
{
printf ("%d", p->info); //обработка узла, например напечатем его
инф.часть
PrefixObhod (p->ltree); // Узлы левого поддерева в префиксном порядке
PrefixObhod (p->rtree); // Узлы правого поддерева в префиксном порядке
}
}
void InfixObhod (tree *p)
{
if (p != NULL) // Если дерево не пусто, то инфиксный порядок это:
{
InfixObhod (p->ltree); // Узлы левого поддерева в инфиксном порядке
printf ("%d", p->info); //обработка узла, например напечатем его
инф.часть
InfixObhod (p->rtree); // Узлы правого поддерева в инфиксном порядке
}
}
void DelSubTree (tree *p) //процедура удаление куста p с использованием
суффиксного обхода
{
if (p != NULL) // Если дерево не пусто, то суффиксный порядок это:
{
DelSubTree (p->ltree); // Узлы левого поддерева в суффиксном порядке
DelSubTree (p->rtree); // Узлы правого поддерева в суффиксном порядке
free(p);
//обработка узла, например удалим узел
}
}
void DelLeftTree (tree *p) //удаление левого поддерева для узла p
{
if (p != NULL)
{
DelSubTree (p->ltree);
p->ltree = NULL;
}
}
void DelRightTree (tree *p) //удаление правого поддерева для узла p
{
if (p != NULL)
{
DelSubTree (p->rtree);
p->ltree = NULL;
}
}
Сравнение деревьев производится путём сравнения информационной части
(информационных полей) соответствующих деревьев, начиная с корня. Функция должна сравнивать информационные части узлов дерева, а далее рекурсивно
167
сравнивать левые и правые поддеревья. Фактически функция осуществляет обход дерева сверху вниз. Выходом из рекурсии в данном случае будет сравнение значений указателей (в том числе и пустых). Для равных деревьев одновременно указатели будут обнулены и станут равными. В случае различия, это равенство не пройдет. Если же оба указателя отличны от пустых, т.е. указывают на поддеревья, то сравниваются их информационные части и соответственно левые и правые потомки. Если все эти три сравнения совпадают, то делается заключение о совпадении сравниваемых деревьев.
Напишем функцию, которая будет выдавать истинное значение, если два дерева равны, и ложное значение в противном случае.
bool TreeEqual(tree *p1, tree *p2)
{
if (p1 == p2) return true;
else
if ((p2 != NULL) && (p1 != NULL))
return ((p1->info = p2->info) && TreeEqual(p1->ltree, p2->ltree) &&
TreeEqual(p1->rtree, p2->rtree));
else return false;
}
Приложение 1. Стандартные библиотеки языка Си
В языке Си стандартные функции собраны в различных библиотеках. Для использования этих функций необходимо подключить к проекту соотаетствующие библиотеки с помощью конструкции #include. Ниже представлены некоторые библиотеки языка Си, а также их состав.
Таблица 19.
Библиотеки языка Си
Имя
Назначение библиотеки
complex.h
Набор функций для работы с комплексными числами
ctype.h
Содержит функции, используемые для классификации символов по их типам или для конвертации между верхним и нижним регистрами независимо от используемой кодировки
errno.h
Для проверки кодов ошибок, возвращаемых библиотечными функциями
iostream
Содержит функции контроля чтения и записи стандартных потоков
limits.h
Содержит заранее заданные константы, определяющие специфику реализации свойств целых типов
signal.h
Функции для управления различными исключительными условиями
math.h
Функции для вычисления основных математических функций
stdio.h
Реализует основные возможности ввода и вывода в языке Си
stdlib.h
Вспомогательные функции, которые могут быть использованы в разнообразных программах
string.h
Для работы с различными видами строк
168

time.h
Для конвертации между различными форматами времени и даты
Таблица 20.
Состав библиотеки complex.h
Имя функции
Описание
cabs, cabsf, cabsl
Абсолютное значение комплексного числа
cacos, cacosf, cacosl
Комплексный арккосинус
cacosh, cacoshf, cacoshl
Комплексный гиперболический арккосинус
carg, cargf, cargl
Аргумент комплексного числа
casin, casinf, casinl
Комплексный арксинус
casinh, casinhf, casinhl
Комплексный гиперболический арксинус
catan, catanf, catanl
Комплексный арктангенс
catanh, catanhf, catanhl
Комплексный гиперболический арктангенс
ccos, ccosf, ccosl
Комплексный косинус
ccosh, ccoshf, ccoshl
Комплексный гиперболический косинус
cexp, cexpf, cexpl
Комплексная экспонента
cimag, cimagf, cimagl
Мнимая часть комплексного числа
clog, clogf, clogl
Натуральный логарифм комплексного числа
conj, conjf, conjl
Комплексное сопряжённое число
cpow, cpowf, cpowl
Степень комплексного числа
cproj, cprojf, cprojl
Проекция на римановскую сферу
creal, crealf, creall
Действительная часть комплексного числа
csin, csinf, csinl
Комплексный синус
csinh, csinhf, csinhl
Комплексный гиперболический синус
csqrt, csqrtf, csqrtl
Комплексный квадратный корень
ctan, ctanf, ctanl
Комплексный тангенс
ctanh, ctanhf, ctanhl
Комплексный гиперболический тангенс
Таблица 21.
Состав библиотеки ctype.h
Имя функции
Проверяет, является ли аргумент…
isalnum
…буквой или цифрой
isalpha
…буквой
iscntrl
…управляющим символом
isdigit
…цифрой
isgraph
…символом, имеющим графическое представление
islower
…буквой в нижнем регистре
isprint
…символом, который может быть напечатан
ispunct
…символом, имеющим графическое представление, но не являющимся при этом буквой или цифрой
isspace
…разделительным символом
isupper
…буквой в верхнем регистре
isxdigit
…цифрой шестнадцатиричной системы счисления
Таблица 22.
Состав библиотеки errno.h
Имя функции
Описание
E2BIG
Список аргументов слишком длинный
EACCES
Отказ в доступе
EAGAIN
Ресурс временно недоступен
EBADF
Неправильный дескриптор файла
EBADMSG
Неправильное сообщение
169

EBUSY
Ресурс занят
ECANCELED
Операция отменена
ECHILD
Нет дочернего процесса
EDEADLK
Обход тупика ресурсов
EDOM
Ошибка области определения
EEXIST
Файл существует
EFAULT
Неправильный адрес
EFBIG
Файл слишком велик
EINPROGRESS
Операция в процессе выполнения
EINTR
Прерванный вызов функции
EINVAL
Неправильный аргумент
EIO
Ошибка ввода-вывода
EISDIR
Это каталог
EMFILE
Слишком много открытых файлов
EMLINK
Слишком много связей
EMSGSIZE
Неопределённая длина буфера сообщения
ENAMETOOLONG
Имя файла слишком длинное
ENFILE
Слишком много открытых файлов в системе
ENODEV
Нет такого устройства
ENOENT
Нет такого файла в каталоге
ENOEXEC
Ошибка формата исполняемого файла
ENOLCK
Блокировка недоступна
ENOMEM
Недостаточно памяти
ENOSPC
Памяти на устройстве не осталось
ENOSYS
Функция не реализована
ENOTDIR
Это не каталог
ENOTEMPTY
Каталог непустой
ENOTSUP
Не поддерживается
ENOTTY
Неопределённая операция управления вводом-выводом
ENXIO
Нет такого устройства или адреса
EPERM
Операция не разрешена
EPIPE
Разрушенный канал
ERANGE
Результат слишком велик
EROFS
Файловая система только на чтение
ESPIPE
Неправильное позиционирование
ESRCH
Нет такого процесса
ETIMEDOUT
Операция задержана
EXDEV
Неопределённая связь
Таблица 23.
Состав библиотеки iostream.h
Имя функции
Описание
cin
Соответствует стандартному вводу. В общем случае он позволяет читать данные с терминала пользователя
cout
Соответствует стандартному выводу. В общем случае он позволяет выводить данные на терминал пользователя
cerr
Соответствует стандартному выводу для ошибок. В этот поток мы направляем сообщения об ошибках программы
Таблица 24.
Состав библиотеки limits.h
170

Имя
Описание
Типичное
значение 32-
битной
программы
Типичное
значение 64-
битной
программы
Стандартный
минимум или
максимум
диапазона значений
CHAR_BIT
Число бит в байте
8 8
≥ 8
SCHAR_MIN
Минимальное значение для знакового char
−128
−128
≤ -127
SCHAR_MAX
Максимальное значение для знакового char
+127
+127
≥ +127
UCHAR_MAX
Максимальное значение для беззнакового char
+255
+255
≥ +255
CHAR_MIN
Минимальное значение для char
−128
−128
≤ -127(если char представлено как знаковый char; иначе 0)
CHAR_MAX
Максимальное значение для char
+127
+127
≥ +127 (если char представлено как знаковый char; иначе +255)
MB_LEN_MAX
Максимальная многобайтовая длина символа по всем локалям различается, обычно от 4 различается, обычно от 4
≥ 1
SHRT_MIN
Минимальное значение для short int
−32,768
−32,768
≤ -32,767
SHRT_MAX
Максимальное значение для short int
+32,767
+32,767
≥ +32,767
USHRT_MAX
Максимальное значение для беззнакового short int
+65,535
+65,535
≥ +65,535
INT_MIN
Минимальное значение для int
−2,147,483,648
−2,147,483,648
≤ -32,767
INT_MAX
Максимальное значение для int
+2,147,483,647
+2,147,483,647
≥ +32,767
UINT_MAX
Максимальное значение для беззнакового int
+4,294,967,295
+4,294,967,295
≥ +65,535
LONG_MIN
Минимальное значение для long int
−2,147,483,648
−9,223,372,036,854
,775,808
≤ -2,147,483,647
LONG_MAX
Максимальное значение для long int
+2,147,483,647
+9,223,372,036,854
,775,807
≥ +2,147,483,647
ULONG_MAX
максимальное значение для беззнакового long int
+4,294,967,295
+18,446,744,073,70 9,551,615
≥ +4,294,967,295
LLONG_MIN
Минимальное значение для long long int
−9,223,372,036,85 4,775,808
−9,223,372,036,854
,775,808
≤ -9,223,372,036,854,775,807
LLONG_MAX
Максимальное значение для long long int
+9,223,372,036,85 4,775,807
+9,223,372,036,854,
775,807
≥ +9,223,372,036,854,775,807
1   ...   7   8   9   10   11   12   13   14   15


написать администратору сайта