文章目录

  • 1 静态单链表的出现原因
  • 2 静态单链表的实现思路
  • 3 继承关系图
  • 4 代码实现
  • 5 StaticLinkList需要增加析构函数吗

1 静态单链表的出现原因

如果需要频繁的删除元素,并且数据元素的最大个数固定,我们该怎么选择线性表呢?

很明显,当需要频繁的删除元素时,使用单链表是明智的选择。但是目前的单链表却有如下的缺陷:当我们长时间使用单链表对象频繁增加和删除元素时,可能会导致堆空间产生大量的内存碎片,导致系统运行缓慢。

由于数据元素的最大个数固定,我们可以设计一种新的线性表:
在单链表内部增加一片预留的空间,所有的Node对象都在这片空间中动态创建和动态销毁。


2 静态单链表的实现思路

  1. 通过模板定义静态单链表类(StaticLinkList)。
  2. 在类中定义固定大小的空间(unsigned char [])。
  3. 重写create和destroy函数,改变内存的分配和归还方式。
  4. 在Node类中重载operator new,用于在指定的内存上创建对象。

3 继承关系图


4 代码实现

StaticLinkList

#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H#include "Linklist.h"namespace LemonLib {template < typename T, int N >
class StaticLinkList : public LinkList<T>
{protected:/* 由于模板的二阶段编译,所以这里我们必须采用这种方式使用父类中的类型 */typedef typename LinkList<T>::Node Node;unsigned char m_space[sizeof(Node)*N];int m_used[N];/* 为了能够在指定的内存空间上调用构造函数,所以我们需要重载Node的new操作符 */struct SNode : public Node{/** 虽然new操作符返回的为void*类型,但编译器会自动处理类型问题* 需要注意的是,当new操作符返回null时,编译器就不会自动调用构造函数*/void* operator new(unsigned int size, void* loc){(void)size; // 避免编译器发出警告return loc;}};Node* create(){Node* ret = NULL;for (int i=0; i<N; i++){if (m_used[i] == 0){ret = reinterpret_cast<Node*>(m_space) + i;ret = new(ret) SNode(); // 调用构造函数m_used[i] = 1;break;}}return ret;}void destroy(Node* pn){SNode* spn = dynamic_cast<SNode*>(pn);   // static_cast用于有继承关系的对象指针之间的转换SNode* addr = reinterpret_cast<SNode*>(m_space);for (int i=0; i<N; i++){if (spn == (addr + i)){m_used[i] = 0;spn->~SNode();  // 调用析构函数break;}}}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 "Object.h"
#include "Exception.h"
#include "List.h"
#include "Seqlist.h"
#include "Staticlist.h"
#include "Dynamiclist.h"
#include "Staticarray.h"
#include "DynamicArray.h"
#include "Linklist.h"
#include "Staticlinklist.h"using namespace std;
using namespace LemonLib;int main()
{StaticLinkList<int, 5> list;for (int i=0; i<5; i++){list.insert(0, i);}for (list.move(0); !list.end(); list.next()){cout << list.current() << endl;}return 0;
}

5 StaticLinkList需要增加析构函数吗

当前实现版本的StaticLinkList类并无析构函数,对于如下代码:

构造比较简单,不用多说。对于析构来说,会自动调用父类的析构函数。而父类的析构函数直接调用了clear函数,在clear中调用destroy函数释放申请的空间。那么,思考如下问题:clear函数调用的真的是子类的destroy函数吗?

构造函数和析构函数中不会发生多态,不管是直接调用还是间接调用,所调用的都是当前类中实现的版本。 所以对于以上分析的问题,会调用父类的destroy函数,这将导致delete释放的有可能不是堆空间,会造成程序的不稳定。在实际工程开发中,这个问题必须避免。那么,我们有必要为StaticLinkList增加析构函数:

 ~StaticLinkList(){this->clear();}

在子类析构函数中完成空间的释放,那么在父类的析构函数中就不会再重复释放空间,如上问题也就完美的解决了。

StaticLinkList相关推荐

  1. java静态链表_数据结构笔记:静态链表(C语言)

    void CreateList(StaticLinkList *P)//创建一个静态链表 { int i; for(i=0;i此时并没有已占用空间,所以第一个节点中的指针(cur)的值为1,也就是说空 ...

  2. 典型问题分析(十五)

    在经过一段时间的编写,我们的数据结构库已经有了一定的规模.那么我们之前编写的代码就没有一点 bug 吗?之前每个代码都是经过测试了的,因此阔能是没有 bug 的,但是我们还是来对它进行分析,看看究竟是 ...

  3. 静态链表的插入和删除

    静态链表相当于是用一个数组来实现线性表的链式存储结构,在静态链表中操作的是数组. 结构体数组 一.静态链表的插入操作 静态链表的插入操作包含两部分,首先是获得空闲量的下标,程序代码如下; int ge ...

  4. 数据结构 - 静态单链表的实行(C语言)

    静态单链表的实现 1 静态链表定义 静态链表存储结构的定义如下: /* 线性表的静态链表存储结构 */ #define MAXSIZE 1000 /* 假设链表的最大长度是1000 */ typede ...

  5. 《大话数据结构》读书笔记-线性表

    写在前面:本文仅供个人学习使用.<大话数据结构>通俗易懂,适合整体做笔记输出,构建体系.并且文中很多图片来源于该书. 文章目录 3.2 线性表的定义 3.3 线性表的抽象数据类型 3.4 ...

  6. DualCircleList

    文章目录 1 Linux内核链表介绍 1.1 移植Linux内核链表 1.1.1 Linux内核链表的位置及依赖 1.1.2 移植时的注意事项 1.2 Linux内核链表剖析 1.2.1 Linux内 ...

  7. DualLinkList

    文章目录 1 单链表的缺陷 2 双向链表的实现 2.1 设计思路 2.2 双向链表的继承层次结构 2.3 DualLinkList的定义 2.4 双向链表的特点 3 代码实现 4 开放性问题 1 单链 ...

  8. CircleList

    文章目录 1 循环链表的实现 1.1 什么是循环链表 1.2 循环链表的逻辑构成 1.3 循环链表的继承层次结构 1.4 循环链表的实现思路 1.5 循环链表的实现要点 2 代码实现 3 循环链表的应 ...

  9. SharedPointer

    文章目录 1 继承关系类图 2 SharedPointer设计要点 3 代码实现 4 智能指针相关注意点 1 继承关系类图 2 SharedPointer设计要点 SharedPointer肯定是类模 ...

最新文章

  1. CMake命令之set_property和get_property
  2. 把Python的200个标准库分类整理了下,供参考
  3. go map并发写错误问题
  4. mysql集群mysql-cluster安装
  5. LeetCode : Binary Tree Paths
  6. android上最好的linux终端,如何在带有Termux的Android上使用Linux命令行 | MOS86
  7. Kali Linux 秘籍 第六章 漏洞利用
  8. 《软件建模与设计: UML、用例、模式和软件体系结构》一一3.2 设计验证和确认...
  9. 深度学习入门笔记(五):神经网络的学习
  10. vi/vim: 文件浏览和缓冲区浏览
  11. python的优点有哪些-Python为何这么火,究竟有哪些优势?
  12. Leetcode 931.下降路径最小和
  13. 动态代理 aop切面实现事务管理
  14. wps怎么生成html,wps如何自动生成页码 wps页码设置详细方法
  15. 修改注册表禁用谷歌浏览器提示保存密码
  16. NVIDIA显卡驱动更新方法
  17. 2021年中国百香果果汁进出口贸易分析:贸易逆差明显,越南是主要进口国[图]
  18. 倒计时 4天,COSCon'22 会议议程全览 精彩亮点抢鲜看!
  19. CHAR 和 VARCHAR 的区别?
  20. lepus mysql 复制监控_lepus 天兔监控Mysql部署

热门文章

  1. 列举ospf的5种报文类型_9种语言的应用场景,程序员的候选清单,你最看好哪一门语言...
  2. 【控制】《鲁棒控制-线性矩阵不等式处理方法》-俞立老师-第9章-时滞系统的分析和综合
  3. 2.14 向量化 Logistic 回归的梯度输出-深度学习-Stanford吴恩达教授
  4. 6.6 二分 K-Means 算法-机器学习笔记-斯坦福吴恩达教授
  5. 1.4 正规方程-机器学习笔记-斯坦福吴恩达教授
  6. 物联网云平台-贝壳物联入门详细使用方法
  7. 【树莓派】可能是最简单粗暴的树莓派搭建个人网站教程
  8. Qt中rcc工具简介
  9. 我的第一个Scrapy 程序 - 爬取当当网信息
  10. 入职五年回顾(十六) 2013年11月