C++数据结构第25课、静态单链表的实现

  • 单链表的一个缺陷
    — 触发条件
    长时间使用单链表对象频繁增加和删除数据元素
    — 可能的结果
    堆空间产生大量的内存碎片,导致系统运行缓慢
  • 新的线性表
    在这里插入图片描述
  • 静态单链表的继承层次
    在这里插入图片描述
  • 静态单链表的实现思路
    — 通过模板定义静态单链表类(StaticLinkList
    — 在类中定义固定大小的空间(unsigned char[])
    — 重写 create 和 destroy 函数,改变内存的分配和归还方式
    — 在 Node 类中重载 operator new ,用于指定内存上创建对象

StaticLinkList.h

#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H
#include "LinkList.h"


namespace DTLib
{

template<typename T, int N>
class StaticLinkList : public LinkList<T>
{
protected:
    typedef typename LinkList<T>::Node Node;

    unsigned char m_space[sizeof(typename LinkList<T>::Node) * N];
    int m_used[N];

    struct SNode : public Node
    {
        void* operator new(unsigned int size, void* loc)
        {
            (void)size;
            return loc;
        }
    };

    SNode* creat()
    {
        SNode* ret = NULL;
        for(int i = 0; i < N; i++)
        {
            if(!m_used[i])
            {
                ret = reinterpret_cast<SNode*>(m_space)+i;
                ret = new(ret)SNode();
                m_used[i] = 1;
                break;
            }

        }
        return ret;
    }

    void destroy(Node* pn)
    {
        SNode* space = reinterpret_cast<SNode*>(m_space);
        SNode* pst = dynamic_cast<SNode*>(pn);
        for(int i = 0; i < N; i++)
        {
            if(pst == (space + i))
            {
                m_used[i] = 0;
                pst->~SNode();
            }
        }
    }

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

    int capacity()
    {
        return N;
    }
};

}
#endif // STATICLINKLIST_H

main.cpp

#include <iostream>
#include "StaticLinkList.h"
using namespace std;
using namespace XiebsLib;

int main()
{
    StaticLinkList<int, 5> list;

    for(int i = 0; i < 5; i++)
    {
        list.insert(0, i);
    }

    for(list.move(0, 1); !list.end(); list.next())
    {
        cout << list.current() << endl;
    }

    try
    {
        list.insert(1);
    }
    catch (const Exception& obj)
    {
        cout << obj.message() << endl;
        cout << obj.location() << endl;
    }


    return 0;
}

在这里插入图片描述

静态单链表的原理:

其实它的原理等同于我们前面在C++课程里面学的 重写 new 操作符(69课自定义内存管理),使得它可以在栈上,静态存储空间等等里面申请内存空间。当我们使用关键字 new 在堆上动态创建一个对象时,它实际上做了三件事:1、获得一块内存空间、2、调用构造函数、3、返回正确的指针。
从代码的1-15行都是基本操作,不用过多解释。在重写 create() 函数时,下面两条语句是我思考的最久的两条语句。

ret = reinterpret_cast<SNode*>(m_space) + i;
ret = new(ret)SNode;

第一句其实就是获得一段内存空间,但是它只涉及指针的移动,并不能去调用构造函数,如果它无法调用构造函数,那么 Node 这个节点结构体的成员变量就无法正确的初始化,这就是为什么我们要重新定义一个 SNode 的节点结构体继承于Node,重写 new 操作符,在重载函数里只返回地址不进行内存操作,使得 ret = new(ret)SNode; 这条语句的意思是在ret 这个地址上调用构造函数,最终返回ret的值。SNode 调用了构造函数,那么它的父类 Node 也会调用构造函数,使得Node 结构体内部的成员变量会被正确的初始化。
在这里插入图片描述

  • 小结
    顺序表和单链表结合后衍生出静态单链表
    — 静态单链表是 LinkList 的子类,拥有单链表的所有操作
    — 静态单链表在预留的空间中创建节点对象
    — 静态单链表适合于频繁增删数据元素的场合(最大元素个数固定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值