循环单链表(链表)

双链表:插入节点时和删除节点时注意位置为0的节点。

 

图:

 

 

继承关系图:

 

 

 CircularList.h

/*
*    CirularList: 循环链表模板
*    成员变量:
*            
*    成员函数:
*            last_to_first()                        连接首尾节点
*            bool insert(int pos,const T& obj)    插入节点
*            bool remove(int pos)                删除下标为pos的节点。分三步:头节点与1节点,尾节点与1节点,删除0节点
*            bool set(int pos, const T& obj)        
*            bool get(int pos, T& obj) const        
*            int find(const T& obj) const        
*            void clean()                        
*    
*    
*    
*/

#ifndef CIRCULARLIST_H
#define CIRCULARLIST_H

#include"LinkList.h"

namespace DSL
{
    template <typename T>
    class CircularList : public LinkList<T>
    {
        protected:
            typedef typename LinkList<T>::Node Node;
            void last_to_first()
            {
                Node* current = reinterpret_cast<Node*>(&this->m_header);
                for(int i = 0; i < this->m_length; i++)
                {
                    current = current->next;
                }
                current->next = this->m_header.next;
            }

        public:
            bool insert(const T & obj) // 默认插入尾部
            {
                return (this->insert(this->m_length,obj));
            }

            bool insert(int pos, const T & obj)
            {
                bool ret = 1;
                pos = pos % (this->m_length + 1);
                if(pos == 0) // 插入链表头部
                {
                    ret = LinkList<T>::insert(pos,obj);
                    last_to_first();
                }
                else  // 插入链表中部
                {
                    ret = LinkList<T>::insert(pos,obj);
                }
                return ret;
            }

            bool remove(int pos)  
            {
                bool ret = 1;
                pos = (this->m_length == 0 ? 0 : (pos % this->m_length));
                if(pos == 0) // 删除0节点
                {
                    Node* toDel = this->m_header.next;
                    if(this->m_length > 0)  // 节点0存在
                    {
                        this->m_header.next = toDel->next;  
                        this->m_length--;
                        if(this->m_length > 0)  // 删除0节点后下个节点存在
                        {
                            last_to_first();
                            if(this->m_current == toDel)
                            {
                                this->m_current = toDel->next;
                            }
                        }
                        else
                        {
                            this->m_header.next == NULL;
                            this->m_current = NULL;
                        }
                        this->destroy(toDel);
                    }
                    else
                    {
                        this->m_header.next == NULL;
                        this->m_current = NULL;
                    }
                    
                }
                else // 删除中间节点
                {
                    ret = LinkList<T>::remove(pos);
                }
                return ret;
            }

            bool set(int pos, const T& obj)
            {
                pos = (this->m_length == 0 ? 0 : (pos % this->m_length));
                return LinkList<T>::set(pos,obj);
            }

            T get(int pos)
            {
                pos = (this->m_length == 0 ? 0 : (pos % this->m_length));
                return LinkList<T>::get(pos);
            }
        
            bool get(int pos, T& obj) const
            {
                pos = (this->m_length == 0 ? 0 : (pos % this->m_length));
                return LinkList<T>::get(pos,obj);
            }

            int find(const T& obj) const
            {
                int ret = -1;
                Node* slider = this->m_header.next;
                for(int i = 0; i < this->m_length; i++)
                {
                    if(slider->value == obj)
                    {
                        ret = i;
                        break;
                    }
                    slider = slider->next;
                }
            }

            void clean()
            {
                for(int i = this->m_length; i > 0; i--)
                {
                    if( this->m_length > 1) // 删除中间节点
                    {
                        remove(1);
                    }
                    else  // 删除头节点
                    {
                        Node* toDel = this->m_header.next;
                        this->m_header.next = NULL;
                        this->m_current = NULL;
                        this->m_length = 0;
                        this->destroy(toDel);
                    }
                }
            }

            bool move(int pos)
            {
                pos = (this->m_length == 0 ? 0 : (pos % this->m_length));
                return LinkList<T>::move(pos);
            }

            bool end()
            {
                return ((this->m_length == 0) || (this->m_current == NULL));
            }

            ~CircularList()
            {
                clean();
            }

    };
}

/*
约瑟夫环
num:   总人数
start: 报数起始位置
step:  报数个数
void Josephus(int num, int start, int step)
{
    CircularList<int> cl;
    for(int i = 1; i <= num; i++)
    {
        cl.insert(i);
    }
    cl.move(start - 1); // 循环链表下标从0开始
    while(cl.length() > 0)
    {
        cl.next(step - 1);
        cout << cl.current() << endl;    
        cl.remove(cl.find(cl.current()));
    }
}


*/

#endif
View Code

 

移植Linux内核的链表,/include/linux/List.h

LinuxList.h

/*
*    LinuxList.h:    移植Linux4.9的双向循环链表/include/linux/list.h,兼容g++/gcc编译器。
*    
*    接口函数:
*            list_head:                         链表节点,通过内嵌到其他数据结构使用。(头节点的数据域并未使用)
*
*            INIT_LIST_HEAD:                    初始化链表头,将链表头的next,prev指针都指向自己,此状态表示链表为空
*            list_add:                        链表头节点和第二个节点中间插入
*            list_add_tail:                  链表头节点和尾节点中间插入
*            list_del:                        删除节点,删除当前传入的节点
*            list_empty:                        链表是否为空,头节点的next和prev指针指向自己则为空。
*            list_for_each_entry:            头节点开始,正向遍历链表
*            list_for_each_entry_reverse:    头节点开始,逆向遍历链表
*
*            contain_of        通过结构体成员指针,结构体成员名,结构体类型获取 结构体首地址
*            list_entry        通过父级结构体的内嵌成员list_head的成员指针,成员名,结构体类型获取 父级结构体的首地址
*/

#ifndef LINUXLIST_H
#define LINUXLIST_H

struct list_head 
{
    struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) (struct list_head name = LIST_HEAD_INIT(name))

/*    params: 
*            list_head  头父级数据结构的链表节点
*/
static  void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list->prev = list;
}

static  void __list_add(struct list_head *entry, struct list_head *prev, struct list_head *next)
{
    next->prev = entry;
    entry->next = next;
    entry->prev = prev;
    prev->next = entry;
}

/*    params: 
*            entry  内嵌到父级数据结构的链表节点
*            head   头父级数据结构中的链表节点
*/
static void list_add(struct list_head *entry, struct list_head *head)
{
    __list_add(entry, head, head->next);
}

static void list_add_tail(struct list_head *entry, struct list_head *head)
{
    __list_add(entry, head->prev, head);
}

static void __list_del(struct list_head *prev, struct list_head *next)
{
    next->prev = prev;
    prev->next = next;
}

/*    params: 
*            要删除父级数据结构中的链表头
*/
static void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
}

static void list_del_init(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}

static void list_move_tail(struct list_head *list,
                  struct list_head *head)
{
    __list_del(list->prev, list->next);
    list_add_tail(list, head);
}

#ifdef __cplusplus  // C语言没有bool类型
static bool list_empty(struct list_head *head)
{
    return head->next == head;
}
#else
static int list_empty(struct list_head *head)
{
    return head->next == head;
}
#endif

#ifndef container_of
#define container_of(ptr, type, member) (type *)((char *)(ptr) - (char *)&((type *)0)->member)
#endif

#define list_entry(ptr, type, member)  container_of(ptr, type, member)

#define list_first_entry(ptr, type, member)  list_entry((ptr)->next, type, member)

#define list_last_entry(ptr, type, member)  list_entry((ptr)->prev, type, member)

#ifdef __cplusplus  // C++类型检查要强一些
#define __container_of(ptr, sample, member)     container_of((ptr), typeof(*(sample)), member)
#else
#define __container_of(ptr, sample, member)     (void *)container_of((ptr), typeof(*(sample)), member)
#endif

/*    params: 
*            pos      用作游标的父级数据结构
*            head    头父级数据结构的链表节点(链表头)
*            member    父级数据结构中定义的list_head的变量名
*/
#define list_for_each_entry(pos, head, member)                \
    for (pos = __container_of((head)->next, pos, member);        \
     &pos->member != (head);                    \
     pos = __container_of(pos->member.next, pos, member))

#define list_for_each_entry_safe(pos, tmp, head, member)        \
    for (pos = __container_of((head)->next, pos, member),        \
     tmp = __container_of(pos->member.next, pos, member);        \
     &pos->member != (head);                    \
     pos = tmp, tmp = __container_of(pos->member.next, tmp, member))

#define list_for_each_entry_reverse(pos, head, member)            \
    for (pos = __container_of((head)->prev, pos, member);        \
         &pos->member != (head);                    \
         pos = __container_of(pos->member.prev, pos, member))

#define list_for_each_entry_continue(pos, head, member)            \
    for (pos = __container_of(pos->member.next, pos, member);    \
         &pos->member != (head);                    \
         pos = __container_of(pos->member.next, pos, member))

#define list_for_each_entry_continue_reverse(pos, head, member)        \
    for (pos = __container_of(pos->member.prev, pos, member);    \
         &pos->member != (head);                    \
         pos = __container_of(pos->member.prev, pos, member))

#define list_for_each_entry_from(pos, head, member)            \
    for (;                                \
         &pos->member != (head);                    \
         pos = __container_of(pos->member.next, pos, member))

#endif

/* TEST

main.cpp:
#include<iostream>
#include"LinuxList.h"
#include<cstdio>

using namespace std;  

int main(void)
{
    struct Node
    {
        int value; 
        struct list_head head;
    };

    Node *m_list = (Node *)malloc(sizeof(Node));
    struct list_head *m_head = &m_list->head;
    Node *m_slider = NULL;   // 游标
    INIT_LIST_HEAD(m_head);

    for(int i=0; i<10; i++)
    {
        Node *temp_node = (Node *)malloc(sizeof(Node));
        temp_node->value = i;
        list_add_tail(&temp_node->head, m_head);
        cout << temp_node->value << endl;
    } 

    list_for_each_entry(m_slider, m_head, head)
    {
        int i = m_slider->value;
        cout << i << endl;
    }
    return 0;
} 

*/
View Code

内核链表真的厉害,同一个简单的代码包含了所有情况下的插入,删除,可能这就是真正的代码复用吧,而不是语法糖。

 

 

posted @ 2019-06-20 17:18  张不源  Views(2904)  Comments(0Edit  收藏  举报