Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения - страница 29

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
TheXpert
17818
TheXpert  
Alexey Volchanskiy:

В MSDN его называют именно кольцевой буфер, я же не придумал название.

ссылку в студию

Alexey Navoykov:

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

могут быть проблемы с литералами

Alexey Volchanskiy
29835
Alexey Volchanskiy  
TheXpert:

ссылку в студию

могут быть проблемы с литералами

Лень снова искать ту статью, но я немного натянул. Кольцевой одно или двух-связанный лист строится на базе linked list, но в последнем элементе хранится ссылка на самый первый.

Alexey Navoykov
4412
Alexey Navoykov  
TheXpert:

могут быть проблемы с литералами

Да не, у меня класс "значений" наследуется от базового класса "ссылок", чисто как обёртка. Поэтому просто выбираем требуемую версию класса - и вперёд
Alexey Navoykov
4412
Alexey Navoykov  
Alexey Volchanskiy:

Кольцевой одно или двух-связанный лист строится на базе linked list, но в последнем элементе хранится ссылка на самый первый.

Так вот в том и дело, что строится "на базе", а не взамен.  Никто не мешал разработчикам и тут сделать это как дополнительный контейнер. А не подменять общепринятые понятия
Alexey Navoykov
4412
Alexey Navoykov  
Alexey Navoykov:

Скорее всего, тот кто портировал эти классы, решил просто облегчить себе жизнь, упростив код.  Вместо двух указателей m_first и m_last сделал один указатель m_head…

Посмотрел исходники dotnet, и понял причину.  Сам класс LinkedList портирован верно, там действительно только один указатель head, являющийся  одновременно и началом, и концом. Т.е. внутренняя реализация действительно является зацикленной.  А вот внешнее поведение - нет.  У MQ ошибка в классе CLinkedNode (методы Next и Previous).  Вот как выглядит их оригинальная реализация:

        public LinkedListNode<T>? Next
        {
            get { return next == null || next == list!.head ? null : next; }
        }

        public LinkedListNode<T>? Previous
        {
            get { return prev == null || this == list!.head ? null : prev; }
        }

А вот как портировано в MQL:

   CLinkedListNode<T>* Next(void)                      { return(m_next); }
   CLinkedListNode<T>* Previous(void)                  { return(m_prev); }

Возможно по невнимательности перепутали.

Но вообще я также немного удивлён насчёт реализации в dotnet.  Почему было не сделать два указателя в самом списке (first и last) вместо одного head. Это позволило бы избежать лишних проверок в вышеперечисленных методах узла списка, т.е. они бы выглядели в точности как сейчас у MQ, но при этом всё бы работало правильно.  Это конечно чуть замедлит процесс вставки/удаления узлов, но зато значительно ускорит итерацию по ним, что гораздо приоритетней.  Next и Previous вызываются несомненно чаще, чем добавляются узлы.   Я именно так себе и сделал,  думал что и у мелкомягких будет аналогично.  Ну да ладно )

Кстати, у MQ ещё один косяк в реализации CLinkedListNode и CRedBlackTreeNode.  Их поля m_next, m_prev и др. (кроме m_value)  предназначены для изменения исключительно самим классом списка.  Никто другой не должен менять их.  Поэтому в dotnet они являются internal полями. Пользователю доступны лишь get-методы.  А MQ зачем-то сделали публичные методы для изменения этих полей, причём ладно бы хоть назвали бы их как-нибудь специфично... но нет же, обычные названия:

void              Next(CLinkedListNode<T>*value)     { m_next=value; }
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий