2010-06-03 3 views
0

나는 C++에서 간단한 링크 된 목록을 구현하고있다. 내가 실수를하고 난 그것이 작동어디서 실수입니까?

#include <stdexcept> 
#include <iostream> 

struct Node { 

    Node(Node *next, int value): 
    next(next), value(value) { 
    } 
    Node *next; 
    int value; 
}; 

class List { 
    Node *first; 
    int len; 
    Node *nthNode(int index); 

public: 

    List():first(0),len(0){ 
    } 

    // Copy - Konstruktor 
    List(const List & other){ 

    }; 

    // Zuweisungs - Operator O(len +other.len) 
    List &operator=(const List &other) { 
     clear(); 
     if(!other.len) return *this; 
     Node *it = first = new Node(0,other.first->value); 
     for (Node *n = other.first->next; n; n = n->next) { 
      it = it->next = new Node(0, n->value); 
     } 
     len = other.len; 
     return *this; 
    } 

    // Destruktor 
    ~List(){ 

    }; 


    void push_back(int value){ 

    }; 

    void push_front(int value){ 
     Node* front = new Node(0,value); 

     if(first){ 
      first = front; 
      front->next = 0; 
     }else{ 
      front->next = first; 
      first = front; 

     } 
     len++; 
    }; 

    int &at(int index){ 
     int count = 0 ; 
     int ret ; 
     Node *it = first; 
     for (Node *n = first->next; n; n = n->next) { 
      if(count==index) ret = n->value; 
      count++; 
     } 
     return ret ; 
    }; 

    void clear(){ 


    }; 

    void show() { 
     std::cout << " List [" << len << " ]:{ "; 
     for (int i = 0; i < len; ++i) { 
      std::cout << at(i) << (i == len - 1 ? '}' : ','); 
     } 
     std::cout << std::endl; 
    } 
}; 

/* 
* 
*/ 
int main() { 

    List l; 
// l. push_back(1); 
// l. push_back(2); 
    l. push_front(7); 
    l. push_front(8); 
    l. push_front(9); 
    l.show(); 
    // List(l). show(); 
} 

를 :(볼 수 없습니다 ...하지만 출력은 다음과 같습니다

목록 [3] : {0,134520896,9484585}

답변

3

push_front 논리는 잘못된 것입니다 그것은 다음과 같아야합니다.

void push_front(int value){ 
    first = new Node(first, value); 
    ++len; 
} 

Whil 우리는 그것에있어, 귀하의 은 예외 안전하지 않습니다. at 멤버 함수를 구현하지 않는 다른 주에

List& operator=(List other) { swap(other); return *this; } 
void swap(List& other) { 
    Node* tnode = first; first = other.first; other.first = tnode; 
    int tlen = len; len = other.len; other.len = tlen; 
} 

; 복사 - 생성자에서 복사를 구현하고 복사 및 스왑 관용구를 사용하여 지정 랜덤 액세스는 매우 비효율적이므로 권장해서는 안됩니다. 대신 iterators를 구현하십시오.

+0

내가 왜 undestand 연산자 = 왜 스왑을 사용해야합니다. 내가 2 목록을 가지고 다른 하나를 할당한다면, 나는 그 fisrt가 목록의 하나의 메모리 공간을 가리키는 게으른 자원 절약 머리를 가진 사본이 될 것이기를 바란다. –

+1

@denard bardadym,'new Node' 호출 중 하나가 실패하면 어떤 상태가 될까요? 복사 및 스왑 이디엄은 복사본이 이미 성공할 때까지 할당 대상을 변경하지 않습니다. 스왑 자체는 절대로 버리지 않습니다. –

+0

push_front()는 marcelo와 같아야합니다. at() 함수에서 잘못된 Node *로 시작합니다. 목록에서 first -> next로 시작하면 "first"여야합니다. – akira

2

at에 로컬 변수에 대한 참조가 반환됩니다. 함수가 종료되면 변수는 범위를 벗어납니다. 이후에 액세스하는 것은 정의되지 않은 동작입니다. 운이 좋으면 추락하지 않아도됩니다.

show (O (n * n) 심각도) 및 push_front (if (first)?) 구현을 다시 고려해야합니다.

Node *at(int index){ 
    int count = 0 ; 
    for (Node *n = first; n; n = n->next) { 
     if(count==index) 
      return n; 
     count++; 
    } 
    return NULL; 
}; 

그것은 참조를 반환하지 않습니다

여기에서의 더 나은 구현입니다. 인덱스가리스트의 길이보다 큰 경우 널 참조를 리턴 할 수 없습니다. 또한 반환 형식을 Node로 변경하여 호출자가 값을 변경할 수 있습니다.

+0

show()가 재미있어합니다. –

관련 문제