- •Основы алгоритмизации и программирования, язык Си
- •Введение
- •Блок-схема алгоритма Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Операции и выражения
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора Директива #include
- •Директива #define
- •Понятие пустого и составного операторов
- •Условные операторы
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Операторы перехода (break, continue, return, goto)
- •Примеры программ
- •Массивы Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Параметры по умолчанию
- •Передача массива в функцию
- •Inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Доступ к элементам структуры
- •Инициализация структур
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Примеры программ
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Потоки и файлы
- •Файлы Основные сведения о файловой системе
- •Организация посимвольного ввода и вывода
- •Определение конца файла feof()
- •Организация ввода и вывода строк
- •Удаление файлов
- •Дозапись потока
- •Позиционирование в файле
- •Текстовые и двоичные файлы
- •Функции fread() и fwrite()
- •Примеры программ
- •Хеширование
- •Схемы хеширования
- •Метод открытой адресации с линейным опробыванием
- •Метод цепочек
- •Машинное представление графов
- •Примеры программ
- •Литература
Операции со списками при связном хранении
Удаление элемента, следующего за узлом, на который указывает р (см. рис. 12 ). Исключение элемента из цепочки данных сводится к изменению одной единственной ссылки и не требует перемещения остальных элементов, как это имело бы место, например, для массивов.
Рис. 12. Схема удаления элемента из списка.
r=p->n;
p->n=r->n;
free(r);
Добавление нового элемента в цепочку данных. Для этого достаточно изменить одну ссылку. Ниже показана вставка нового узла со значением new за элементом, определенным указателем р (см. рис. 13):
Рис. 13. Схема вставки элемента в список.
r=( SPIS*)malloc(1,sizeof(SPIS));
r->n=p->n; r->val=new; p->n=r;
Печать значений элементов списка. Рассматриваются два случая:
1) печать значения элемента списка определяемого указателем r:
r=dl;
while(r)
{ printf("\n элемент %d равен %f ",i,r->val);
r=r->n;
}
2) печать обоих соседей узла(элемента), определяемого указателем p (см. рис.14)
Рис.14. Схема выбора соседних элементов.
if((r=p->n)==NULL) printf("\n нет соседа справа");
else printf("\n сосед справа %f", r->val);
if(p==dl) printf("\n нет соседа слева" );
else { r=dl;
while( r->n!=p ) r=r->n;
printf("\n левый сосед %f", r->val);
}
Частичное упорядочение списка (см. рис.15)
Рис.15. Схема частичного упорядочения списка.
SPIS *v;
float k1;
k1=dl->val;
r=dl;
while( r->n!=NULL )
{ v=r->n;
if (v->valn=v->n
v->n=dl;
dl=v;
}
else r=v;
}
Стек
Стек - это конечная последовательность некоторых однотипных элементов - скалярных переменных, массивов, структур или объединений, среди которых могут быть и одинаковые. Размещение новых элементов в стек и удаление существующих из стека производится только с одного его конца, называемого вершиной стека.
Стек предполагает добавление и удаление из него элементов так, что стек является динамической, постоянно меняющейся структурой. Согласно определению, в стеке имеется только одно место для размещения новых элементов - его вершина. Последний размещаемый элемент находится в вершине стека. Стек иногда называется списком с организацией LIFO - ”последний размещенный извлекается первым”. Если необходимо поддерживать информацию о промежуточных состояниях стека, то она должна размещаться вне стека. Внутри самого стека эта информация не поддерживается.
Допустимыми операциями над стеком являются:
- проверка стека на пустоту;
- добавление нового элемента на вершину стека;
- удаление элемента в вершины стека.
Стек можно представить как стопку книг на столе, где добавление или взятие новой книги возможно только сверху.
Ниже приводится текст программы, иллюстрирующий работу со стеком:
#include <stdio.h>
#include <alloc.h>
#include <conio.h>
#include <string.h>
struct zap {char inf[50];
zap *l;};
void push(zap **);
void pop(zap **);
void see(zap *);
void sort1(zap *);
void sort2(zap **);
void (*f[])(zap **)={push,pop,sort2};
void (*ff[])(zap *)={see,sort1};
main()
{ zap *s;
char l;
clrscr();
s=NULL;
while(1)
{ puts("\nвид операции:\n 1-создать/добавить\n 2-удалить");
puts(" 3-просмотреть\n 4-сортировка 1\n 5-сортировка 2");
puts(" 0-окончить");
fflush(stdin);
l=getch();
switch(l)
{ case '1': (*f[0])(&s); break;
case '2': if(s) (*f[1])(&s); break;
case '3': (*ff[0])(s); break;
case '4': if (s) (*ff[1])(s); break;
case '5': if (s) (*f[2])(&s); break;
case '0': return;
default: printf("Ошибка, повторите \n");
}
}
return 0;
}
// функция cоздания/добавления в стек
void push(zap **s)
{ zap *s1=*s;
do
{ if(!(*s=(zap *) calloc(1,sizeof(zap))))
{ puts("Нет памяти");
return;
}
puts("Введите информацию в inf");
fflush(stdin);
gets((*s)->inf);
(*s)->l=s1;
s1=*s;
puts("Продолжить (y/n)");
fflush(stdin);
} while(getch()=='y');
}
// функция просмотра элементов стека
void see(zap *s)
{ zap *s1;
s1=s;
if (!s)
{ puts("Стек пуст");
return;
}
do
{ printf("%s\n",s1->inf);
s1=s1->l;
} while(s1);
puts("Вывод стека закончен");
}
// функция удаления последнего элемента стека
void pop(zap **s)
{ zap *s1;
s1=*s;
*s=(*s)->l;
free(s1);
puts("Последний элемент стека удален");
return;
}
// функция сортировки элементов стека
// перестановкой содержимого элементов стека
void sort1(zap *s)
{ zap *s1,*s2;
for(;s->l;s=s->l)
{ s1=s; // элемент стека для упорядочивания
for(s2=s->l;s2;s2=s2->l) // перебор последующих эл-тов справа от i-го
if(strcmp(s1->inf,s2->inf)>0)
s1=s2; // найдено новое меньшее значение
// по новому адресу
if(s1!=s)
{ strcpy(s2->inf,s1->inf);
strcpy(s1->inf,s->inf);
strcpy(s->inf,s2->inf);
}
}
puts("Сортировка стека выполнена");
}
// функция сортировки элементов стека
// перестановкой адресов элементов стека
void sort2(zap **s)
{ zap *ss,*s1,*s2,*s3,*s4=NULL;
ss=( zap *) calloc(1,sizeof(zap));
ss->l=*s; // ссылка на вершину стека
for(;ss->l->l;)
{ s1=ss->l; // элемент стека для упорядочивания
for(s2=ss->l; s2->l; s2=s2->l) // перебор последующих эл-тов стека
if(strcmp(s1->inf,s2->l->inf)>0) // найдено новое меньшее значение
{ s1=s2->l; // адрес текущего минимального эл-та
s3=s2; // адрес элемента перед минимальным
}
if(s1!=ss->l)
{ s3->l=s1->l;
s1->l=ss->l;
ss->l=s1;
}
ss=ss->l;
if(!s4) s4=s1; //новая вершина стека
}
puts("Сортировка стека выполнена");
*s=s4;
}