Wg mnie to powinno wyglądać mniej więcej następująco:
#include <iostream>
using namespace std;
template <typename T> class DoubleLinkedList // No thread safe!
{
public:
struct Node
{
T data;
private:
Node *next,*prev;
Node(const T &data,Node *next=nullptr,Node *prev=nullptr):data(data),next(next),prev(prev) {}
friend class DoubleLinkedList;
};
private:
Node *head,*tail;
public:
DoubleLinkedList():head(nullptr),tail(nullptr) {}
DoubleLinkedList(const DoubleLinkedList &lst)=delete; // lepiej jednak napisać
DoubleLinkedList &operator=(const DoubleLinkedList &lst)=delete; // lepiej jednak napisać
~DoubleLinkedList() { clear(); }
bool isEmpty()const { return !head; }
Node *front()const { return head; }
Node *back()const { return tail; }
Node *next(Node *from,int count)const { while((from)&&(count-->0)) from=from->next; return from; }
Node *prev(Node *from,int count)const { while((from)&&(count-->0)) from=from->prev; return from; }
void clear() { for(;(tail=head)!=nullptr;delete tail) head=head->next; }
void insert(const T &data,int position)
{
if(position>=0)
{
Node *node=next(head,position);
if(node) insert_before(node,data);
else insert_after(tail,data);
}
else // position=-1 => na koniec, position=-2 => przed ostatnim
{
Node *node=prev(tail,-position-1);
if(node) insert_after(node,data);
else insert_before(head,data);
}
}
void insert_before(Node *node,const T &data)
{
if(!node) push_front(data);
else node->prev=(node->prev?node->prev->next:head)=new Node(data,node,node->prev); // ?node->prev: => ?node->prev->next:
}
void insert_after(Node *node,const T &data)
{
if(!node) push_back(data);
else node->next=(node->next?node->next->prev:tail)=new Node(data,node->next,node); // ?node->next: => ?node->next->prev:
}
void push_front(const T &data)
{
head=(head?head->prev:tail)=new Node(data,head,nullptr);
}
void push_back(const T &data)
{
tail=(tail?tail->next:head)=new Node(data,nullptr,tail);
}
ostream &prn(ostream &s)const
{
for(Node *node=head;node;node=node->next) s<<(node!=head?", ":"")<<node->data;
return s;
}
ostream &nrp(ostream &s)const
{
for(Node *node=tail;node;node=node->prev) s<<(node!=tail?", ":"")<<node->data;
return s;
}
friend ostream &operator<<(ostream &s,const DoubleLinkedList<T> &lst) { return lst.nrp(lst.prn(s)<<"] <=> ["); }
};
int main()
{
DoubleLinkedList<int> MyList;
cout<<'['<<MyList<<']'<<endl;
MyList.push_back(13);
cout<<'['<<MyList<<']'<<endl;
MyList.push_front(666);
cout<<'['<<MyList<<']'<<endl;
MyList.push_back(31);
cout<<'['<<MyList<<']'<<endl;
MyList.push_front(999);
cout<<'['<<MyList<<']'<<endl;
cout<<"****"<<endl;
MyList.clear();
MyList.insert(1,0);
cout<<'['<<MyList<<']'<<endl;
MyList.insert(2,1);
cout<<'['<<MyList<<']'<<endl;
MyList.insert(3,2);
cout<<'['<<MyList<<']'<<endl;
MyList.insert(6,-1);
cout<<'['<<MyList<<']'<<endl;
MyList.insert(5,-2);
cout<<'['<<MyList<<']'<<endl;
MyList.insert(4,-3);
cout<<'['<<MyList<<']'<<endl;
MyList.insert(0,-100);
cout<<'['<<MyList<<']'<<endl;
MyList.insert(7,100);
cout<<'['<<MyList<<']'<<endl;
return 0;
}
@Baxing, zauważ że kodu o parę wierszy więcej niż u ciebie ale:
- znacznie więcej możliwości - więc myśl na przód np poprawne usuwanie w destruktorze
- wszystkie metody są jednowierszowe lub kilkuwierszowe - łatwo się szuka ewentualnego błędu.