Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ЭУМКД КИТ-ч1-Бутов.docx
Скачиваний:
9
Добавлен:
05.05.2019
Размер:
262.85 Кб
Скачать

Линейные списки

Самый простой способ связать множество узлов - сделать так, чтобы каждый узел содержал ссылку на следующий. Такой список называется однонаправленным (односвязным). Если добавить в каждый узел вторую ссылку - на предыдущий узел, получится двунаправленный список (двусвязный), если последний узел связать указателем с первым, получится кольцевой список.

Каждый узел списка содержит ключ, идентифицирующий этот узел. В качестве ключа в процессе работы со списком могут выступать те или иные поля данных или части поля данных если оно составного типа. Например, если создается линейный список из записей, содержащих данные о сотрудниках, то в качестве ключа может использоваться фамилия или год рождения или стаж работы и т.п.

Над списками можно выполнять следующие операции:

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;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]