Олександр Ненько. Домашні сторінки
Головна сторінка Книга Федан Софтварь Фото про все Савченки 2016/10 Савченки 2016/01 Миколаїв 2015 Галявина 15° Особисті фото Різні приколи Турція 2020 Єгипет 2015 Турція 2013 Кріт 2012 Єгипет 2012 Єгипет 2011 Турція 2004 Данія 2007 Галина Аліна Ненько Вова Ненько Home: [ EN | UK | RU] Contact me: alex.nenko@gmail.com CC: nenko@nenko.net |
Bidirectional linked list - реалізація на мові програмування CНа протязі більше 15 років я використовував дуже простий і ефективний код для роботи з двунаправленим списком. Такий список може стати в пригоді на проектах, написаних на C, а такі проекти час від часу продовжують зустрічатися. Можу Вас запевнити, що будуть зустрічатися і в майбутньому.Основна функціональність роботи зі списком:
Ось ці рядки: #define AN_LIST_Init(x) {(x)->next=(x)->prev=(x); } #define AN_LIST_IsEmpty(x) ((x)->next==(x) ) #define AN_LIST_Insert(x,y) {((y)->next=(x)->next)->prev=(y);\ ((x)->next=(y))->prev=(x); } #define AN_LIST_InsertB4(x,y) {((y)->prev=(x)->prev)->next=(y);\ ((x)->prev=(y))->next=(x); } #define AN_LIST_Exclude(x) {((x)->prev)->next=(x)->next;\ ((x)->next)->prev=(x)->prev;}Припускаю, що в цей момент читач думає "якась дичина" (дуже просто, щоб бути правдою). Але якщо стало цікаво, що це за дичина, читаймо далі. Щоб пояснити основну ідею такої реалізації списку, я пропоную згадати класичну будову списку, і наведу код вставки елемента в класичний список. . Доступ до такого списку здійснюється через голову списку, яка зазвичай є вказівником на перший елемент списку. Голова списку дорівнює NULL для пустого списку. Кінець списку позначається нульовим 'next' вказівником. Вказівник 'prev' першого элементу також зазвичай нульовий. Розглянемо вставку елемента 'elem' в список після елемента 'cur'. void classic_list_insert_after( struct ELEM * cur, struct ELEM * elem) { if( cur == NULL) /* insert at the head of list */ { elem->next = head; elem->prev = NULL; head = elem; } else { elem->next = cur->next; elem->prev = cur; cur->next = elem; } if( elem->next != NULL) elem->next->prev = elem; }Зверніть увагу на кольори в тексті програмного коду. Фактично, тільки сині рядки коду виконують вставку. Весь інший код відмічений червоним, обробляє особливі випадки - коли щось дорівнює NULL - в голові чи в хвості списку. При спробі написати код для видалення елемента видно ту ж саму проблему - тільки 2-4 рядки коду переміщують вказівники, весь інший "роспухший" код обробляє спеціальні випадки - видалення першого або останнього елементу. Принципіальна ідея запропонованої реалізації - "ні NULL вказівникам". Це ускладнює блок-схему списку, але кардинально спрощує програмний код. . Таким чином, в якості голови списку ми замість вказівника на перший елемент використовуємо фіктивний елемент. В результаті голова пустого списку не містить нульових вказівників, всі вказівники вказують на голову списку ! . Замість класичної перевірки, чи список є пустим if (head == NULL)буде інша перевірка, більш складна, але їх 3 рівнозначних! if (head->next == head)або if (head->prev == head)або if (head->next == head->prev) Цікаво, що на блок-схемах (діаграмах) така реалізація списку виглядає більш складною, чим реалізація з нульовими вказівниками. Але при кодуванні такої реалізації на мові програмування вона виявляється гранично лаконічною та природною. Тобто існує концептуальна різниця між нашим сприйняттям (читай алгоритмами нашого мозку), і класичними мовами програмування ;) Відсутність умовного розгалуження в алгоритмі дає надію на дуже ефективне виконання на сучасних процесорах із конвеєром команд. Нарешті, реалізація настільки проста, що не потребує окремого модуля компіляції, інлайн код або препроцесорні директиви є достатніми. Мій хедер файл, який я використовую більше десятиліття, можна завантажити тут - an-list.h . Подана реалізація списку є інтрузивною, згідно з класифікацією Страуструпа (Bjarne Stroustrup), див. його знамениту книгу The C++ Programming Language відносно intrusive и nonintrusive реалізацій контейнерів. |
Terms and Conditions (c) 2005, 2006, 2008, 2009, 2011, 2012, ..., 2023 NAN |