Программирование. Принципы и практика использования C++ Исправленное издание, стр. 400
{ assert(lst); { struct Link* curr = lst–>first; while(curr) { struct Link* next = curr–>suc; free(curr); curr = next; } lst–>first = lst–>last = 0; }}Обратите внимание на способ, с помощью которого мы обходим список, используя член
sucLinkfree()nextListLinkfree()Если не все объекты структуры
Linkclear()Функция
destroy()create()deletevoid destroy(struct List* lst) /* удаляет все элементы списка lst; затем удаляет сам список lst */{ assert(lst); clear(lst); free(lst);}Обратите внимание на то, что перед вызовом функции очистки памяти (деструктора) мы не делаем никаких предположений об элементах, представленных в виде узлов списка. Эта схема не является полноценной имитацией методов языка С++ — она для этого не предназначена.
Функция
push_back()Linkvoid push_back(struct List* lst, struct Link* p) /* добавляет элемент p в конец списка lst */{ assert(lst); { struct Link* last = lst–>last; if (last) { last–>suc = p; /* добавляет узел p после узла last */ p–>pre = last; } else { lst–>first = p; /* p — первый элемент */ p–>pre = 0; } lst–>last = p; /* p — новый последний элемент */ p–>suc = 0; }}Весь этот код было бы трудно написать, не нарисовав схему, состоящую из нескольких прямоугольников и стрелок. Обратите внимание на то, что мы забыли рассмотреть вариант, в котором аргумент
pФункцию
erase()struct Link* erase(struct List* lst, struct Link* p)/* удаляет узел p из списка lst; возвращает указатель на узел, расположенный после узла p*/{ assert(lst); if (p==0) return 0; /* OK для вызова erase(0) */ if (p == lst–>first) { if (p–>suc) { lst–>first = p–>suc; /* последователь становится первым */ p–>suc–>pre = 0; return p–>suc; } else { lst–>first = lst–>last = 0; /* список становится пустым */ return 0; } } else if (p == lst–>last) { if (p–>pre) { lst–>last = p–>pre; /* предшественник становится последним */ p–>pre–>suc = 0; } else { lst–>first = lst–>last = 0; /* список становится пустым */ return 0; } } else { p–>suc–>pre = p–>pre; p–>pre–>suc = p–>suc; return p–>suc; }}Остальные функции читатели могут написать в качестве упражнения, поскольку для нашего (очень простого) теста они не нужны. Однако теперь мы должны разрешить основную загадку этого проекта: где находятся данные в элементах списка? Как реализовать простой список имен, представленных в виде С-строк. Рассмотрим следующий пример: