- •Функции.
- •Вызов функции с переменным числом параметров
- •Функция main и её параметры.
- •Директивы препроцессора (прекомпилера).
- •Объявление указателей.
- •Модификатор const.
- •Операции.
- •Указатели на различные типы.
- •Указатель на void.
- •Применение указателей для передачи данных между функциями.
- •Массивы.
- •Индексация массивов.
- •Хранение массива в памяти. Адреса элементов. Хранение массива в памяти.
- •Массивы и константные указатели.
- •Статическое и динамическое выделение памяти.
- •Функции calloc, malloc, free
- •Функция realloc
- •Передача массивов в качестве аргументов функции.
- •Указатели на функции.
- •Библиотеки функций.
- •Функции форматированного ввода-вывода.
- •Функция printf().
- •%[Флаги] [Ширина] [.Точность] [{h | l | I | i32 | i64}]тип
- •Для чего нужен форматированный вывод.
- •Функция scanf().
- •Функции sprintf() и sscanf().
- •Функции fprintf() и fscanf().
- •Функции неформатированного ввода-вывода.
- •Работа со строковыми данными (стрингами). Представление строковых данных в языке c.
- •Функции работы со строками.
- •Потоковый ввод-вывод
- •Функции форматированного ввода-вывода.
- •Функция printf().
- •%[Флаги] [Ширина] [.Точность] [{h | l | I | i32 | i64}]тип
- •Для чего нужен форматированный вывод.
- •Функция scanf().
- •Функции sprintf() и sscanf().
- •Функции fprintf() и fscanf().
- •Функции неформатированного ввода-вывода.
- •Функции работы с файлами.
- •Потоковый ввод-вывод
- •Работа с потоками
- •Курсор.
- •Ввод-вывод отдельных символов и строк.
- •Форматированный ввод-вывод информации в файл.
- •Блочный потоковый ввод-вывод
- •Смена текущей позиции в файле. Проверка конца файла.
- •Функции доступа к файлам нижнего уровня.
- •Методы сортировки данных.
- •Введение
- •Сравнение методов сортировки
- •Программная реализация алгоритмов сортировки
- •Метод пузырька.
- •Метод обмена.
- •Метод вставки.
- •Метод Шелла.
- •Метод кучи (бинарной кучи).
- •Очередь
- •Линейный список
- •Физическое (машинное) представление линейных списков
- •Программные реализации структур данных. Стек. Реализация в виде массива.
- •Стек. Связанное представление.
- •Очереди. Реализация в виде массива.
- •Дерево. Связанное представление.
- •Рекурсивный вызов функций.
- •Структуры. Объединения. Перечисления.
- •Перечисление (enum).
- •Производные типы данных.
- •Структура (struct).
- •Побитовое описание полей структуры.
- •Объявление переменных, реализующих структуру.
- •Доступ к элементам структуры.
- •Объединение (union).
- •Вложенное описание структур и объединений.
- •Описание структур и объединений в виде пользовательского типа.
- •Передача структур и объединений в виде параметров функции.
- •Инициализация структур и объединений.
- •Выгода от использования структур
Программная реализация алгоритмов сортировки
Перейдем к описанию программной реализации различных алгоритмов сортировки массивов данных. При этом будем исходить из следующих условий:
Массив состоит из элементов произвольного типа, но постоянной длины;
Для сравнения двух элементов будем использовать функцию со следующим прототипом:
int fcmp(const int a, const int b, const void *base, const size_t width);
Здесь a и b – индексы элементов, подлежащих сравнению, base – указатель на сортируемый массив, width – длина элемента массива в байтах.
Для обмена содержимого двух элементов будем использовать функцию со следующим прототипом:
void elemswap(const int a, const int b, void *base, const size_t width);
Здесь a и b – индексы элементов, подлежащих обмену, base – указатель на сортируемый массив, width – длина элемента массива в байтах.
Метод пузырька.
Метод пузырька является наиболее простым методом сортировки. Идея его очень проста: перебираются все элементы массива (за исключением последнего), и каждый из них сравнивается с последующим элементом. Если предыдущий элемент больше последующего, эти два элемента меняются местами. После этого перебор элементов начинается сначала. Так повторяется до тех пор, пока при переборе элементов массива не будет совершено ни одного обмена элементов.
void bubble(void *base, size_t nelem, size_t width,int (*fcmp)(const int, const int, const void*, const size_t))
{
int i,sw;
do
{
sw = 0;
for (i = 0; i <= (int)nelem - 2; i++)
{
if (fcmp(i, i+1, base, width) > 0)
{
elemswap(i, i+1, base, width);
sw = 1;
}
}
} while (sw);
}
Метод обмена.
Метод обмена также является довольно простым методом. Суть его в следующем: перебираются все элементы массива. Для каждого из них перебираются все следующие за ним элементы. Из числа этих элементов выбирается наименьший. После этого текущий и найденный элементы меняются местами. Таким образом, все элементы до текущего отсортированы. Когда перебраны все элементы, сортировка завершена.
void exchange(void *base, size_t nelem, size_t width, int (*fcmp)(const int, const int, const void*, const size_t))
{
int j, i, min;
for (j = 0; j < (int)nelem; j++)
{
min = j;
for (i = j + 1; i < (int)nelem; i++)
{
if (fcmp(i, min, base, width) < 0)
{
min = i;
}
}
if (min > j)
{
elemswap(j, min, base, width);
}
}
}
Метод вставки.
Метод вставки похож на метод обмена. Как и в методе обмена, в методе вставки перебираются все элементы массива. Однако, на этот раз для каждого из них перебираются все предыдущие элементы. В ходе этого перебора определяется место, куда среди них следует поместить текущий элемент. После того, как это место определено, текущий элемент помещается туда. Как и в методе вставки, все элементы до текущего отсортированы. Когда перебраны все элементы, сортировка завершена.
Заметим, что в методе сортировки вставкой требуется функция сравнения, которая может сравнивать не только два элемента массива по заданным индексам, но и два произвольных элемента, не обязательно принадлежащих сортируемому массиву. Поэтому используется функция, в которую передаются два аргумента – указатели на сравниваемые элементы.
void insertion(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *))
{
int j, i;
void *tmp;
tmp=malloc(width);
for (j = 1; j < (int)nelem; j++)
{
memcpy(tmp, (char *)base + j*width, width);
for (i = j; i > 0; i--)
{
if (fcmp((char *)base + (i-1)*width, tmp) > 0)
{
memcpy((char *)base + i*width, (char *)base + (i-1)*width, width);
}
else
{
break;
}
}
memcpy((char *)base + i*width, tmp, width);
}
free(tmp);
}