2012-11-21 50 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

在你提供的鏈接中檢查完整的代碼後,我可以肯定地說這個問題是因爲你沒有賦值操作符。

現在發生的情況是,列表的分配將使用由編譯器自動生成的默認賦值運算符。這是一個副本,所以分配左側的列表將其指針與右側列表的指針相同。這意味着當你返回的局部變量超出範圍時,它當然會調用刪除列表的析構函數。現在副本有指向已刪除內存的指針,並且訪問thos指針是未定義的行爲。這就是爲什麼它似乎在一個地方而不是另一個地方工作。

+0

我並不完全確定'你沒有賦值運算符'的含義,因爲我可以在任何地方看到賦值。你的意思是他沒有覆蓋列表中的賦值操作符?這不是必需的,因爲他正在使用STL,並且如果您將1個STL列表分配給另一個,它將執行深層複製(如果他一直使用指針,情況不會如此)。請注意,不是對象的深層副本,而是列表本身,而在這種情況下這是一個微不足道的差異,因爲int不能被淺拷貝。 – Dukeling

+0

@Dukeling,他沒有使用'std :: list'。他有他自己的'sorted :: list'。 – Shahbaz

+0

哦,對,這似乎確實如此。有時候,當人們將某些標準庫命名爲完全一樣時,我會有點困惑。 – Dukeling