2009-04-20 5 views
1

Несомненно, некоторые из вас видели мою недавнюю публикацию, касающуюся одной и той же программы. У меня все время возникают проблемы. Повторяю: все еще учащиеся, не очень продвинутые, не очень хорошо понимают указатели, не беря класс, вообще не понимают концепции ООП и т. Д. Этот код просто объединяет два отсортированных вектора, farray и sarray, в один отсортированный вектор. По крайней мере, я надеюсь, что так оно и есть. Скажите мне:Является ли хорошей формой для сравнения с изменением значений в цикле в C++?

//int num is to find the size of the original vector and 
    //build up farray and sarray; not used in the merge process 
    int num = original.size() 
    std::vector<int> final; 

    std::vector<int>::iterator it = farray.begin(); 
    std::vector<int>::iterator iter = sarray.begin(); 

    //farray.size() == (0 thru (num/2)) 
    //sarray.size() == ((num/2) thru num) 
    for (;it != farray.end() && iter != sarray.end();) { 
     if (*it > *iter) { 
      final.push_back(*it); 
      it++; 
     }  
     else 
     { 
      final.push_back(*iter); 
      iter++; 
     } 

      if (it == farray.end()) { 
       for (int i = 0; iter < sarray.end(); i++) { 
        final.push_back(*iter); 
       } 
      } 

      if (iter == sarray.end()) { 
       for (int i = 0; it < farray.end(); i++) { 
        final.push_back(*iter); 
       } 
      } 
     } 

Я переписал часть слияния функции сортировки слияния, чтобы ... ну, заставьте ее работать. Я на самом деле есть несколько вопросов по поводу этого кода:

  1. ли это хорошая форма для сравнения с STD :: вектор :: итераторы это & & ITER за мои последние два, если заявления, если цикл может изменить их на своем следующем проходе ?
  2. Будут ли значения iter и it изменяться на последнем проходе этого цикла и испортить мой код? Помещает мои последние утверждения if перед сопоставлением * it и * iter?
  3. Выполняет ли функция-член end() последнее значение того, что его вызывает? Похоже, что он каким-то образом простирается.

EDIT: я отвечу на все ответы завтра, чтобы проверить, если вы хотите услышать больше. Прошло полночь. Спокойной ночи.

+1

Для циклов в ваших последних двух операциях if, кажется, сломаны - как написано, они просто будут продолжать увеличивать «i» навсегда. Я предполагаю, что вы имели в виду что-то вроде «for (; iter goldPseudo

+0

Вы правы, я просто привык к работе с массивами и стандартной системой итераций для них, которые я не думал об этом , – jkeys

ответ

3

1. Хорошо сравнивать итераторы, которые из одного и того же контейнера, как условие для цикла, но это имеет смысл только в том случае, если вы перемещаете те или иные итераторы в части приращения, если оператор цикла или в самом цикле цикла for. В этом цикле вы сравниваете iter против sarray.end(), но цикл for никогда не меняется iter. Это означает, что либо итераций не будет, либо цикл for никогда не завершится. Кроме того, вы, вероятно, хотите использовать !=, а не < для сравнения. == и != Работа для всех итераторов, < нет.

  for (int i = 0; iter != sarray.end(); i++) { 
       final.push_back(*iter); 
      } 

Как iter начинается там, где вы хотите, чтобы начать цикл, вы можете что-то вроде этого:

  for (; iter != sarray.end(); ++iter) { 
       final.push_back(*iter); 
      } 

Как вы все еще учимся (хотя не все мы!), Это, вероятно, поучительно работать с таким алгоритмом, но вы должны знать о std::merge, который, вероятно, делает то, что вы хотите.

std::merge(farray.begin(), farray.end(), sarray.begin(), sarray.end(), std::back_inserter(final)); 

(Вы должны #include <iterator> и <algorithm>.)

2. Я не вижу приращения iter или во внешнем цикле, который лишает логику более поздние для циклов, а именно точку в 1..

3. end() указывает на один конец контейнера, поэтому вы можете использовать его для проверки завершения цикла, но вы не должны пытаться разыменовать итератор, который является «==» на «.end()».

1

Некоторые общие рекомендации: вам нужно подумать об именах переменных. Вызов ваших итераторов «это» и «iter» в какой-то момент смутит вас. Собственно, если вы внимательно присмотритесь, это уже есть. Если «farray» и «sarray» являются значимыми именами, как насчет «fiter» и «siter».

Также подумайте, что делает сортировка слияния. Эти последние два блока предназначены только для «истощения» того, что осталось от итератора. Поэтому они не должны быть в первом цикле.

Я бы, наверное, написать как (псевдокод):

while not (list1.empty and list2.empty): 
    if list1.empty: 
     result.push(list2.pop) 
    else if list2.empty: 
     result.push(list1.pop) 
    else if list1.top > list2.top: 
     result.push(list2.pop) 
    else: 
     result.push(list1.pop) 

Или в несколько ржавых груза-culted C++:

std::vector<int>::iterator fiter = farray.begin(); 
std::vector<int>::iterator siter = sarray.begin(); 

while (fiter != farray.end() || siter != sarray.end()) { 
    if (fiter == farray.end())  final.push_back(*siter++); 
    else if (siter == sarray.end()) final.push_back(*fiter++); 
    else if (*fiter > *siter)  final.push_back(*siter++); 
    else       final.push_back(*siter++); 
} 
3

Я не проверял выполнение своего алгоритма, я буду просто обратитесь к трем вопросам:

  1. Итераторы очень похожи на указатели на значения контейнера. Это похоже на использование size_t i, а затем ++ i в цикле for. вы считали бы проблематичным сравнивать farray [i] с sarray [i]? вероятно, нет, поэтому все в порядке.
  2. Что я вижу в вашем коде здесь, так это то, что вы просто читаете значения * it и * iter, вы их на самом деле не меняете, поэтому они не изменятся.
  3. Конец() указывает на недопустимое место. Он не указывает на последнее значение, а на «после него». Это похоже на «NULL», если вы это сделаете, поэтому если (iter == sarray.end()) истинно, вы столкнетесь, если будете писать * iter, потому что вы не можете разыменовать итератор, равный end().
0

У вас есть о чем подумать.

Во-первых, если вы сходите на два диапазона, вам будет намного лучше использовать функцию std::merge, а не сворачивать самостоятельно.

Ваш код немного трудно читать, потому что вы используете разные стили для отступов и где вы находитесь в своих фигурных скобках. Выберите стиль & придерживайтесь его.

Первая часть вашего цикла, кажется, правильное осуществление слияния:

for (;it != farray.end() && iter != sarray.end();) { 
    if (*it > *iter) { 
     final.push_back(*it); 
     it++; 
    }  
    else 
    { 
     final.push_back(*iter); 
     iter++; 
    } 

... и это должно быть все, что вам нужно, чтобы получить работу.

Вторая часть вашего цикла имеет несколько проблем:

for (;it != farray.end() && iter != sarray.end();) { 
     : : 
      if (it == farray.end()) { 
       for (int i = 0; iter < sarray.end(); i++) { 
        final.push_back(*iter); 
       } 
      } 

      if (iter == sarray.end()) { 
       for (int i = 0; it < farray.end(); i++) { 
        final.push_back(*iter); 
       } 
      } 
     } 

За одно, для() условных написано так, что оба it и iter не должно указывать на end() их соответствующей коллекции, или петля заканчивается. Таким образом, it никогда не может указывать на sarray.end(), iter никогда не может указывать на farray.end(), и ни одно из них не может быть объявлено как if. Они оба являются мертвым (недостижимым) кодом.

Но даже если они не были мертвым кодом, у них есть ошибки. Условное значение в for(...) прерывает цикл, когда итератор указывает на конец коллекции, но этот итератор никогда не перемещается, поэтому у вас есть бесконечный цикл.

Снова оба этих for(...) s являются неизмененными мертвым кодом, потому что итераторы никогда не могут указывать на конец вектора.

+0

Не могу ли я просто вычесть 1 из каждого оператора if? if (it == farray.end() - 1), например. Есть ли какая-то причина, которая была бы плохой? – jkeys

+0

Записан: Что вы пытаетесь достичь? –

+0

Ну, я хочу выбросить все ценности дальнего и саррейского. Если я попаду в конец одного, потому что все они являются более низким значением другого, мне нужно будет добавить остальные значения выше в final. Я просто хочу, чтобы цикл прошел от первого отсортированного числа последнего отсортированного массива до последнего числа последнего отсортированного массива. – jkeys

0

Один простой комментарий: почему бы не использовать while (condition) вместо for(; !condition;).

Последнее строительство нестандартно и трудно понять!

+0

Я не согласен. Мне не трудно читать вообще, и для меня это более стандартно, чем использование while(). –