- •Динамические структуры данных
- •Динамические структуры данных (язык Си)
- •Статические данные
- •Динамические данные
- •Указатели
- •Обращение к данным
- •Что надо знать об указателях
- •Динамические
- •Где нужны динамические массивы?
- •Программа
- •Динамические массивы
- •Ошибки при работе с памятью
- •Динамические структуры данных
- •Структуры
- •Как работать со структурами?
- •Копирование структур
- •Массивы структур
- •Пример программы
- •Выделение памяти под структуру
- •Динамические массивы структур
- •Сортировка массива структур
- •Динамические структуры данных (язык Си)
- •Динамические структуры данных
- •Когда нужны списки?
- •Списки: новые типы данных
- •Что нужно уметь делать со списком?
- •Создание узла
- •Добавление узла после заданного
- •Проход по списку
- •Добавление узла в конец списка
- •Поиск слова в списке
- •Удаление узла
- •Двусвязные списки
- •Динамические структуры данных
- •Стек
- •Пример задачи
- •Решение задачи со скобками
- •Реализация стека (массив)
- •Реализация стека (массив)
- •Реализация стека (список)
- •Реализация стека (список)
- •Очередь
- •Реализация очереди (массив)
- •Реализация очереди (кольцевой массив)
- •Реализация очереди (списки)
- •Реализация очереди (списки)
- •Реализация очереди (списки)
- •Динамические структуры данных (язык Си)
- •Деревья
- •Деревья
- •Деревья
- •Дерево – рекурсивная структура данных
- •Двоичные деревья
- •Двоичные деревья поиска
- •Двоичные деревья поиска
- •Обход дерева
- •Динамические структуры данных (язык Си)
- •Определения
- •Определения
- •Описание графа
- •Весовая матрица
- •Задача Прима-Краскала
- •Кратчайшие пути (алгоритм Дейкстры)
- •Задача коммивояжера
- •Другие классические задачи
Сортировка массива структур
Ключ (ключевое поле) – это поле, по которому сортируются структуры.
Проблема:
как избежать копирования структур при сортировке?
Решение:
использовать вспомогательный массив указателей, при сортировке переставлять указатели.
До |
p[0] |
p[1] |
p[2] |
p[3] |
p[4] |
|
|
|
|
|
|
сортировки: |
5 |
1 |
3 |
2 |
4 |
После |
p[4] |
p[0] |
p[2] |
p[1] |
p[3] |
|
|
|
|
|
|
сортировки: |
5 |
1 |
3 |
2 |
4 |
Вывод результата:
for ( i = 0; i < 5; i ++ )
printf("%d %s", p[i]->year, p[i]->title);
21
|
Реализация в программе |
|
||
const N = 10; |
|
|
||
Book B[N]; |
вспомогательные |
|
||
Book *p[N], |
указатели |
|
||
|
|
|||
*temp; |
|
|
||
... |
// здесь заполняем структуры |
|
||
for ( i = 0; i < N; i++ |
начальная расстановка |
|||
) |
|
указателей |
||
for ( i = 0; i < n-1; i++ ) |
|
|||
for ( j = n-2; j >= i; j-- ) |
|
|||
|
if ( p[j+1]->year < p[j]->year ) |
{ |
||
{ |
|
сортировка методом |
||
temp = p[j]; |
||||
пузырька, меняем только |
||||
p[j] = p[j+1]; |
||||
указатели, сами структуры |
||||
p[j+1] = temp; |
||||
остаются на местах |
||||
} |
|
|
|
|
printf("%d %s", p[i]->year, p[i]->title); |
Динамические структуры данных (язык Си)
Тема 4. Списки
Динамические структуры данных
Строение: набор узлов, объединенных с помощью ссылок.
Как устроен узел:
данные |
ссылки на |
|
другие узлы |
||
|
Типы структур: |
|
|
списки |
деревья |
графы |
односвязный |
|
|
NULL |
|
|
двунаправленный (двусвязный) |
|
|
NULLNULL NULL
циклические списки (кольца)
NULL |
NULL NULL |
|
NULL NULL
24
Когда нужны списки?
Задача (алфавитно-частотный словарь). В файле записан текст.
Нужно записать в другой файл в столбик все слова, встречающиеся в тексте, в алфавитном порядке, и количество повторений для каждого слова.
Проблемы:
1)количество слов заранее неизвестно
2)количество слов определяется только в конце работы Решение – список.
Алгоритм:
3)создать список;
4)если слова в файле закончились, то стоп.
5)прочитать слово и искать его в списке;
6)если слово найдено – увеличить счетчик повторений,
иначе добавить слово в список; |
25 |
7) перейти к шагу 2.
Списки: новые типы данных
Что такое список: |
! |
Рекурсивное |
1) пустая структура – это список; |
2)список – это начальный узел (голова) определение! и связанный с ним список.
Структура узла: |
NULL |
|
struct |
Node { |
|
|
char |
word[40]; |
// слово |
|
int |
count; |
// |
счетчик повторений |
Node |
*next; |
// |
ссылка на следующий элемент |
}; |
|
|
|
Указатель на эту структуру:
typedef Node *PNode; |
! |
Для доступа к |
Адрес начала списка: |
списку достаточно |
|
|
знать адрес его |
|
PNode Head = NULL; |
|
головы! |
26
Что нужно уметь делать со списком?
1.Создать новый узел.
2.Добавить узел:
a)в начало списка; b)в конец списка;
c)после заданного узла; d)до заданного узла.
3.Искать нужный узел в списке.
4.Удалить узел.
27
Создание узла
Функция CreateNode (создать узел): вход: новое слово, прочитанное из файла;
выход: адрес нового узла, созданного в памяти.
возвращает адрес |
новое слово |
созданного узла |
PNode CreateNode ( char NewWord[] )
{
PNode NewNode = new Node; strcpy(NewNode->word, NewWord);
NewNode->count = 1;
NewNode->next = NULL; return NewNode;
}
28
Добавление узла после заданного
1) Установить ссылку нового узла на узел, следующий за p:
NewNode |
|
|
|
|
|
|
NULL |
NewNode->next = p->next; |
|
|
|
||||||
|
|
|
|
|
|
p
NULL
2) Установить ссылку узла p на новый узел:
NewNode |
p->next = NewNode; |
|
p
NULL
void AddAfter (PNode p, PNode NewNode)
{
NewNode->next = p->next; p->next = NewNode;
}
29
Проход по списку
Задача:сделать что-нибудь с каждым элементом списка.
q
Head NULL
Алгоритм:
1)установить вспомогательный указатель q на голову списка;
2)если указатель q равен NULL (дошли до конца списка), то стоп;
3)выполнить действие над узлом с адресом q ;
4)перейти к следующему узлу, q->next.
... |
|
|
|
PNode |
q = Head; |
// |
начали с головы |
while |
( q != NULL ) { // |
пока не дошли до конца |
|
... |
|
// |
делаем что-то хорошее с q |
q = |
q->next; |
// |
переходим к следующему узлу |
} |
|
|
|
... |
|
|
|