/ *函数delete_back()有问题;我认为删除功能3部分有问题。 还有remove_ele()我不知道怎么做,谢谢。 为什么我使用相同的方法删除元素不起作用 * /
#include <iostream>
using namespace std;
template<class T>
class doulinked
{
private:
doulinked *head;
doulinked *tail;
doulinked *prev;
doulinked *next;
T data;
public:
doulinked()
{
head=tail=prev=next=NULL;
T data;
}
void Inlist (doulinked *head);
void add(T d);
void insert_node();
void remove(doulinked* v);
void push_tail(T d);
void delete_front();
void delete_back();
void remove_ele (T d);
template <class U>
friend ostream & operator<<(ostream & os, const doulinked<U> & dll);
};
template<class U>
ostream & operator<<(ostream & os,const doulinked<U> & dll)
{
doulinked<U> * tmp = dll.head;
while (tmp)
{
os << tmp->data << " ";
tmp = tmp->next;
}
return os;
}
template<class T>
void doulinked<T>::add(T d)
{
doulinked *n = new doulinked;
n->data=d;
if( head == NULL)
{
head = n;
tail = n;
}
else
{
head->prev = n;
n->next = head;
head = n;
}
}
template<class T>
void doulinked<T>::push_tail(T d)
{
doulinked *n = new doulinked;
n->data=d;
if( tail == NULL)
{
head = n;
tail = n;
}
else
{
tail->next = n;
n->prev = tail;
tail = n;
}
}
template <class T>
void doulinked<T>::delete_front()
{
remove(head);
}
template <class T>
void doulinked<T>::delete_back()
{
remove(tail);
}
template <class T>
void doulinked<T>::remove(doulinked* v)
{
if(v->prev!=NULL && v->next!=NULL)
{
doulinked* p = v->prev;
doulinked* n = v->next;
p->next = n;
n->prev = p;
delete v;
}
else if(v->prev==NULL && v->next!=NULL)
{
doulinked* n =v->next;
head->next = n;
n->prev = head;
delete head;
head=n;
}
else if(v->prev!=NULL && v->next==NULL) // have some wrong with this loop;
{
doulinked* p=v->prev;
p->next=tail;
tail->prev=p;
delete tail;
tail=p;
}
}
template <class T>
void doulinked<T>::remove_ele(T d) // have some wrong with this loop
{
if(head->data==d)
{
remove(head);
head=head->next;
}
else
head=head->next;
}
int main()
{
doulinked<int> dll;
dll.add(5123);
dll.add(1227);
dll.add(127);
dll.push_tail(1235);
dll.push_tail(834);
dll.push_tail(1595);
dll.delete_front();
//dll.delete_back();
//dll.remove_ele(834);
cout<<dll<<endl;
system("pause");
}
答案 0 :(得分:0)
你的设计有点混乱。
设计链接列表的传统C ++方法(如std::list
)具有单独的node
和list
类,而不是作为两者的单个类:
template <typename T> struct node {
node *prev, *next;
};
template <typename T> struct list {
node *head, *tail;
};
如果你想传递node
指针,那很好 - 但是你必须传递节点指针,而不是节点对象。并且mutator函数也必须返回指针 - 如果你在头节点上调用delete_front
,你现在已经获得了对已删除节点的引用;你需要它next
或者你丢失了对列表的任何引用。由于构造函数必须返回指针,因此不能使用真正的公共构造函数;你想要一个静态工厂方法。等等。
你还必须确定在头部之前(以及尾部之后)是否有“哨兵节点”。如果你正在构造函数中创建一个标记 - 正如你所做的那样 - 在末尾插入的新节点需要指向你没有做过的标记 -
此外,您使用的整个head
/ tail
概念对于节点API来说是错误的。 (另外,混合和匹配来自不同风格的名字令人难以置信的混淆 - 您add
匹配delete_front
和push_tail
匹配delete_back
...)拥有{{1你要么必须遍历整个列表(使其为O(N)),要么必须让每个节点都保持push_tail
指针(使任何列表更改为O(N)),或者你有使头部保持tail
指针,尾部保持tail
指针。
最后一个工作(当每个节点只需要一个节点时,它会为每个节点浪费几个指针,但这很少重要)。但考虑到这一点令人困惑。
创建圆形列表实际上要简单得多,其中头部的head
指向尾部(或哨兵)而不是0,尾部的prev
指向头部(或哨兵)这将获得单独的next
类的所有优点,而不需要该类 - 如果你有一个指向头部的指针,那么你需要引用整个列表(因为{{1}是头部,list
是尾部,或者如果你有一个哨兵那么类似。)
另外,你的构造函数没有多大意义:
node
这会创建一个名为node->prev
的本地默认构造的doulinked()
{
head=tail=prev=next=NULL;
T data;
}
变量,然后......对它无效。您可能想要将T
设置为某些内容。你可能想为此使用初始化器。在这种情况下,您不需要做任何事情,因为那已经是默认值。
而且我不确定data
应该做什么。
对于data
,大概你想删除Inlist
的第一个元素,对吧?如果您首先编写remove_ele(T d)
方法,那么它很简单:data == d
。 (我假设find
会引发异常;如果您希望remove(find(d))
返回null或者返回标记或其他内容,并find
返回find
或{{ 1}},显然你还需要一行来检查查找是否有效。)
如果您不知道如何编写remove_ele
方法......那么,这就是链表的重点,对所有遍历函数都有一个简单的递归定义,包括true
:
false
无论如何,我认为在你的代码工作之前不要试图敲打你的代码,你应该看看各种设计的现有实现,直到你理解了差异,然后选择你想要的设计并尝试实现它。