zoukankan      html  css  js  c++  java
  • 线性表的链式存储结构(链表)

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

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

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

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

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

     链表基本概念: 头节点(辅助节点。不包含数据域,指针域指向第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
  • 相关阅读:
    day 03
    day 02
    day 02 作业
    day 01
    day 10 预科
    day 09作业 预科
    day 09 预科
    day 08作业 预科
    The word 'localhost' is not correctly spelled 这个问题怎么解决
    不能够连接到主机(名称为localhost)上的MySQL服务”
  • 原文地址:https://www.cnblogs.com/zsy12138/p/11028116.html
Copyright © 2011-2022 走看看