这是一个双重链接的列表吗

Is this a doubly linked list?

本文关键字:链接 列表 一个      更新时间:2023-10-16

来自Java背景,下面是C++代码,我想从中了解DList listp;成员在DListNode类中的概念用法。

我不明白,如何在代码node->add ( (DListNode*) this, this ) ;this.tail = (DListNode*) this ; 中将DList类型的对象转换为DListNode类型

我的目标是将这个C++代码转换成Java。

class  DList
{
    private:
        friend class DlistNode;
        DListNode* head ;
        DListNode* dummy ;
        DListNode* tail ;
        int size;
    public:
        DList ( void ): dummy( NULL), size( 0 )
        {
            this.head = (DlistNode*) &dummy ; //this is sentinel
            this.tail = (DListNode*) this ;
        }
        void add_head   ( DListNode* node )
        {
            node->add ( (DListNode*) this, this ) ;
        }
        void add_tail ( DListNode* node )
        {
            node->add ( tail, this ) ;
        }
}

class DListNode
{
    private:
        friend class DList;
        DListNode* next ;
        DListNode* prev ;
        DList* listp;
    public:
        DListNode*  rem ( void )
        {
            if (listp)
            {
                next -> prev = prev ;
                prev -> next = next ;
                next = prev = this ;
                listp->size--;
                listp = NULL;
            }
            return ( this ) ;
        } 
        void  add ( DListNode* predecessor, DList *parent )
        {
            rem() ;
            if (!parent)
            {       
                listp = predecessor->listp;
            }
            else
            {
                listp = parent;
            }
            prev = predecessor ;
            next = prev -> next ;
            prev -> next = next -> prev = this ;
            if ( 0 != listp )
            {  
                listp->size++;
            }
        } 
}

我的问题:

1)listp加入class DListNode的目的是什么?

2)class DListtail成员的目的是什么?

1)listp是指向整个列表的指针。这允许在只给定节点指针的情况下对列表进行操作。

2) tail是指向列表中最后一项的指针。这允许一些操作(如追加)为O(1)而不是O(n)。

对于双链表来说,这不是一个有效的(或者至少不是一个很好的)实现。DList类正在做一些DListNode没有意识到的非常危险的事情,而DListNode根本没有管理DListheadtail成员。

最安全的方法是只使用STL std::list类,让它为您处理所有细节。但是,如果您必须手动实现它,请尝试更像这样的方法:

class  DList
{
private:
    friend class DlistNode;
    DListNode* head;
    DListNode* tail;
    int size;
public:
    DList() : head(NULL), tail(NULL), size(0)
    {
    }
    ~DList()
    {
        while (head)
            delete head;
    }
    void add_head(DListNode* node)
    {
        node->add_head(this);
    }
    void add_tail(DListNode* node)
    {
        node->add_tail(this);
    }
};

class DListNode
{
private:
    friend class DList;
    DListNode* next;
    DListNode* prev;
    DList* listp;
public:
    DListNode() : next(NULL), prev(NULL), listp(NULL)
    {
    }
    ~DListNode()
    {
        remove();
    }
    void remove()
    {
        if (next)
            next->prev = prev;
        if (prev)
            prev->next = next;
        if (listp)
        {
            if (listp->head == this)
                listp->head = next;
            if (listp->tail == this)
                listp->tail = prev;
            listp->size--;
            listp = NULL;
        }
        prev = next = NULL;
    } 
    void add_head(DList *parent)
    {
        if (!parent)
            throw std::runtime_error("no parent specified");
        if (parent->head == this)
            return;
        remove();
        if (parent->head)
        {
            parent->head->prev = this;
            next = parent->head;
        }
        parent->head = this;            
        listp = parent;
        listp->size++;
    } 
    void add_tail(DList *parent)
    {
        if (!parent)
            throw std::runtime_error("no parent specified");
        if (parent->tail == this)
            return;
        remove();
        if (parent->tail)
        {
            parent->tail->next = this;
            prev = parent->tail;
        }
        parent->tail = this;            
        listp = parent;
        listp->size++;
    } 
    void add_before(DListNode *node)
    {
        if (!node)
            throw std::runtime_error("no node specified");
        if (node == this)
            return;
        remove();
        if (node->prev)
            node->prev->next = this;
        next = node;
        prev = node->prev;
        node->prev = this;
        listp = node->listp;
        if (listp->head == node)
            listp->head = this;
        listp->size++;
    }
    void add_after(DListNode *node)
    {
        if (!node)
            throw std::runtime_error("no node specified");
        if (node == this)
            return;
        remove();
        if (node->next)
            node->next->prev = this;
        prev = node;
        next = node->next;
        node->next = this;
        listp = node->listp;
        if (listp->tail == node)
            listp->tail = this;
        listp->size++;
    }
};