线性表的链式存储结构(链表)

链表:基于来链式存储的线性表

链式逻辑存储结构:基于链式存储结构的线性表中,每个节点都包含数据域和指针域(数据域:存储数据元素本身。指针域:存储相邻节点的地址。)

   单链表:链表的每个节点只包含后一个元素的地址信息            

   循环链表:链表的最后一个元素的包含第一个元素的地址信息

   双向链表:链表的节点中包含后驱和前驱的地址信息

 链表基本概念: 头节点(辅助节点。不包含数据域,指针域指向第0个数据元素)+ 数据节点(数据域+地址域)+  尾节点(指针域为空或某一值,只有数据域)

 

单链表节点定义:

struct node: public TopClass   //
{
    T value;          //
    Node* next;    //
}

 单链表的表现形式:

 

 单链表操作:插入操作

 单链表的继承关系:

 

LinkList.h

/*
*   LinkList: 链表类
*    成员变量:
*            Node           节点
*            m_handler      头部辅助节点
*            m_length    节点数
*    成员函数:
*            create()    
*            destroy()    
*            
*            LinkList()    构造函数初始成员变量
*            insert()    参数判断,申请新节点,寻找节点,插入节点
*            remove()    参数判断,寻找节点,删除节点
*            set()        参数判断,寻找节点,设置节点值
*            get()        参数判断,寻找节点,获取节点值
*            length()    获取链表长度
*            clean()        释放所有节点空间
*            ~LinkList()    释放所有节点空间
*
*            move()         移动游标到指定位置
*            end()        判断游标是否到最后
*            current()    回去当前游标节点值
*            next()        移动步长的节点数
*/

#ifndef LINKLIST_H
#define LINKLIST_H

#include"List.h"
#include"Exception.h"

namespace DSL
{
    template <typename T>
    class LinkList : public List<T>
    {
        protected:
                struct Node : public TopClass
                {
                    T value;
                    Node* next;
                };
                //mutable Node m_handler; // 头节点中包含了数据域,当泛指类型中构造函数抛出异常时,此处会调用构造函数发生异常
                
                mutable struct : public TopClass // 继承顶层父类使得内存布局相同
                {
                    char reserved[sizeof(T)];
                    Node* next;
                }m_handler;
                
                int m_length;    // 链表长度
                int m_step;      // 游标每次移动数目
                Node* m_current; // 游标位置

                virtual Node* create(const T& value)
                {
                    Node* node = new Node();
                    node->value = value;
                    return node;
                }
                virtual void destroy(Node* node)
                {
                    delete node;
                }
        public:    
                LinkList()
                {
                    m_handler.next = NULL;
                    m_length = 0;
                    m_step = 1;
                    m_current = NULL;
                }

                bool insert(const T& obj)
                {
                    return insert(m_length,obj);
                }

                bool insert(int pos, const T& obj)
                {
                    bool ret = ((pos >= 0) && (pos <= m_length));
                    if(ret)
                    {
                        Node* node =create(obj);
                        if(node != NULL)
                        {
                            Node* current = reinterpret_cast<Node*>(&m_handler);
                            for(int i = 0; i < pos; i++)
                            {
                                current = current->next;
                            }
                            node->next = current->next;
                            current->next = node;
                            m_length++;
                        }
                        else
                        {
                            THROW_EXCEPTION(NotEnoughMemoryException,"error: no enough memory to create node!");
                        }
                    }
                    return ret;
                }

                bool remove(int pos)
                {
                    bool ret = ((pos >= 0) && (pos < m_length));
                    if(ret)
                    {
                        Node* current = reinterpret_cast<Node*>(&m_handler);
                        for(int i = 0; i < pos; i++)
                        {
                            current = current->next;
                        }
                        Node* toDel = current->next;
                        current->next = toDel->next;
                        destroy(toDel);
                        m_length--;
                    }
                    else
                    {
                        THROW_EXCEPTION(IdexOutOfBoundException,"error: index out of bound!");
                    }
                    return ret;
                }
                
                bool set(int pos,const T& obj)
                {
                    bool ret = ((0 <= pos) && (pos < m_length));
                    if(ret)
                    {
                        Node* current = reinterpret_cast<Node*>(&m_handler);
                        for(int i = 0; i < pos; i++)
                        {
                            current = current->next;
                        }
                        current->next->value = obj;
                    }
                    else
                    {
                        THROW_EXCEPTION(IdexOutOfBoundException,"error: index out of bound!");
                    }
                    return ret;
                }

                T get(int pos) const
                {
                    T ret;
                    get(pos, ret);
                    return ret;
                }

                bool get(int pos, T& obj) const
                {
                    bool ret = ((0 <= pos) && (pos < m_length));
                    if(ret)
                    {
                        Node* current = reinterpret_cast<Node*>(&m_handler);   //const成员函数不可以修改成员变量的值
                        for(int i = 0; i < pos; i++)
                        {
                            current = current->next;
                        }
                        obj = current->next->value;
                    }
                    else
                    {
                        THROW_EXCEPTION(IdexOutOfBoundException,"error: index out of bound!");
                    }
                    return ret;
                }

                int find(const T& obj) const
                {
                    int ret = -1;
                    Node* current = reinterpret_cast<Node*>(&m_handler);
                    current = current->next;
                    for(int i = 0; i <= m_length; i++)
                    {
                        if( current->value == obj)  // 当泛指类型为对象时,无法比较,要在TopClass中重载==操作符
                        {
                            ret = i;
                            break;
                        }
                        else
                        {
                            current = current->next;
                        }
                    }
                    return ret;
                }

                int length() const
                {
                    return m_length;
                }

                void clean()
                {
                    while(m_handler.next)
                    {
                        Node* toDel = m_handler.next;
                        m_handler.next = toDel->next;
                        delete toDel;
                    }
                    m_length = 0;
                }

                bool move(int addr) // 移动到addr节点
                {
                    bool ret = ((0 <= addr) && (addr < m_length));
                    if(ret)
                    {
                        Node* current = reinterpret_cast<Node*>(&m_handler);
                        for(int i = 0; i < addr; i++)
                        {
                            current = current->next;
                        }
                        m_current = current->next;
                    }
                    return ret;
                }

                bool end() // 判断游标是否在链表尾部
                {
                    return (m_current == NULL);
                }

                T current() //返回游标所在节点的值
                {
                    if(!end())
                    {
                        return m_current->value;
                    }
                    else
                    {
                        THROW_EXCEPTION(InvalidOperationException,"error: operation a no exit node!");
                    }
                }

                bool next(int step = 1) // 一次移动步长为m_step的节点
                {
                    bool ret = ((0 < step) && (step <= m_length));
                    if(ret)
                    {
                        int i = 0;
                        while((i < step) && (!end()))
                        {
                            m_current = m_current->next;
                            i++;
                        }
                        return (i == step);
                    }
                    else
                    {
                        THROW_EXCEPTION(InvalidOperationException,"error: operation node over max node number!");
                    }
                }
                
                ~LinkList()
                {
                    clean();
                }
    };

}

#endif
View Code

 

顺序表:访问需求较大的场合

单链表:数据频繁插入的场合

 

静态单链表:StaticLinkList

    数据最大元素固定且需要频繁的增删元素时采用静态单链表。

    实现原理:分配一个固定大小内存空间( m_pool[] ),所有节点从这里申请和归还(create()和destroy()),指定空间创建对象(重载new)。

        

 StaticLinkList.h

/*
*    StaticLinkList:静态单链表
*    成员变量:
*            Snode:        重载new的Node节点
*            m_pool[]:    固定大小内存池
*            m_flag[]:    标记使用了的节点
*    成员函数:
*            create()    内存池中申请节点空间
*            destroy()    返回节点空间到内存池
*
*            StaticLinkList()    初始化标记
*            capacity()            获取内存池大小
*            
*/

#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H

#include"LinkList.h"

namespace DSL
{
    template < typename T, int N >
    class StaticLinkList : public LinkList<T> 
    {
        protected:
            typedef typename LinkList<T>::Node Node;
            struct Snode : public Node
            {
                void* operator new (size_t size, void* addr)
                {
                    return addr;    
                }                
            };
            unsigned char m_pool[sizeof(Node) * N];
            char m_flag[N];
            
            Node* create()
            {
                Snode* addr = NULL;
                for(int i = 0; i < N; i++)
                {
                    if(m_flag[i] == 0)
                    {
                        addr = reinterpret_cast<Snode*>(m_pool + i*sizeof(Snode));
                        addr = new(addr) Snode(); // 从m_pool中申请节点空间,并调用构造函数
                        m_flag[i] = 1;
                        break;
                    }
                }
                return addr;
            }

            void destroy(Node* addr)
            {
                Snode* toDel = dynamic_cast<Snode*>(addr);
                for(int i = 0; i < N; i++)
                {
                    if(toDel ==  reinterpret_cast<Snode*>(&m_pool[i*sizeof(Node)]))
                    {
                        m_flag[i] == 0;
                        toDel->~Node();
                        break;
                    }
                }
            }

        public:
            StaticLinkList()
            {
                for(int i = 0; i < N; i++)
                {
                    m_flag[i] = 0;
                }
            }
            int capacity()
            {
                return N;
            }

            ~StaticLinkList()  // 默认析构函数调用父类LinkList的析构函数,会直接释放内存池的空间
            {
                this->clean(); // 调用父类的clean函数,会调用子类的destroy函数。
            }                   // 构造,析构函数调用的虚函数是调用当前类的实现的版本
        
    };
}

#endif
View Code

 

posted @ 2019-06-15 17:00  张不源  Views(1056)  Comments(0Edit  收藏  举报