Кресты / Говнокод #8426 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
template<class fwd, class Predicat>
fwd findLast(fwd one, fwd last, Predicat P)
{
          if (one == last) return one;
          fwd s = one;
          fwd tt = ++s;
          for ( ; s!=last; )
          { 
               s = find_if(s, last, P);
               if (s != last) { tt=++s;  }
          }
          return tt;
}

Функция для поиска последнего вхождения элемента в контейнере STL с помощью алгоритма find_if.

Запостил: Stanislaw374 Stanislaw374, (Updated )

Комментарии (79) RSS

    • Судя по всему, это — однонаправленный итератор. Так что код не говно. Только ищет он не последнее вхождение, а итератор сразу за последним вхождением.
      Ответить
          • подловил
            тем не менее, даже для такого "популярного" forward_list функция написана безобразно
            Ответить
            • А как иначе? Код идеальный, ничего не изменишь без ухудшения.
              Ответить
              • даже если предположить, что автор реально хотел возвращать элемент, следующий за искомым (последним в контейнере, удовлетворяющим предикату), возвращать второй элемент контейнера, если ничего не нашли - бред
                но я, пожалуй, поверю тому, кто запостил говнокод, и его описанию, что на самом деле должен был делать код - найти последний удовлетворяющий элемент в контейнере
                кодер, наверное, хотел писать s++, это бы имело как раз больше смысла (кроме начала, конечно, там что ++s, что s++ бред)
                идеальный код - использовать файд_иф и реверс_итератор везде, где это возможно, и конкретно для форвард_листа (ну или в той говноархитектуре, где хочется именно искать с начала в любом контейнере) пользоваться
                template <class FwdIter, class Pred>
                FwdIter find_last_fwd(FwdIter first, FwdIter last, Pred pred)
                {
                	FwdIter found = last;
                	while (first != last) {
                		if (pred(*first))
                			found = first;
                		++first;
                	}
                	return found;
                }
                Ответить
                • Этот код не тождественен исходному. Если автор имел в виду именно то, что написал (а иначе трудно объяснить tt = ++s), то ни прибавить, ни отнять (ну разве что от локальной переменной избавиться, итерируя по параметру, но это придирки).
                  Ответить
                  • если нужно следующий после требуемого - код должен быть еще проще
                    while (first != last)
                    	if (pred(*first++))
                    		found = first;

                    вот ведь упёртый дед
                    Ответить
                    • Постфиксный инкремент менее эффективен. И как же киллер-фича — возврат второго элемента, если ничего не найдено?
                      Ответить
              • 1)std::forward_list не нужен. Ошибка проектирования.
                >Код идеальный, ничего не изменишь без ухудшения.
                2) Превратить О(n) в О(n^2) - это идеально.
                http://ideone.com/c5nS3
                Вывод:
                Код говно, автор мудак.
                Ответить
                • Да, так не нужен, что его наконец-то легализировали в новом стандарте. Между прочим, самая популярная структура в достандартном C++, C и многих других языках (не говоря уж о Lisp).
                  Ответить
                    • У Лиспа с однонаправленными списками особые отношения.
                      Ответить
                  • >Между прочим, самая популярная структура в достандартном C++
                    Это преждевременная оптимизация. То, к чему она привела можно увидеть на примере данного говнокода. Ещё и лишние тормоза получили из-за неумения писать код для односвязанного списка. Сначала нужно было std::list юзать, а когда закончил писать блок проги и слезно понадобилась оптимизация по объему памяти, то можно переходить на std::forward_list.
                    Преждевременная оптимизация root of all evil.
                    Ответить
                      • да, у find_if сложность О(n) и у цикла представленного в данном говнокоде тоже сложность О(n). Так что у обоих О(n). Но в данном ГК они вложены друг в друга и получается О(n^2). Такая простая математика. Никакого матана.
                        Ответить
                        • это фейл, они не вложены друг в друга, они вместе образуют цепочку действий, позволяющих тупо пройти контейнер за n шагов
                          Ответить
                          • ты вообще отличаешь
                            for (...)
                            { 
                                     s = find_if(s, last, P);
                                      ...
                            }
                            от не вложенной цепочки действий
                            for (...)
                            { 
                                      ...
                            };
                             s = find_if(s, last, P);
                            ?
                            Ответить
                            • ты вообще понимаешь, что после вызова find_if текущему итератору контейнера s присваивается то, что найдет find_if
                              ты сегодня фейлишься больше обычного, сосредоточься!
                              Ответить
                            • Он прав, действия не вложены, они образуют цепочку.
                              Это видно хотя бы по тому, что итератор прогоняется вдоль цикла только один раз. Внутренний прогон учитывается во внешнем.
                              Ответить
                            • Он же не от начала ищет, а со смещением. Линейная сложность. я тоже после праздников не в себе
                              Ответить
    • возвращает следующий элемент после последнего вхождения требуемого в контейнере, либо если ни одного не нашел, то второй, очевидно же
      Ответить
      • А, понял.
        Да, забавно, искать последний элемент, ищя с начала.
        Ответить
          • Зачем заводить односвязный список в задачах, где надо искать последний элемент?
            Ответить
            • Может когда заводили, не собирались искать последний. Или эта операция так редка, что пусть.

              А так — экономия памяти (до двух раз), быстрее модификация (раза в два).
              Ответить
            • >Зачем заводить односвязный список в задачах, где надо искать последний элемент?
              Вполне возможно, что в данной задаче этот самый последний элемент, но равный заданному, с большой вероятностью (это особенность конкретной задачи) лежит ближе к началу списка. Искать с конца в таком случае не имеет смысла. Поэтому можно применять односвязанный список. Если применять тот алгоритм, что работает за О(n) (а не тот, что в ГК за О(n^2)), то при учитывании данной особенности задачи (то условие, что последний равный элемент скорее всего лежит намного ближе к началу, чем к концу). То сложность данной задачи очень часто может вырождаться до сложности О(с) при c намного меньше n. Это будет намного эффективней применения традиционного std::list с реверсированными итераторами для данной конкретной задачи.
              Ответить
              • хуясе теоретик
                как это ты сможешь остановиться на 10-м элементе в контейнере из 100, считая что этот элемент - действительно последний в контейнере
                ты же не проверял остальные 90
                Ответить
                  • По крайней мере, моё предложение можно использовать для префетча в многопроцессорных системах. Но это, конечно, очень узкоспецифичная задача получается...
                    Ответить
                  • Хуйню опасно долго морозить, потому что тогда она отморозится и отвалится.
                    Ответить

Добавить комментарий

Из-за тебя ушел bormand, guest!

    А не использовать ли нам bbcode?


    8