Шаг 50.
Изображение бинарного дерева (нерекурсивный алгоритм)

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

    Пусть бинарное дерево построено с помощью описанного на предыдущем шаге нерекурсивного алгоритма и определено указателем t.

    Нам понадобятся два стека, которые мы реализуем на базе однонаправленных списков. Тип звеньев стека опишем так:

    struct no
    {
      no *sled;   // Указатель на вершину.
      node *elem; // Информационное поле.
      int ch;     // Уровень вершины.
    }

    Изобразим схематично звено стека:


Рис.1. Звено стека

    Опишем используемые переменные:

    no *stk;  // Стек "левых" ссылок.
    no *stk1; // Стек "правых" ссылок.
    node *u;  // Указатель на структуру.

    Теперь приведем и сам алгоритм:

    stk = stk1 = NULL; // Первоначально оба стека пусты.
    n = 0;
    while (t!=NULL)
    {
      PushStack (&stk1,&t,&n);
      // Пока не достигнут лист дерева, в стек stk помещаются
      // левые ссылки тех структур, по которым перемещается
      // указатель t.
      if ((*t).Right!=NULL)
        { if ((*t).Left!=NULL) PushStack (&stk,&(*t).Left,&n); t = (*t).Right;}
      else {
        // Как только будет достигнут самый правый лист, проверяем левую 
        //ссылку. Если она существует, то из стека правых ссылок удаляем 
        //последний  адрес, и на печать выводим поле ключа этой вершины.
        if ((*t).Left!=NULL) 
        { if (stk1!=NULL) 
          { PopStack (&stk1,&u,&n); 
            for (i=0; i<=n; i++) cout<<" ";
              cout<<(*u).Key<<endl; } 
            t = (*t).Left; } 
        if (stk==NULL) t = NULL; 
        else {
          // Если у вершины дерева указатели на правое и 
          // левое поддеревья равны NULL, а стек левых 
          // указателей не пуст, то...
          while ((*stk).elem!=(*((*stk1).elem)).Left)
            { // Удаляется адрес из стека правых ссылок 
              //и на печать выводится значение поля ключа
              //вершины с данным адресом 
               PopStack (&stk1,&u,&n); 
               for (i=0; i<=n; i++) cout<<" ";
                 cout<<(*u).Key<<endl; } 
               // Как только выполнится условие
               //((*stk).elem==(*((*stk1).elem)).Left), удаля- 
               //ются адреса из обоих стеков, а поле ключа
               //также выводится на экран дисплея.
               PopStack (&stk1,&u,&n); 
               for (i=0; i<=n; i++) cout<<" ";
                 cout<<(*u).Key<<endl;
               PopStack (&stk,&t,&n); }
            }
           n = n + 1;
        }
    VyvodStack (&stk1);

    Оформим алгоритм в виде функции на языке C++:

void VyvodTree (node *t)
// Изображение дерева, заданного указателем t,
// на экране дисплея (нерекурсивный алгоритм).
{
  no *stk, *stk1;
  node *u;
  int i,n;
  stk = stk1 = NULL; n = 0;
  while (t!=NULL)
  { PushStack (&stk1,&t,&n); 
    if ((*t).Right!=NULL) 
    {    if ((*t).Left!=NULL) 
        PushStack (&stk,&((*t).Left),&n); 
        t = (*t).Right; } 
    else { 
      if ((*t).Left!=NULL) 
        { if (stk1!=NULL) 
          { PopStack (&stk1,&u,&n); 
             for (i=0; i<=n; i++) cout<<" ";
                 cout<<(*u).Key<<endl; }
             t = (*t).Left; } 
          else 
            if (stk==NULL) t = NULL; 
            else 
              { while ((*stk).elem!=(*((*stk1).elem)).Left)
                  { PopStack (&stk1,&u,&n); 
                     for (i=0; i<=n; i++) cout<<" ";
                       cout<<(*u).Key<<endl;
                  } 
                 PopStack (&stk1,&u,&n); 
                 for (i=0; i<=n; i++) cout<<" ";
                    cout<< (*u).Key<endl; 
                 PopStack (&stk,&t,&n); 
              } 
        } 
      n = n + 1;
    }
  VyvodStack (&stk1);
}

    На следующем шаге мы приведем пример построения и изображения бинарного дерева с помощью нерекурсивных алгоритмов.




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