• 循环单链表(链表)


    双链表:插入节点时和删除节点时注意位置为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

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

     

  • 相关阅读:
    Lucene学习总结之七:Lucene搜索过程解析
    Lucene学习总结之六:Lucene打分公式的数学推导
    Lucene学习总结之五:Lucene段合并(merge)过程分析
    Lucene学习总结之四:Lucene索引过程分析
    Lucene学习总结之三:Lucene的索引文件格式(1)
    Lucene学习总结之二:Lucene的总体架构
    Lucene学习总结之一:全文检索的基本原理
    解决Eclipse中文乱码
    【Lucene4.8教程之五】Luke
    【Tika基础教程之一】Tika基础教程
  • 原文地址:https://www.cnblogs.com/zsy12138/p/11059994.html
Copyright © 2020-2023  润新知