2012-11-21 3 views
1

나는이 병합 정렬 기능을이 병합 정렬 함수가 왜 연결된 목록을 반환하는지 (C++)?

namespace sorted{ 

    template<typename T> 
    class list { 

     /* other stuff */ 

     list<T>* slice(int from, int to){ 
      from = (from < 0) ? 0 : from; 
      to = (to > this->len) ? this->len : to; 
      list<T>* result = new list<T>(); 
      node<T> *n = this->head; 
      int idx = 0; 
      while (n && (idx < this->len)){ 
       if ((from <= idx) && (idx <= to)) result->append(n->value); 
       if (idx > to) break; 
       n = n->next; 
       idx++; 
      } 
      return result; 
     }    
    } 

    template<typename T> 
    list<T>* merge(list<T>* left, list<T>* right){ 
     list<T>* result = new list<T>(); 
     while ((left->length() > 0) || (right->length() > 0)){ 
      if ((left->length() > 0) && (right->length() > 0)){ 
       T l = left->get(0); 
       T r = right->get(0); 
       if (l <= r){ 
        result->append(l); 
        left->remove(0); 
       } else{ 
        result->append(r); 
        right->remove(0); 
       } 
       continue; 
      } 

      if (left->length() > 0) { 
       result->append(left->get(0)); 
       left->remove(0); 
      } 

      if (right->length() > 0) { 
       result->append(right->get(0)); 
       right->remove(0); 
      } 
     } 
     return result; 
    } 

    template<typename T> 
    list<T>* merge_sort(list<T>* original){ 
     if (original->length() <= 1) { 
      return original; 
     } 
     int len = original->length(); 
     list<T>* left = NULL; 
     list<T>* right = NULL; 
     if (len > 2){ 
      left = original->slice(0,(len/2)); 
      right = original->slice((len/2)+1,len-1); 
     }else if (len == 2){ 
      left = original->slice(0,0); 
      right = original->slice(1,1); 
     } 
     left = merge_sort(left); 
     right = merge_sort(right); 
     delete original; 
     list<T>* result = merge(left, right); 
     delete left; 
     delete right; 
     return result; 
    } 

    /* other stuff */  
} 

을 가지고 그리고 여기

int main(int argc, char** argv){ 
    sorted::list<int>* l = get_random_list(); 
    l = merge_sort(l); 
    for (int i = 0; i < (l->length() - 1); i++){ 
     int t = l->get(i); 
     int u = l->get(i+1); 
     if (t > u){ 
      sorted::list<int>* m = l->slice(i - 5, i + 5); 
      cout << m << endl; 
      delete m; 
      break; 
     } 
    } 
    delete l; 
    return 0; 
}   

링크

내 질문 bitbucket.org project에이이이었다 내 주요 방법입니다했습니다.

슬라이싱 기능에서 목록이 제대로 반환되면 동일한 방식으로 수행되면 왜 주 기능으로 제대로 반환되지 않습니까?

[업데이트] 그들이 현재해야하는 방식대로 기능이 추가되었습니다. bitbucket에서 정식 버전이 나옵니다.

+1

할당 담당자에게 문제가 있습니까? 너는 할당 연산자를 가지고 있지, 그렇지? –

+0

병합은 어떻게 정렬됩니까? 당신은 단지 하나의 정렬되지 않은 슬라이스를 반환합니다 ... 당신은 당신의 결과물에있는 것이 아닙니다. – leftaroundabout

+0

나는 그가 단순한 버전 –

답변

3

제공된 링크에서 전체 코드를 확인한 후에는 할당 연산자가 없기 때문에 문제가 있다고 할 수 있습니다.

이제 목록의 할당은 컴파일러에서 자동으로 생성되는 기본 할당 연산자를 사용합니다. 그러면 얕은 사본이되므로 과제 왼쪽에있는 목록의 포인터는 오른쪽에있는 목록과 동일하게됩니다. 즉, 반환하는 로컬 변수가 범위를 벗어나면 물론 목록을 삭제하는 소멸자가 호출됩니다. 이제 사본에는 삭제 된 메모리를 가리키는 포인터가 있으며 포인터에 액세스하는 것은 정의되지 않은 동작입니다. 이것이 왜 한 곳에서 일하는 것처럼 보입니다.

+0

나는 당신이 할당 연산자를 가지고 있지 않다는 것을 당신이 의미하는 것이 확실하지 않습니다, 왜냐하면 나는 장소 전체에서 과제를 볼 수 있기 때문입니다. 그가리스트의 대입 연산자를 덮어 쓰지 않았다는 뜻입니까? 이것이 STL을 사용함에있어 필수적인 것은 아니며, STL리스트를 다른 STL리스트에 할당 할 경우, 딥 카피를 할 것입니다 (이것은 포인터를 사용하고있는 경우에는 그렇지 않습니다). 객체의 딥 카피는 아니고,리스트 자체의 딥 카피는 아닙니다. int의 얕은 카피가 가능하지 않기 때문에,이 경우는 사소한 차이가 있습니다. – Dukeling

+0

@Dukeling, 그는'std :: list'를 사용하지 않습니다. 그는 자신 만의'sorted :: list'를 가지고있다. – Shahbaz

+0

아 맞아, 그럴 것 같아. 사람들이 어떤 표준 라이브러리와 똑같은 이름을 붙이면 가끔 혼란스러워집니다. – Dukeling