Upload
mikhail-kurnosov
View
711
Download
2
Embed Size (px)
Citation preview
Лекция 3:
Бинарный поиск.
Связные списки.
Курносов Михаил Георгиевич
к.т.н. доцент Кафедры вычислительных систем
Сибирский государственный университет
телекоммуникаций и информатики
http://www.mkurnosov.net
Контроль
2
1. Что такое вычислительная сложность алгоритма?
2. O(3n3 + 1000n2) = …. ?
3. O(n2 + logn) = ….
4. O(nlogn + n2 ) = …. ?
5. O(2n + n6 – 1000n3) = …. ?
6. O(n6 + n!) = …. ?
7. Асимптотическая сложность пузырьковой сортировки в
среднем случае (average case).
8. Асимптотическая сложность пузырьковой сортировки в
худшем случае (worst case).
9. Вычислительная сложность алгоритмы быстрой
сортировки (QuickSort).
Поиск элемента в массиве (Search)
3
function Search(v[1:n], value)
for i = 1 to n do
if v[i] = value then
return i
end if
end for
return -1
end function
Вычислительная сложность линейного алгоритма поиска
элемента – O(n).
Можно ли ускорить алгоритм?
Бинарный поиск (Binary Search)
4
function BinarySearch(v[1:n], key)
l = 1
h = n
while l <= h do
mid = (l + h) / 2
if v[mid] = key then
return mid
else if key > v[mid] then
l = mid + 1
else
h = mid - 1
end if
end while
return -1
end function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
2 3 3 5 7 9 13 23 25 29 31 33 37 41 42 46 49 50 52 67 73 81 94
key = 100
Бинарный поиск (Binary Search)
5
function BinarySearch(v[1:n], key)
l = 1
h = n
while l <= h do
mid = (l + h) / 2
if v[mid] = key then
return mid
else if key > v[mid] then
l = mid + 1
else
h = mid - 1
end if
end while
return -1
end function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
2 3 3 5 7 9 13 23 25 29 31 33 37 41 42 46 49 50 52 67 73 81 94
key = 100
�
��, �
��, …,
�
��
� � = 1 – 1 итерация
� � = 23 – 5 итераций
� � = 32 – 6 итераций
�
��= 1, � = 2� ,
log�� = log� 2� = �
� � = � ���� � + �
� � = �(���� �)
Связные списки (Linked Lists)
6
Связный список (Linked list) – динамическая структура
данных для хранения информации
Операция Описание Вычислительная
сложность
Сложность
по памяти
AddFront(a, x) Добавляет элемент x
в начало списка a
O(1) O(1)
AddEnd(a, x) Добавляет элемент x
в конец списка a
O(n) O(1)
Get(a, i) Возвращает i-й
элемент списка a
O(n) O(1)
Set(a, i, x) Присваивает i-у элементу
списка a значение x
O(n) O(1)
Size(a) Возвращает количество
элементов в списке a
O(1) или O(n) O(1)
Односвязный список (Singly Linked List)
7
Данные Next Данные Next Данные Next Данные Next NULL
Head
� Размер списка заранее не известен – элементы добавляются
во время работы программы (динамически)
� Память под элементы выделяется динамически
(функции: malloc, calloc, free).
Односвязный список (Singly linked list)
8
#include <stdio.h>
#include <stdlib.h>
struct listnode {
char *data; /* Data */
int value; /* Data */
struct listnode *next; /* Next node */
};
Создание элемента (выделение памяти)
9
struct listnode *list_createnode(char *data,
int value)
{
struct listnode *p;
p = malloc(sizeof(*p));
if (p != NULL) {
p->data = data;
p->value = value;
p->next = NULL;
}
return p;
}Вычислительная сложность создания элемента
TCreateNode = O(1)
Создание элемента (выделение памяти)
10
int main()
{
struct listnode *node;
node = list_createnode(“Ivanov Ivan”, 178);
return 0;
}
data: “Ivanov Ivan”
value: 178
next: NULL
Добавление элемента в начало списка
11
NULL
head
Data
ValueNext
Data
ValueNext
NULL
head
Data
ValueNext
Data
ValueNext
Data
ValueNext
NULL
1. Создаем новый узел newnode в памяти
newnode
Добавление элемента в начало списка
12
NULL
head
Data
ValueNext
Data
ValueNext
NULL
head
Data
ValueNext
Data
ValueNext
Data
ValueNext
2. Устанавливаем указатель next узла newnode на head
newnode
Добавление элемента в начало списка
13
NULL
head
Data
ValueNext
Data
ValueNext
NULL
head
Data
ValueNext
Data
ValueNext
Data
ValueNext
3. Делаем головой списка узел newnode
newnode
Добавление элемента в начало списка
struct listnode *list_addfront(
struct listnode *list,
char *data, int value)
{
struct listnode *newnode;
newnode = list_createnode(data, value);
if (newnode != NULL) {
newnode->next = list;
return newnode;
}
return list;
}
14TAddFront = O(1)
Добавление элемента в начало списка
15
int main()
{
struct listnode *head;
head = list_addfront(NULL, "Ivanov Ivan",
178);
head = list_addfront(head, "Petrov Petr",
182);
return 0;
}
data: “Ivanov Ivan”
value: 178
next: NULL
data: “Petrov Petr”
value: 182
next: 0xdeadbeaf
Поиск элемента в списке (Lookup)
16
head
� Начиная с головы списка просматриваем все узлы
и сравниваем ключи
data: “Ivanov Ivan”
value: 178
next: 0x3434ff99
data: “Petrov Petr”
value: 182
next: 0xdeadbeaf
data: “Sidorov Lev”
value: 169
next: NULL
Поиск элемента в списке (Lookup)
17
struct listnode *list_lookup(
struct listnode *list,
char *data, int value)
{
for ( ; list != NULL; list = list->next) {
if (strcmp(list->data, data) == 0 &&
list->value == value)
{
return list;
}
}
return NULL;
} TLookup = Θ(n)
Поиск элемента в списке (Lookup)
18
int main()
{
struct listnode *node, *p;
node = list_addfront(NULL, "Ivanov Ivan", 178);
node = list_addfront(node, "Petrov Petr", 182);
node = list_addfront(node, “Sidorov Lev", 169);
p = list_lookup(node, "Ivanov Ivan", 178);
if (p != NULL) {
printf("Data: %s\n", p->data);
}
return 0;
}
Удаление элемента (Delete)
19
head
1. Находим элемент в списке
2. Корректируем указатели
3. Удаляем элемент из памяти
data: “Ivanov Ivan”
value: 178
next: 0x3434ff99
data: “Petrov Petr”
value: 182
next: 0xdeadbeaf
data: “Sidorov Lev”
value: 169
next: NULL
Три возможных ситуации:
a) удаляемый узел – в начале списка
b) удаляемый узел – внутри списка
c) удаляемый узел – в конце списка
Удаление элемента (Delete)
struct listnode *list_delete(struct listnode *list,
char *data, int value)
{
struct listnode *p, *prev = NULL;
for (p = list; p != NULL; p = p->next) {
if (strcmp(p->data, data) == 0
&& p->value == value)
{
if (prev == NULL)
list = p->next;
else
prev->next = p->next;
free(p);
return list;
}
prev = p;
}
return NULL;
}20TDelete = Θ(n)
Удаление элемента
21
int main()
{
struct listnode *node, *p;
node = list_addfront(NULL, "Ivanov Ivan", 178);
node = list_addfront(node, "Petrov Petr", 182);
node = list_addfront(node, “Sidorov Lev", 169);
p = list_delete(node, "Ivanov Ivan", 178);
if (p != NULL) {
printf("Deleted\n");
}
return 0;
}
Задание
22
� Познакомиться с алгоритмом поразрядной сортировки
(Radix Sort, Sedgewick2001, С.401-419).
� Прочитать о реализации связных списков в “практике
программирования” (Kernighan2011, С.61-66).