双链表删除后节点功能

时间:2013-03-25 22:52:41

标签: function linked-list

/ *函数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");
}

1 个答案:

答案 0 :(得分:0)

你的设计有点混乱。

设计链接列表的传统C ++方法(如std::list)具有单独的nodelist类,而不是作为两者的单个类:

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_frontpush_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

无论如何,我认为在你的代码工作之前不要试图敲打你的代码,你应该看看各种设计的现有实现,直到你理解了差异,然后选择你想要的设计并尝试实现它。