循环单向链表(c++实现)

  在单向链表(c++实现)中,链表的最后一个节点的nex指针指向NULL,而所谓的循环单向链表即是指链表的最后一个节点的next指针指向首节点(注意不是头节点,头节点是方便链表操作而存在的结构体变量)。循环链表是一种特殊的单向链表,因此软件设计上,循环链表可继承自单向链表。
  循环单向链表的实现难点在于:
  (1)插入数据的位置为0时,头节点和尾节点的next指针均指向新节点;
  (2)删除位置为0的节点时,头节点和尾节点的next指针都指向为位置为1的节点,然后安全删除位置为0的节点。

//CirculateList.h
//LinkList类的源码参照前面的单向链表(c++实现)
#ifndef __CIRCULATELIST_H__
#define __CIRCULATELIST_H__

#include "LinkList.h"

template <typename T>
class CirculateList : public LinkList<T>
{
protected:
    typedef typename LinkList<T>::Node_t Node_t;

    //获取最后一个节点
    Node_t* _last() const
    {
        return this->position(this->m_length - 1)->next;
    }

    //将最后一个节点的next指针指向首节点
    void _last_2_first() const
    {
        _last()->next = this->m_header.next;
    }

public:
    bool insert(int i, const T& e)  //插入操作涉及到可能插入的是首节点的位置所以需要重新实现
    {
        bool ret = true;
        i %= this->m_length + 1;    //循环链表,i的值可以大于链表的m_length,插入操作时i的值为[0, m_length]
        ret = LinkList::insert(i, e);

        //若插入的位置是首节点,需要将最后一个节点的next指针指向新节点
        if (ret && i== 0)
        {
            _last_2_first();
        }

        return ret;
    }

    bool insert(const T& e)
    {
        return insert(this->m_length, e);
    }

    bool remove(int i)  //删除操作涉及到可能删除的是首节点所以需要重新实现
    {
        bool ret = true;
        i %= this->m_length;

        if (i == 0)     //删除的位置是首节点
        {
            Node_t* toDel = this->m_header.next;
            if (toDel != NULL)
            {
                this->m_header.next = toDel->next;
                --this->m_length;

                if (this->m_length > 0)
                {
                    _last_2_first();
                    if (this->m_current == toDel)
                        this->m_current = toDel->next;
                }
                else    //链表中只有一个节点,删除后就链表为空
                {
                    this->m_header.next = NULL;
                    this->m_current = NULL;
                }
                this->DestoryNode(toDel);
            }
            else
                ret = false;
        }
        else
        {
            ret = LinkList<T>::remove(i);
        }
        return ret;
    }

    //调用LinkList<T>对应的成员函数,需要注意i的取值要取模
    bool set(int i, const T& e)
    {
        return LinkList<T>::set(i % m_length, e);
    }

    T get(int i) const
    {
        return LinkList<T>::get(i % m_length);
    }

    int find(const T& e) const  //LinkList的while()循环条件是next不为0,所以这里需要重新实现find()
    {
        int ret = -1;
        Node_t* tmp = this->m_header.next;

        for (int i = 0; i < this->m_length; ++i)
        {
            if (tmp->value == e)
            {
                ret = i;
                break;
            }
            tmp = tmp->next;
        }

        return ret;
    }

    void clear()    //LinkList的while()循环条件是next不为0,所以这里需要重新实现clear()
    {
        while (this->m_length > 1)
            remove(1);  //每次都删除位置为1的节点,避免重复调用_last_2_first()函数

        if (this->m_length == 1)
        {
            Node_t* toDel = this->m_header.next;
            this->m_header.next = NULL;
            this->m_length = 0;
            this->m_current = NULL;
            this->DestoryNode(toDel);
        }
    }


    bool move(int i, int step)
    {
        return LinkList<T>::move(i % this->m_length, step);
    }

    bool end()  //循环链表,end()为true只能说明链表中无节点
    {
        return (this->m_length == 0 || this->m_current == NULL);
    }

    ~CirculateList()
    {
        clear();
    }
};

#endif /* __CIRCULATELIST_H__ */

  测试:15只猴子围成一圈从1报数到7的出局,最后谁是猴王?

void DiademaMonkey(int cnt, int start, int n)
{
    CirculateList<int> c;

    for (int i = 1; i <= cnt; ++i)
        c.insert(i);

    c.move(start - 1, n - 1);

    while (c.length() > 1)
    {
        c.next();
        c.remove(c.find(c.current()));
    }

    cout << c.current() << endl;
}

int main()
{
    DiademaMonkey(15, 1, 7);

    getchar();
    return 0;
}

  编译运行:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_29344757/article/details/79242014