2013-11-10 2 views
0

У меня возникли проблемы с правильной работой моего push_front. Похоже, что new_head->next = head не будет правильно связывать new_head и head. Мой класс node - это обычный класс узлов, где next - указатель узла. Моя функция push_back работает нормально. Я не понимаю, почему head не будет ссылаться на new_head.Непосредственно связанный список push_front не переназначает головку

template <class T> class mylist { 
public: 
    typedef T value_type; 
    typedef T& reference; 
    typedef const T& const_reference; 
    typedef mynode<T>* iterator; 
    typedef size_t size_type; 
    mylist() { create(); } 
    mylist(size_type n, const T& val = T()) { create(n, val); } 
    ~mylist() { uncreate(); } 
    iterator begin() { return head; } 
    iterator end() { return head + size(); } 
    size_type size(); 
    void push_back(const T&); 
    void push_front(const T&); 
    void pop_back(); 
    void pop_front(); 

private: 
    std::allocator<mynode<T>> alloc; 
    mynode<T>* head; 
    mynode<T>* tail; 
    void create() { head = tail = 0; } 
    void create(size_type, const T&); 
    void uncreate(); 
}; 

template <class T> void mylist<T>::push_front(const T& t) 
{ 
    iterator new_head = alloc.allocate(1); 
    new_head->data = t; 
    new_head->next = head; 
    head = new_head; 
    if(tail == 0) 
     tail = head; 
} 

template <class T> void mylist<T>::push_back(const T& t) 
{ 
    tail->next = alloc.allocate(1); 
    tail = tail->next; 
    tail->data = t; 
    tail->next = 0; 
} 

MAIN

#include "mylist.h" 
int main() 
{ 
    mylist<int> lst(5, 2); 
    lst.push_back(22); 
    mylist<int>::iterator temp = lst.begin(); 
    while(temp != lst.end()) { 
     std::cout << **temp << " "; 
     temp++; 
    } 
    std::cout << std::endl; 
    std::cout << "list size: " << lst.size() << std::endl; 
    lst.push_front(80); 
    lst.push_back(7); 
    lst.push_back(3); 
    mylist<int>::iterator inc = lst.begin(); 
    while(inc != lst.end()) { 
     std::cout << **inc << " "; 
     inc++; 
    } 
    std::cout << std::endl; 
    std::cout << "list size: " << lst.size() << std::endl; 
} 

OUTPUT

2 2 2 2 2 22 
list size: 6 
80 7 3 
list size: 3 

EDIT

template <class T> void mylist<T>::create(size_type n, const T& t) 
{ 
    head = alloc.allocate(1); 
    head->data = t; 
    head->next = alloc.allocate(1); 
    mynode<T>* next = head->next; 
    int i = 0; 
    while(i != n-2) { 
     next->data = t; 
     next->next = alloc.allocate(1); 
     next = next->next; 
     ++i; 
    } 
    tail = next; 
    tail->data = t; 
    tail->next = 0; 
} 

class mynode

template <class T> class mynode { 
public: 
    mynode() : next(0) {} 
    mynode(T a, mynode* n = 0) : data(a), next(n) {} 
    mynode* next; 
    mynode* operator++() { return this->next; } 
    mynode* operator+(size_t n) { 
     size_t cnt = 0; 
     mynode* count = this; 
     while(cnt != n) { 
      ++cnt; 
      count = count->next; 
     } 
     return count; 
    } 
    T& operator*() { return this->data; } 
    T data; 
}; 

Example using operator+

#include "mylist.h" 
int main() 
{ 
    mylist<int> test(5,5); 
    mylist<int>::iterator n = test.begin(); 
    while(n != test.end()) { 
     std::cout << **n << " "; 
     n = n + 1; 
    } 
    std::cout << std::endl; 

    mylist<int> test2(6,6); 
    mylist<int>::iterator m = test2.begin(); 
    while(m != test2.end() - 1) { 
     std::cout << **m << " "; 
     m = m->next; 
     if(m == test2.end()-1) 
      std::cout << **m; 
    } 
    std::cout << std::endl; 
} 

Output from example

5 5 5 5 5 
6 6 6 6 6 6 
+0

Вы уверены, что это 'push_front()', а не ваш 'operator ++'? Что произойдет, если вы измените 'lst.push_back (22)' на 'lst.push_front (22)' перед этим первым циклом 'while'? Если он вставляет 22 в начале, то проблема связана с вашим оператором 'operator ++ 'вашего итератора, изменяющим указатели' next' в вашем списке узлов. –

+0

Что произойдет, если вы сделали 'push_back()' в пустом списке? – Leeor

+0

@JoeZ. Когда я делаю это изменение, он переходит в бесконечный цикл. – Ares

ответ

1

Кажется, это push_back, что работает неправильно. Измените его следующим образом:

template <class T> void mylist<T>::push_back(const T& t) 
{ 
    mynode<T>* new_tail = alloc.allocate(1); 
    new_tail->data = t; 
    new_tail->next = 0; 
    if (tail == 0) 
    { 
     head = new_tail; 
    } 
    else 
    { 
     tail->next = new_tail; 
    } 
    tail = new_tail; 
} 
+0

И что бы это сделать, если 'tail == 0'? (т. е. 'push_back' в пустом списке?) Я согласен, что' push_back' сломан, но вы его не исправили полностью. –

+0

Вы действительно хотите, чтобы это зеркало 'push_front', с' new_tail = alloc ... ', а затем' if (tail) {tail-> next = new_tail; tail = new_tail; } else {head = tail = new_tail; } ' –

+0

Joe Z спасибо, я даже не смотрел, что хвост не проверен. :) Я обновил свой код. –