
- •Содержание
- •1. Основные понятия и определения
- •1.1. Структура персональной ЭВМ
- •1.2. Размещение данных и программ в памяти ПЭВМ
- •1.3. Программные модули
- •1.4. Ошибки
- •1.5. Функциональная и модульная декомпозиции
- •1.6. Файловая система хранения информации
- •1.7. Операционная система
- •2. Понятие алгоритмов и способы их описания
- •2.1. Свойства алгоритмов
- •2.2. Способы описания алгоритмов
- •3. Базовые элементы языка Cи
- •3.1. Алфавит языка
- •3.2. Лексемы
- •3.3. Идентификаторы и ключевые слова
- •3.4. Знаки операций
- •3.5. Литералы (константы)
- •3.6. Комментарии
- •4. Базовые типы объектов
- •4.1. Простейшая программа
- •4.2. Основные типы данных
- •4.3. Декларация объектов
- •4.4. Данные целого типа (int)
- •4.5. Данные символьного типа (char)
- •4.6. Данные вещественного типа (float, double)
- •5. Константы в программах
- •5.1. Целочисленные константы
- •5.2. Константы вещественного типа
- •5.3. Символьные константы
- •5.4. Строковые константы
- •6. Обзор операций
- •6.1. Операции, выражения
- •6.2. Арифметические операции
- •6.3. Операции присваивания
- •6.4. Сокращенная запись операции присваивания
- •6.5. Преобразование типов операндов арифметических операций
- •6.6. Операция приведения типа
- •6.7. Операции сравнения
- •6.8. Логические операции
- •6.9. Побитовые логические операции, операции над битами
- •6.10. Операция «,» (запятая)
- •7. Обзор базовых инструкций языка Си
- •7.1. Стандартная библиотека языка Си
- •7.2. Стандартные математические функции
- •7.3. Функции вывода данных
- •7.4. Функции ввода информации
- •7.5. Ввод - вывод потоками
- •8. Синтаксис операторов языка Cи
- •8.1. Условные операторы
- •8.2. Условная операция «? :»
- •8.3. Оператор выбора альтернатив (переключатель)
- •9. Составление циклических алгоритмов
- •9.1. Понятие цикла
- •9.2. Оператор с предусловием while
- •9.3. Оператор цикла с постусловием do – while
- •9.4. Оператор цикла с предусловием и коррекцией for
- •10. Операторы передачи управления
- •10.1. Оператор безусловного перехода goto
- •10.2. Оператор continue
- •10.3. Оператор break
- •10.4. Оператор return
- •11.1. Операции над указателями (косвенная адресация)
- •11.2. Ссылка
- •12. Массивы
- •12.1. Одномерные массивы
- •12.2. Многомерные массивы
- •12.3. Операция sizeof
- •12.4. Применение указателей
- •12.5. Указатели на указатели
- •13. Работа с динамической памятью
- •13.1. Пример создания одномерного динамического массива
- •13.2. Пример создания двухмерного динамического массива
- •14. Строки в языке Си
- •14.1. Русификация под Visual
- •15. Функции пользователя
- •15.1. Декларация функции
- •15.2. Вызов функции
- •15.3. Операция typedef
- •15.4. Указатели на функции
- •16. Классы памяти и области действия объектов
- •16.1. Автоматические переменные
- •16.2. Внешние переменные
- •16.3. Область действия переменных
- •17. Структуры, объединения, перечисления
- •17.1. Структуры
- •17.2. Декларация структурного типа данных
- •17.3. Создание структурных переменных
- •17.4. Вложенные структуры
- •17.5. Массивы структур
- •17.6. Размещение структурных переменных в памяти
- •17.7. Объединения
- •17.8. Перечисления
- •18. Файлы в языке Си
- •18.1. Открытие файла
- •18.2. Закрытие файла
- •18.3. Запись – чтение информации
- •18.4. Текстовые файлы
- •18.5. Бинарные файлы
- •Литература
- •Приложение 1. Таблицы символов ASCII
- •Приложение 2. Операции языка Си
- •Приложение 3. Возможности препроцессора
- •1. Вид рабочего стола консольного приложения Visual C++
- •2. Создание нового проекта
- •3. Добавление к проекту файлов с исходным кодом
- •4. Компиляция, компоновка и выполнение проекта
- •5. Конфигурация проекта
- •6. Открытие существующего проекта
- •Приложение 5. Некоторые возможности отладчика Visual C++
- •1. Установка точки прерывания
- •2. Пошаговое выполнение программы
- •3. Проверка значений переменных во время выполнения программы
- •4. Окна Auto и Watch 1
- •5. Программные средства отладки
- •ЧАСТЬ 2
- •1. Системы счисления
- •1.1. Общие определения
- •1.2. Алгоритмы перевода из одной системы счисления в другую
- •2. Организация памяти и структуры данных
- •3. Линейные списки и рекурсия
- •4. Динамическая структура данных – СТЕК
- •5. Динамическая структура данных – ОЧЕРЕДЬ
- •6. Двунаправленный линейный список
- •7. Построение обратной польской записи
- •8. Нелинейные структуры данных
- •Пояснение к программе
- •9. Понятие хеширования
- •9.1. Хеш-функция и хеш-таблица
- •9.2. Схемы хеширования
- •10. Элементы теории погрешностей
- •10.1. Методы реализации математических моделей
- •10.2. Источники погрешностей
- •10.3. Приближенные числа и оценка их погрешностей
- •10.4. Прямая задача теории погрешностей
- •10.5. Обратная задача теории погрешностей
- •10.6. Понятия устойчивости, корректности и сходимости
- •11. Вычисление интегралов
- •11.1. Формулы численного интегрирования
- •11.2. Формула средних
- •11.3. Формула трапеций
- •11.4. Формула Симпсона
- •11.5. Схема с автоматическим выбором шага по заданной точности
- •12. Методы решения нелинейных уравнений
- •12.1. Итерационные методы уточнения корней
- •12.2. Метод Ньютона
- •12.3. Метод секущих
- •12.4. Метод Вегстейна
- •12.5. Метод парабол
- •12.6. Метод деления отрезка пополам
- •13. Решение систем линейных алгебраических уравнений
- •13.1. Прямые методы решения СЛАУ
- •13.2. Метод Гаусса
- •13.3. Метод прогонки
- •13.4. Метод квадратного корня
- •13.5. Итерационные методы решения СЛАУ
- •13.6. Метод простой итерации
- •14. Поиск и сортировка
- •14.1. Последовательный поиск в массиве
- •14.2. Барьерный последовательный поиск
- •14.3. Сортировка вставками (включениями)
- •14.4. Двоичный поиск
- •14.5. Сортировка выбором
- •14.6. Алгоритмы сортировки выбором
- •14.7. Сортировка обменом
- •14.8. Быстрая сортировка
- •15. Обработка статистических данных
все
все
конец цикла
После выполнения цикла номер элемента, равного .X хранится в переменной R. Если R=N-1, значит совпадения нет.
14.5. Сортировка выбором
Концепция упорядоченного множества элементов имеет существенное значение в разнообразных областях нашей жизни.
В общем, сортировку (упорядочение) следует понимать как процесс перегруппировки (перераспределения) заданного множества объектов в некотором определенном порядке. Основная цель сортировки – облегчить поиск элементов в таком упорядоченном множестве.
Мы встречаемся с упорядоченными объектами на складах, в телефонных справочниках, в библиотечных каталогах, в словарях, т.е. почти везде, где нужно осуществлять поиск в массивах объектов.
Задачу сортировки формулирую так. Пусть надо упорядочить N элементов
a1, a2, ... , an,
которые назовем объектами. Каждый объект ai имеет свой ключ kI, который и управляет процессом сортировки
Задача сортировки – найти такую перестановку объектов p(1)p(2)...р(n), после которой ключи объектов расположились бы например так:
Кр(1) ≤ Кр(2) ≤ ... ≤ Кр(n).
Порядок, при котором в массиве объектов первым элементом является объект с наименьшим ключом, а каждое следующее значение больше предыдущего, и наконец последнее – самое большое из данного массива называют возрастаю-
щим.
Примером задачи сортировки может служить следующая формулировка.
В массиве из N различных целых чисел осуществить их перестановку так, чтобы после перестановки в массиве первым элементом было самое большое число. Каждое следующее должно быть меньше предыдущего, и последнее – наименьшее из чисел массива. Такой порядок расположения чисел называют убы-
вающим.
Сортировка – хороший пример комплекса задач, которые решают при помощи большой совокупности разнообразных алгоритмов. Каждый из алгоритмов имеет и свои достоинства, и свои недостатки. Выбирать конкретный алгоритм рекомендуется исходя из конкретной постановки задачи.
Выбранный метод сортировки должен экономно использовать оперативную память компьютера. А это значит, что перестановки, приводящие элементы в требуемый порядок, должны выполняться по возможности на том же участке
200
памяти. Поэтому методы, в которых элементы из массива a пересылаются в результирующий массив b используют только в исключительных случаях.
Существенным критерием выбора конкретного метода сортировки из существующих является и его экономичность, т. е. время работы. Поэтому одним из критериев эффективности алгоритмов сортировки является число необходимых сравнений элементов.
Таким образом, основное требование к методам сортировки – экономное использование времени процессора и памяти. Например, хорошими алгоритмами считаются те, которые затрачивают на сортировку N объектов время порядка
N*log2(N).
При сортировке либо перемещаются сами объекты, либо создается вспомогательная таблица, которая описывает перестановку и обеспечивает доступ к объектам в соответствии с порядком их ключей.
Обычно сортировку подразделяют на два класса: внутреннюю, когда все объекты хранятся в оперативной памяти, и внешнюю, когда они там все не помещаются. Мы рассмотрим только внутреннюю сортировку.
Существующие методы сортировки обычно разбивают на три класса, в зависимости от лежащего в их основе приема:
а) сортировка выбором; б) сортировка обменами;
в) сортировка включениями (вставками).
Рассмотрим основные алгоритмы сортировки на примере целочисленного массива.
14.6. Алгоритмы сортировки выбором
Метод 1. Простой линейный выбор
Метод предполагает использование рабочего (дополнительного) массива, в который в конечном итоге помещается отсортированный массив. Количество просмотров определяется количеством элементов массива. Сортировка посредством простого линейного выбора сводится к следующему:
1.Найти наименьший (наибольший) элемент, переслать его в рабочий массив и заменить его в исходном массиве величиной, которая больше (меньше) любого реального элемента.
2.Повторить шаг 1. На этот раз будет выбран наименьший (наибольший) из оставшихся элементов.
3.Повторять шаг 1 до тех пор, пока не будут выбраны все N элементов. Программа, реализующая алгоритм простого линейного выбора может быть
следующей:
#include <iostream.h> #include <conio.h> #include <limits.h>
// Файл с декларацией max(min) целого: INT_MAX (INT_MIN)
201
void Sort_Lin(int *, int); void main(void)
{
int *a, n, i;
cout << " \n Input N: "; cin >> n;
a = new int [n]; // Захватываем память для основного массива cout << " \n Array ? "<<endl;
//Формируем исходный массив for ( i=0; i<n; i++)
{
cout<<"a["<<i<<"]="; cin >> a[i];
}
Sort_Lin ( a, n ); // Вызвали сортировку
//и распечатали отсортированный массив cout << " \n Sort Array : ";
for ( i=0; i<n; i++) cout << a[i] << " "; cout << endl;
delete [ ]a; getch();
}
//----Функция, реализующая простой линейный выбор ------
void Sort_Lin(int *a, int n)
{
int i, j, imn, amin, *p;
p = new int [n]; // Захватываем память для рабочего массива for ( j=0; j<n; j++) // Внешний цикл по j
{
for ( amin=INT_MAX, i=0; i<n; i++) // Внутренний цикл по i if ( a[i] < amin )
{
imin = i; amin = a[i];
}
p[j] = amin; // Найденный текущий min в рабочий массив
a[imin] = INT_MAX; // а на его место max_допустимое целое
}
for ( j=0; j<n; j++)
a[j] = p[j]; // Отсортированный массив на место исходного delete [ ]p;
}
В результате получим:
Input N: 5 Array ?
202
a[0]=4
a[1]=1
a[2]=8
a[3]=5
a[4]=3
Sort Array : 1 3 4 5 8 Press any key to continue
Здесь, внешний цикл по j осуществляет формирование рабочего отсортированного массива. последовательно укорачивая исходный массив записывая на место текущего максимально допустимое целочисленное значение INT_MAX., А внутренний цикл по i осуществляет поиск min (и определяет его порядковый номер imin) в текущей рабочей части массива, который будет максимальным по отношению к уже сформированной по возрастанию части рабочего массива.
После выхода из внешнего цикла все элементы исходного массива a имеют значение равное INT_MAX. Поэтому последний цикл переписывает отсортированные значения рабочего массива в исходный, после чего рабочий массив уничтожаем.
Метод 2. Линейный выбор с обменом (сортировка выбором)
Рабочий массив здесь не используется.
Рассмотрим принципы, на которых основан этот метод сортировки. Например, нужно отсортировать массив по убыванию.
1.Выбирается максимальный элемент.
2.Он меняется местами с первым элементом a[1]. На первом месте оказывается максимальный элемент.
3.Дальше рассматривается только не отсортированная часть массива, и этот процесс повторяется с оставшимися N-1, N-2 элементами и т. д. до тех пор, пока не останется один, наименьший элемент.
Рассмотрим работу данного метода на примере целочисленного массива a={0, 1, 9, 2, 4, 3, 6, 5}.
Максимальный элемент на текущем шаге подчеркиваем, а рабочую часть отделять вертикальной линией. Итак:
1)│ 0, 1, 9, 2, 4, 3, 6, 5 ─ выбрали, поменяли с первым (с 1-м)
2) |
9, │ 1, 0, 2, 4, 3, 6, 5 |
─ выбрали, поменяли с первым оставшейся части |
массива |
|
|
3) |
9, 6, │ 0, 2, 4, 3, 1, 5 |
─ и т.д |
4)9, 6, 5, │ 2, 4, 3, 1, 0
5)9, 6, 5, 4, │ 2, 3, 1, 0
6)9, 6, 5, 4, 3, 2, │ 1, 0
7)9, 6, 5, 4, 3, 2, 1, │ 0
8)9, 6, 5, 4, 3, 2, 1, 0
Подсчитаем количество сравнений, которые пришлось сделать для упорядочения массива.
203