문제

의심 할 여지없이 여러분 중 일부는 동일한 프로그램과 관련하여 최근 게시물을 보았습니다. 나는 그것으로 계속 문제를 일으킨다. 반복하려면 : 여전히 학습, 매우 진보되지 않고, 수업을 듣지 않고, OOP 개념을 전혀 이해하지 못하는 포인터를 잘 이해하지 못합니다. 벡터. 적어도, 나는 그것이 그것이하는 일이기를 바랍니다. 말해 주세요:

    //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 :: vector :: iterators it && iter for loop이 다음 패스에서 그들을 변경할 수있는 경우 마지막 두 If 문에 대해 비교하는 것이 좋은 형태입니까?
  2. 이 루프의 마지막 패스에서 ITER 값과 IT 값이 변경되고 내 코드를 망칠까요? *IT 및 *ITER 비교 전에 마지막 if 진술을 넣을 수 있습니까?
  3. end () 멤버 함수는 그것을 부르는 것의 마지막 값을 나타 냅니까? 어떻게 든 지나가는 것처럼 보입니다.

편집 : 내일 모든 답변에 응답하겠습니다. 더 많이 듣고 싶다면 다시 확인하십시오. 자정이 지나서야. G'night.

도움이 되었습니까?

해결책

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. 루프를 위해 외부에서 반복을 늘리는 것은 나중에 루프의 논리를 무효화하는 것을 보지 못합니다.

3 . end() 컨테이너의 끝을 지나치게 지적하므로 루프 종료 점검에 사용할 수 있지만 반복자를 해석하지 않아야합니다. "==" 에게 ".end()".

다른 팁

알고리즘의 구현을 확인하지 않았습니다. 세 가지 질문 만 참조하겠습니다.

  1. 반복자는 컨테이너 값에 대한 포인터와 매우 유사합니다. for 루프에서 size_t i와 ++ i를 사용하는 것과 똑같습니다. Farray [i]를 Sarray [i]와 비교하는 것이 문제가 있다고 생각하십니까? 아마도 그렇지 않을 것입니다. 괜찮습니다.
  2. 여기서 코드에서 당신이하는 것은 *그것의 값과 *iter의 값을 읽는 것입니다. 실제로 변경하지 않으므로 변경하지 않습니다.
  3. End ()는 유효하지 않은 장소를 가리 킵니다. 그것은 마지막 값을 가리키지 않고 "이후"를 가리 킵니다. (iter == sarray.end ())이 사실이면 "널"과 같습니다. end ()와 동일한 반복자를 대상으로 할 수 없기 때문에 *iter를 작성하면 충돌합니다.

몇 가지 일반적인 조언 : 가변 이름에 대해 생각해야합니다. 반복자를 'IT'와 'iter'라고 부르면 어느 시점에서 당신을 혼란스럽게 할 것입니다. 실제로, 당신이 면밀히 살펴보면 이미 가지고 있습니다. 'Farray'와 'Sarray'가 의미있는 이름이라면 'Fiter'와 'Siter'는 어떻습니까?

또한 병합 정렬이 무엇을하고 있는지 생각해보십시오. 마지막 두 블록은 반복자가 남은 물건을 "배수"하기 위해 있습니다. 따라서 첫 번째 루프에있을 필요는 없습니다.

아마 (pseudocode)로 쓸 것입니다.

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)

또는 다소 녹슨화물 문화 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++);
}

여기서 생각할 몇 가지가 있습니다.

첫째, 두 범위를 병합하는 경우 std :: 합병 오히려 자신만의 롤링을합니다.

강화에 다양한 스타일을 사용하고 곱슬 괄호 안에있는 곳을 사용하기 때문에 코드는 읽기가 조금 어렵습니다. 스타일을 선택하고 고수하십시오.

For Loop의 첫 번째 부분은 합병의 올바른 구현 인 것 같습니다.

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);
                }
            }
        }

우선, for () 조건부는 둘 다 it 그리고 iter 지적해서는 안됩니다 end() 각각의 컬렉션 또는 루프가 끝납니다. 그래서 it 결코 가리킬 수 없습니다 sarray.end(), iter 결코 가리킬 수 없습니다 farray.end(), 그리고 둘 다 if 성명서는 해고 될 수 있습니다. 둘 다 죽은 (도달 할 수없는) 코드입니다.

그러나 그들이 죽은 코드가 아니더라도 버그가 있습니다. 조건부 for(...) 반복자가 컬렉션의 끝을 가리킬 때 루프를 깨뜨립니다. 그러나이 반복기는 결코 움직이지 않으므로 무한 루프가 있습니다.

다시이 둘 다 for(...)반복자가 벡터의 끝을 가리킬 수 없기 때문에 s는 무시되지 않은 데드 코드입니다.

하나의 간단한 의견 : 사용하지 않는 이유 while (condition) 대신에 for(; !condition; ).

후자의 건축은 비표준이며 이해하기 어렵다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top