单链表的一个缺陷
触发条件
- 长时间使用单链表对象频繁增加和删除元素
可能的结果
- 堆空间产生内存碎片,导致系统运行缓慢
新的线性表
设计思路
在“单链表”的内部增加一片预留的空间,所有的Node对象都在这片空间中动态创建和动态销毁
静态单链表的继承层次结构
静态单链表的实现思路
- 通过类模板定义静态单链表(StaticLinkList)
- 在类中定义固定大小的空间(unsigned char[])
- 重写 create 和 destroy 函数,改变内存的分配和归还方式
- 在 Node 类中重载 operator new,用于在指定内存上创建对象
编程实验:静态单链表的实现
文件:StaticLinkList.h
#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H
#include "LinkList.h"
#include <iostream>
using namespace std;
namespace DTLib
{
template <typename T, int N>
class StaticLinkList : public LinkList<T>
{
public:
StaticLinkList() // O(n)
{
for (int i=0; i<N; ++i)
{
m_used[i] = 0;
}
}
int capacity() // O(1)
{
return N;
}
protected:
//typedef typename LinkList<T>::Node Node;
using Node = typename LinkList<T>::Node;
struct SNode : public Node
{
void *operator new (unsigned int size, void *loc)
{
(void)size;
return loc;
}
};
unsigned char m_space[N * sizeof(SNode)];
char m_used[N];
Node *create() override // O(n)
{
SNode *ret = nullptr;
for (int i=0; i<N; ++i)
{
if (m_used[i] == 0)
{
ret = reinterpret_cast<SNode*>(m_space) + i;
ret = new(ret)SNode;
m_used[i] = 1;
break;
}
}
return ret;
}
void destroy(Node *pn) override // O(n)
{
SNode *space = reinterpret_cast<SNode*>(m_space);
SNode *psn = dynamic_cast<SNode*>(pn);
for (int i=0; i<N; ++i)
{
if (psn == (space + i))
{
m_used[i] = 0;
pn->~Node();
break;
}
}
}
};
}
#endif // STATICLINKLIST_H
文件:main.cpp
#include <iostream>
#include "StaticLinkList.h"
using namespace std;
using namespace DTLib;
int main()
{
cout << "main begin" << endl;
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;
}
cout << "main end" << endl;
return 0;
}
输出:
main begin
4
3
2
1
0
main end
答疑
LinkList 中封装 create 和 destroy 函数的意义是什么呢?
为静态单链表(StaticLinkList)的实现准备。
StaticLinkList 与 LinkList 的不同仅在于链表结点内存分配上的不同;因此将仅有的不同封装于父类和子类的虚函数中。
小结
- 顺序表与单链表相结合后衍生出静态单链表
- 静态单链表是LinkList的子类,拥有单链表的所有操作
- 静态单链表在预留的空间中创建结点对象
- 静态单链表适合于频繁增删元素的场合(最大元素个数固定)
以上内容整理于狄泰软件学院系列课程,请大家保护原创!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。