- •Часть 1
- •Общие сведения Сведения об эумк
- •Методические рекомендации по изучению дисциплины
- •Рабочая учебная программа
- •Часть 2 184
- •Пояснительная записка
- •Содержание дисциплины
- •Индивидуальные практические работы, их характеристика
- •Контрольные работы, их характеристика
- •Литература
- •Основная
- •Дополнительная
- •Перечень компьютерных программ, наглядных и других пособий, методических указаний и материалов и технических средств обучения
- •Учебно-методические пособия
- •Алфавит языка
- •Лексемы
- •Идентификаторы
- •Ключевые слова
- •Знаки операций
- •Константы
- •Комментарии
- •Тема 2. Типы данных Концепция типа данных.
- •Простые типы данных
- •Целый тип int
- •Символьный тип char
- •Типы с плавающей точкой: float, double, long double
- •Тема 3. Выражения
- •Переменные
- •Именованные константы
- •Операции
- •Операции присваивания
- •Инкремент и декремент
- •Унарный плюс и унарный минус (строка 2)
- •Явное преобразование типа
- •Операция определения размера sizeof
- •Деление и остаток от деления
- •Логические операции не, и, или (!, &&, ||)
- •Условная операция (?:)
- •Операция запятая (,)
- •Операции взятия адреса и разадресации
- •Тема 4. Операторы
- •Структура программы
- •Тема 5. Базовые конструкции структурного программирования
- •Операторы ветвления
- •1. Условный оператор if
- •2. Оператор switch
- •Операторы цикла
- •1. Цикл с предусловием while
- •2. Цикл с постусловием do-while
- •3. Цикл с параметром for
- •Тема 6. Массивы
- •Тема 7. Указатели и массивы
- •Тема 8. Строки символов
- •Тема 9. Структуры
- •Массивы структур
- •Битовые поля
- •Объединения
- •Перечисления
- •Тема 10. Функции
- •Глобальные, локальные и статические переменные
- •Параметры функции
- •Передача массивов в качестве параметров функции
- •Функция main, ее параметры
- •Функции стандартной библиотеки
- •Функции форматного вывода и ввода printf и scanf
- •Тема 11. Файлы
- •Тема 12. Работа с динамической памятью
- •Тема 13. Динамические структуры данных
- •Очереди
- •Линейные списки
- •Бинарные деревья
- •Практический раздел Общие указания Указания по выбору варианта
- •Порядок оформление итогового отчета
- •Индивидуальные практические работы Индивидуальная практическая работа 1 Методические указания
- •Варианты заданий.
- •Индивидуальная практическая работа 2 Методические указания
- •Варианты заданий
- •Контрольные работы Контрольная работа 1 Методические указания
- •Варианты заданий
- •Контрольная работа 2 Методические указания
- •Варианты заданий
Линейные списки
Самый простой способ связать множество узлов - сделать так, чтобы каждый узел содержал ссылку на следующий. Такой список называется однонаправленным (односвязным). Если добавить в каждый узел вторую ссылку - на предыдущий узел, получится двунаправленный список (двусвязный), если последний узел связать указателем с первым, получится кольцевой список.
Каждый узел списка содержит ключ, идентифицирующий этот узел. В качестве ключа в процессе работы со списком могут выступать те или иные поля данных или части поля данных если оно составного типа. Например, если создается линейный список из записей, содержащих данные о сотрудниках, то в качестве ключа может использоваться фамилия или год рождения или стаж работы и т.п.
Над списками можно выполнять следующие операции:
1) формирование первого узла списка;
2) добавление нового узла в конец списка;
3) поиск узла по ключу;
4) вставка нового узла в определенное место списка (после узла с заданным ключем);
5) удаление узла с заданным ключем;
6) вставка нового узла с упорядочением по ключу.
Рассмотрим простейший односвязный список, предназначеный для хранения целых чисел. Описание узла списка:
struct node
{
int data; //поле данных
node *next; //поле указателя на следующий узел
};
Для работы со списком будем использовать два указателя: на начало списка (begin) и на его конец (end):
node *begin, *end;
Теперь определим функции, реализующие указанные выше операции над списком.
1. Формирование первого узла списка
void first(int d)
{
node *pv = new node; //выделяем динамическую память под первый узел
pv->data = d; //заполняем поле данных
pv->next = NULL; //заполняем поле указателя на следующий узел
begin = pv; //инициализируем указатель на начало списка
end = pv; //инициализируем указатель на конец списка
}
2. Добавление нового узла в конец списка
void add(int d)
{
node *pv = new node; //выделяем динамическую память под новый узел
pv->data = d; //заполняем поле данных
pv->next = NULL; //заполняем поле указателя на следующий узел
end->next = pv; //указываем ссылку на новый узел
end = pv; //корректируем указатель на конец списка
}
3. Поиск узла по ключу
node *find(int key) //функция возвращает указатель на искомый узел
{
node *pt = begin; //определяем и инициализируем указатель на node
while (pt != NULL)
{
if (pt->data == key)
break; //нашли узел с нужным ключем и выходим из цикла
pt = pt->next; //переходим к следующему узлу списка
}
return pt;
}
4. Вставка нового узла в определенное место списка
void insert(int key, int d)
{
node *pkey; //определяем указатель на node
pkey = find(key); //ищем узел по заданному ключу
if (pkey != NULL)
{
//узел с заданным ключем найден
node *pv = new node; //выделяем динамическую память под новый узел
pv->data = d; //заполняем поле данных
pv->next = pkey->next; //устанавливаем связь нового узла с последующим
pkey->next = pv; //устанавливаем связь предыдущего узла с новым
if (pkey == end)
end = pv; //корректируем указатель на конец списка
}
}
5. Удаление узла с заданным ключем
int remove(int key)
{
node *pkey; //определяем указатель на node
pkey = find(key); //ищем узел по заданному ключу
if (pkey != NULL)
{
//узел с заданным ключем найден
if (pkey == begin)
{
begin = begin->next; //корректируем указатель на начало списка
if (pkey == end)
end = NULL; //корректируем указатель на конец списка
}
else
{
//поиск узла, предшествующего удаляемому
node *prev = begin; //определяем и инициализируем указатель на node
while (prev != NULL)
{
if (prev->next == pkey)
break; //нашли предшествующий узел и выходим из цикла
prev = prev->next; //переходим к следующему узлу списка
}
if (pkey == end)
{
prev->next = NULL;
end = prev; //корректируем указатель на конец списка
}
else
prev->next = pkey->next;
}
delete pkey; //освобождаем память из-под удаленного узла
return 1; //удаление выполнено успешно
}
return 0; //удаление не выполнено (нет узла с указанным ключом)
}
6. Вставка нового узла с упорядочением по ключу (предполагается, что первый узел существует)
void add_sort(int d)
{
node *pv = new node; //выделяем динамическую память под новый узел
pv->data = d; //заполняем поле данных
node *pt = begin, *prev = begin; //определяем и инициализируем указатели на node
while (pt != NULL)
{
if (pt->data > d)
{
//поместить новый узел перед текущим узлом (pt)
pv->next = pt;
if (pt == begin)
begin = pv; //корректируем указатель на начало списка
else
prev->next = pv; //помещаем в середину списка
return; //здесь может быть выход из функции
}
prev = pt;
pt = pt->next;
}
//поместить новый узел в конец списка
pv->next = NULL;
end->next = pv;
end = pv; //корректируем указатель на конец списка
}
Пример работы со списком.
int main()
{
//С о з д а н и е н е у п о р я д о ч е н н о г о с п и с к а
//формирование первого узла списка с ключом 10
first(10);
//добавление в конец списка четырех узлов с ключами 20,30,40 и 50
for (int i=20; i<60; i+=10)
add(i);
//вставка узла с ключом 200 после узла с ключом 20
insert(20, 200);
//вставка узла с ключом 400 после узла с ключом 40
insert(40, 400);
//удаление узла с ключом 40
if (!remove(40)) //эквивалентно if (remote(40) == 0)
puts("Remove --> not found");
//добавление в конец списка узла с ключом 500
add(500);
//вывод списка на экран
puts("Unordered spisok:");
node *pt = begin;
while (pt != NULL)
{
printf("Key = %d\n", pt->data);
pt = pt->next;
}
//С о з д а н и е у п о р я д о ч е н н о г о с п и с к а
//очистка списка (удаление из списка всех узлов)
while (begin != NULL)
remove(begin->data);
//формирование первого узла списка с ключом 20000
first(20000);
//добавление в список девяти узлов со случайными ключами
for (i=0; i<9; ++i)
add_sort(rand()); //функция rand генерирует случайное число
//вывод списка на экран
puts("\nOrdered spisok:");
pt = begin;
while (pt != NULL)
{
printf("Key = %d\n", pt->data);
pt = pt->next;
}
return 0;
}