这种块链栈在容量可以动态拓展的同时,节省了大量的new操作和delete操作,从而提高了效率.
template<typename T, int patchsize=128>//默认模板参数.
class patchstack
{
struct patch {
patch* lastptr, * nextptr;
T matters[patchsize];//不必用array.因为这个模板本身保存了size信息.
patch(patch* lastp) :lastptr(lastp), nextptr(nullptr) {}//不需要初始化matters.//注意一点:这不是一般的双向链表结构,而是这种栈专属的操作受限链表.
};
patch* const baseptr;//动态生成的头节点.一初始化就有了,不可更改.
patch* topptr;
int topcursor;//游标;待填充的位置.
static void vrtpop(patch*& vtopptr, int& vtopcursor)
{
if (vtopcursor == 0)
{
vtopptr = vtopptr->lastptr;
vtopcursor = patchsize;
}
--vtopcursor;
}
public:
void clean(void) { for (patch* ptr; (ptr = topptr->nextptr); topptr->nextptr = ptr->nextptr, delete ptr); }
void clear(void)
{
for (patch* ptr; (ptr = baseptr->nextptr); baseptr->nextptr = ptr->nextptr, delete ptr);
topptr = baseptr, topcursor = 0;
}
patchstack(void) :baseptr(new patch(nullptr)), topcursor(0) { topptr = baseptr; }
~patchstack(void) { clear(); delete baseptr; }
operator bool() { return topcursor != 0 || topptr != baseptr; }//一开始居然是这里有一处bug...(逻辑反了.)
void push(const T& matter)
{
if (topcursor == patchsize)
{
if (!topptr->nextptr)
{
topptr->nextptr = new patch(topptr);//只创建不销毁;只有调用clear,销毁base节点以外的所有资源.
}
topptr = topptr->nextptr;
topcursor = 0;
}
topptr->matters[topcursor++] = matter;
}
//不负责检查正确性.
//错误调用会简单地引发段错误(访问nullptr),这是一个非常良好的设计.
const T& topcref(void)const
{
patch* temptopptr = topptr; int temptopcursor = topcursor;
vrtpop(temptopptr, temptopcursor);
return topptr->matters[temptopcursor];
}
T& topref(void) { return const_cast<T&>(topcref()); }
void wpop(void) { vrtpop(topptr, topcursor); }
void pop(T& matter) { wpop(); matter = topptr->matters[topcursor]; }
T pop(void) { wpop(); return topptr->matters[topcursor]; }
};