Шаг 4.
Линейные однонаправленные списки. Удаление списка из памяти

    На этом шаге мы рассмотрим алгоритм удаления списка из памяти.

    Остановимся теперь на удалении однонаправленного линейного списка из динамической памяти.

    Алгоритм удаления можно сформулировать следующим образом:

    Приведем текст функции, реализующей указанный алгоритм.

void OCHISTKA (node **phead)
//Удаление однонаправленного списка из памяти. 
// *phead - указатель на заглавное звено списка.
{
  struct node *q,*q1; // Рабочие указатели.
  q = *phead;
  q1 = (*q).sled; // Указатель q1 "опережает" указатель q.
  while (q1!=NULL)
  { q = q1; q1 = (*q1).sled; delete q;}
  delete *phead; //Удаление заглавного звена.
}

    Отметим, что одной из распространенных ошибок при составлении программ является неаккуратное обращение с динамически распределяемой памятью, в частности, "забывание" освободить ее после использования, что в конце концов может привести к аварийному завершению программы из-за нехватки оперативной памяти. Поиск же мест "засорения" оперативной памяти в отлаживаемых программах, занимающих значительный объем, может занять много места, поскольку к моменту комплексной отладки, когда эти ошибки попадаются на глаза, естественным образом забываются многие детали создания программных компонентов. Поэтому целесообразно с самого начала отладки программ отслеживать процесс возврата динамической памяти в "кучу".

    Соберем рассмотренные функции в объектно-ориентированную программу.


    Пример. Построение однонаправленного списка с заглавным звеном и его просмотр.
#include<iostream.h>
class Spisok
{
  private:
    struct node
      {
        int elem; 
        node *sled;
      } *phead; //Указатель на начало списка.
  public: 
    Spisok() {phead = new (node); (*phead).sled=NULL;} //Конструктор.
    ~Spisok() { delete phead; } //Деструктор.
    void POSTROENIE (); 
    void VYVOD (); 
    void OCHISTKA ();
}; 

void main ()
{
  Spisok A;

  A.POSTROENIE ();
  A.VYVOD ();
  A.OCHISTKA ();
} 

void Spisok::POSTROENIE ()
//Построение однонаправленного списка с заглавным звеном.
// phead - указатель на заглавное звено списка. 
{
  node *t;
  int el;
  t = phead;
  cout<< "Вводите элементы списка: ";
  cin>>el;
  while (el!=0)
  { 
    (*t).sled = new (node); 
    t = (*t).sled; (*t).elem = el; (*t).sled = NULL; 
    cin>>el;
  }
} 

void Spisok::VYVOD ()
//Вывод содержимого однонаправленного линейного списка
//с заглавным звеном.
// phead - указатель на заглавное звено списка.
{
  node *t;
  t = (*phead).sled; 
  cout<<"Список: ";
  while (t!=NULL)
  { 
    cout<<(*t).elem<<" "; 
    t = (*t).sled;
  }
  cout<<endl;
} 

void Spisok::OCHISTKA ()
//Удаление однонаправленного списка из памяти.
// phead - указатель на заглавное звено списка.
{
  node *q,*q1;// Рабочие указатели.

  q = phead;
  q1 = (*q).sled; // Указатель q1 "опережает" указатель q.
  while (q1!=NULL)
  { q = q1; q1 = (*q1).sled; delete q;}
}
Текст этой программы можно взять здесь.

    Со следующего шага мы начнем рассматривать основные операции над списками с заглавным звеном.




Предыдущий шаг Содержание Следующий шаг