- •И.А. Васюткина основы алгоритмизации и программирования.
- •Содержание
- •1.Обзор языКа программирования с
- •2.Этапы создания программы
- •3.Структура программы на языке си
- •3.1. Внутренняя структура программы
- •3.2. Пример программы на си
- •4.Базовые элементы языка си
- •5.Данные в программе на си
- •5.1. Константы
- •5.2. Базовые стандартные типы переменных
- •6.2. Операции отношения
- •6.3. Логические операции
- •6.4. Операции с разрядами
- •6.5. Операции сдвига
- •6.6. Операция условия ?:
- •6.7. Преобразование типов
- •6.8. Операции приведения
- •6.9. Дополнительные операции присваивания
- •7.Операторы языка си
- •Оператор может быть простым и составным. Позволяет пропустить оператор или блок операторов, если условие ложно.
- •1.Схема выполнения оператора
- •8. Оператор множественного выбора
- •9. Операторы цикла while
- •8. Операторы безусловных переходов
- •8.Стандартные функции ввода и вывода
- •8.1. Функция вывода данных на экран printf ()
- •8.2. Модификаторы спецификаций преобразования
- •8.3. Функция ввода данных с клавиатуры sсanf()
- •8.4. Функции ввода/вывода одного символа getchar(), putchar()
- •8.5. Функции небуфиризированного ввода с клавиатуры
- •8.7. Форматирование вывода
- •Заключительная программа
- •9. Массивы
- •9.1. Одномерные массивы
- •Стандартные алгоритмы работы с одномерными массивами
- •Инициализация одномерных массивов
- •9.2. Многомерные массивы
- •Инициализация многомерных массивов
- •9.2.2 Стандартные алгоритмы работы с двумерными массивами
- •10. Функции
- •10.1.Cоздание и использование пользовательских функций
- •10.2.Параметры функции
- •10.3.Возвращение значения функцией
- •10.4.Inline-функции
- •10.5.Значение формальных параметров функции по умолчанию
- •10.6.Перегрузка функций
- •11. Классы памяти и область действия
- •11.1.Глобальные переменные
- •Extern - внешние переменные
- •Статистические внешние переменные - static
- •11.2.Локальные переменные
- •Внутренняя статическая переменная
- •Регистровая переменная
- •Автоматические переменные
- •11.3.Доступ к функциям в многомодульной программе
- •12. Препроцессор языка си
- •12.1. Подстановка имен
- •12.2.Включение файлов
- •12.3.Условная компиляция
- •13. Указатели
- •13.1.Операция косвенной адресации *
- •13.2. Описание указателей
- •13.3.Использование указателей для связи функций
- •13.4.Указатели на одномерные массивы
- •13.5.Указатели на многомерные массивы
- •13.6.Операции над указателями
- •13.7.Передача массива в качестве параметра в функцию
- •13.8.Указатель на void *
- •14. Символьные строки и функции над строками
- •14.1.Массивы символьных строк
- •14.2.Массивы указателей
- •14.3.Указатель как возвращаемое значение функции Передача указателя как параметра функции
- •14.4.Функции, работающие со строками Функции, определеные в заголовочном файле stdio.H
- •14.5. Стандартные библиотечные функции Функции, определеные в заголовочном файле string.H
- •14.6. Преобразование символьных строк
- •Функции, определеные в заголовочном файле ctype.H.
- •15. Ссылки
- •16. Параметры командной строки
- •17. Производные типы данных
- •17.1.Структуры
- •Массивы структур
- •Вложенные структуры
- •17.1.3 Указатели на структуры
- •Операции над структурами
- •Передача структуры в функцию
- •17.2.Объединения
- •17.3. Синоним имени типа
- •17.4.Определение именнованных констант
- •17.5.Перечисления
- •17.6.Битовые поля
- •18. Динамическое выделение памяти
- •2. Функция void* calloc(n,size type);
- •18.2.Операция new с массивами
- •18.3.Инициализаторы с операцией new
- •18.4.Ошибки при использовании динамичской памяти
- •19. Файл
- •19.1.Открытие файла fopen()
- •19.2.Закрытие файла fclose()
- •19.3.Функции ввода/вывода одного символа fgetc(), fputc()
- •19.4.Функции форматированного ввода/вывода в файл
- •Int fprintf(file *stream,”управл.Cтрока”,arg1,…)
- •Int fscanf(file *stream,”управл.Cтрока”,&arg1,…)
- •19.5. Функции ввода/вывода строки символов в файл
- •19.6.Функции управления указателем в файле
- •Int fseek(file *stream, смещение, start)
- •19.7.Ввод/вывод записей фиксированной длины
- •20. Динамические структуры данных
- •20.1.Однонаправленные связные списки
- •Вставка узла
- •Удаление узла из списка
- •20.2.Бинарные деревья
- •21. Размещение данных в памяти
- •22.Модели памяти
- •Список литературы
Вставка узла
a) в начало списка
start
temp
temp->next = start;
start = temp;
b ) в середину списка
start current
temp
temp->next = current->next;
current->next = temp;
в конец списка
end temp
end->next = temp;
end = temp;
end->next = NULL;
Удаление узла из списка
первого узла
start
TelNum *del = start;
start = start->next;
delete del;
В середине писка
current del
TelNum *del = current->next;
current->next = del->next;
delete del;
c) в конце списка
current end
TelNum *del = end;
current->next=NULL;
delete del;
end = current;
Алгоритмы, приведенные выше, обладают существенным недостатком - если необходимо произвести вставку или удаление ПЕРЕД заданным узлом, то так как неизвестен адрес предыдущего узла, невозможно получить доступ к указателю на удаляемый (вставляемый) узел и для его поиска надо произвести обход списка, что для больших списков неэффективно. Избежать этого позволяет двунаправленный список, который имеет два указателя: один - на последующий узел, другой - на предыдущий.
start
NULL
// Пример программы работы с односвязным списком
#include <stdio.h>
#include <conio.h>
struct TelNum;
int printAllData(TelNum * start);
int inputData(TelNum * n);
struct TelNum
{
TelNum * next;
long number;
char name[30];
};
// Описание: печать списка
int printAllData(TelNum * start){
int c=0;
for(TelNum * t=start;t; t= t->next)
printf("#%3.3i %7li %s\n",++c,t->number,t->name);
return 0;
}
// Описание: ввод данных в структуру n конец ввода - ввод нуля
// в первое поле. Возвращает 1 если конец ввода
int inputData(TelNum * n){
printf("Номер?"); scanf("%7li",&n->number);
if(!n->number) return 1;
printf("Имя? "); scanf("%30s",&n->name);
return 0;
}
void main(void){
TelNum * start = NULL; //сторож
TelNum * end = start;
do{ //блок добавления записей
TelNum * temp = new TelNum;
if(inputData(temp)) {
delete temp;
break;
}
else {
if(start==NULL) {
temp->next = start;
start = temp;
end = temp;
}
else {
end->next=temp;
end=temp;
end->next=NULL;
}
}
}while(1);
printf("\nЗаписи после добавления новых:\n");
printAllData(start);
getch();
do{ //блок удаления записей
TelNum * deleted = start;
start = start->next;
delete deleted;
printAllData(start);
getch();
}while(start!=NULL);
}
20.2.Бинарные деревья
В бинарном дереве каждый узел содержит 2 указателя. Начальная точка бинарного дерева называется корневым узлом.
Корневой узел Е указывает на В и Н. Узел В является корневым узлом для левого поддерева Е, узел Н – для правого поддерева Е. За исключением самого нижнего яруса каждый узел бинарного дерева имеет одно или два поддерева.
Обычно левое поддерево содержит меньшие данные, правое большие, что ускоряет поиск информации. Дерево такого типа называется деревом бинарного поиска.
Поиск обычно начинается с корня. В зависимости от результата сравнения двигаются либо влево (если данные узла больше образца поиска), либо вправо (если меньше). Новые узлы всегда присоединяются к нижним вершинам, так что дерево всегда растет вниз.
Чтобы распечатать бинарное дерево можно использовать алгоритм, называемый обратным ходом. Простейший алгоритм - рекурсивный. При заданном корне, программа совершает 3 шага:
а) выполняет обход левого поддерева;
б) печать корня;
в) выполняет обход правого поддерева.
Если обнаружен указатель NULL, то продвижение в направлении обхода в данном поддереве прекращается.
При прямом обходе содержимое корня печатается до обхода поддеревьев.
При концевом обходе содержимое корня печатается после совершения обхода двух поддеревьев.
// Пример программы работы с бинарным деревом
#include <stdio.h>
#include <conio.h>
#include <string.h>
struct TelNum;
void printtreepre(TelNum * ); //обход с корня дерева, левое поддерево, правое поддерево
void printtreein(TelNum * ); //обход с вершины правое поддерево,корень, левое поддерево
void printtreepost(TelNum * ); //обход с вершины левое поддерево, правое поддерево,корень
int inputData(TelNum * );
TelNum * addtree(TelNum *, TelNum *);
struct TelNum
{
TelNum * left, *right;
long number;
char name[30];
};
// Описание: печать списка
void printtreepre(TelNum * root)
{
if(!root) return;
if(root->number)
printf("номер %7li фамилия %s\n",root->number,root->name);
printtreepre(root->left);
printtreepre(root->right);
}
void printtreein(TelNum * root)
{
if(!root) return;
if(root->number)
printtreein(root->left);
printf("номер %7li фамилия %s\n",root->number,root->name);
printtreein(root->right);
}
void printtreepost(TelNum * root)
{
if(!root) return;
if(root->number)
printtreepost(root->left);
printtreepost(root->right);
printf("номер %7li фамилия %s\n",root->number,root->name);
}
// Описание: ввод данных
int inputData(TelNum * n)
{
printf("Номер?"); scanf("%7li",&n->number);
if(!n->number) return 1;
printf("Имя? "); scanf("%30s",&n->name);
return 0;
}
// Добавление узла к дереву
TelNum * addtree(TelNum *root, TelNum *temp) {
if(root==NULL) { //добавление узла в вершину дерева
TelNum * root = new TelNum;
root->number=temp->number;
strcpy(root->name,temp->name);
root->left=NULL;
root->right=NULL;
return root;
}
else {
if(root->number>temp->number)
root->left=addtree(root->left,temp);
else root->right=addtree(root->right,temp);
}
return root;
}
// Поиск значения в бинарном дереве
//по номеру телефона
void searchtree(TelNum *root, int num) {
while (root!=NULL) {
if(root->number==num) {
printf("номер %7li фамилия %s\n",root->number,root->name);
return ;
}
else{
if(root->number>num)
root=root->left;
else root=root->right;
}
}
puts("Телефон не найден");
return ;
}
void main(void)
{
TelNum * start = NULL; //сторож
TelNum * temp = new TelNum;
do{ //блок добавления записей
if(inputData(temp))
{delete temp;
break;
}
else
start=addtree(start,temp);
}while(1);
printtreepre(start); //ebcahgi
getch();
printtreein(start); //ighebca
getch();
printtreepost(start); //acbighe
getch();
int num;
puts("Введите номер телефона");
scanf("%d",&num);
searchtree(begin,num);
}