一、前言
前几天发了一篇关于模板类双向链表的文章,介绍了一些链表的基本情况,同时用c++的模板类实现了双向链表的基本结构和基础功能。
今天想要写一些使用双线链表实现栈和队列的内容。因为栈和队列的性质只需要在头或者尾处增减元素,所以相对于顺序表来说,链表更适合,能够轻松的实现动态的栈和队列。
linklist<>的代码实现可以参考之前的文章:c++模板类——双向链表的代码实现和讲解
二、代码演示及讲解
栈:
template<typename T>
class stack : private linklist<T>
{
public:
stack() :linklist<T>() {}
bool push(const T& val)
{
return linklist<T>::push_back(val);
}
bool pop()
{
if (linklist<T>::empty())
{
return false;
}
linklist<T>::erase(linklist<T>::end.prev);
return true;
}
T top()
{
if (linklist<T>::empty())
{
return *(new T(-1));
}
return linklist<T>::end.prev->element;
}
void output()
{
std::cout << "[";
linknode<T>* p = linklist<T>::head.next;
while (p != &(linklist<T>::end))
{
std::cout << p->element;
if (p != linklist<T>::end.prev) std::cout << ",";
p = p->next;
}
std::cout << "]\n";
}
bool empty()
{
return linklist<T>::__size == 0;
}
int size()
{
return linklist<T>::__size;
}
};
因为栈和队列的功能和链表相对比较重合,所以我直接用继承的方式来实现栈。
构造函数:
首先是栈的构造函数,不需要任何额外的操作,直接调用链表的默认构造函数就好了。
push:
栈每次加入新元素都放在尾端,因此可以直接调用链表的方法push_back来实现。
pop:
出栈时要先判断此时栈是否为空,调用父类的empty方法,如果为空直接返回false,不为空的话调用父类的erase方法删除掉最后一个节点。
top:
查看栈顶元素,也要用empty方法确认此时的栈是否为空,如果栈为空,返回-1。否则的话将最后一个结点的element返回。
output:
这个方法是用来检验栈中元素的方法,帮助开发者进行代码调试。
empty:
判断栈是否为空。
size:
返回栈中的元素个数。
队列:
template<typename T>
class queue :private linklist<T>
{
public:
bool empty()
{
return linklist<T>::__size == 0;
}
int size()
{
return linklist<T>::__size;
}
bool inque(const T& val)
{
return linklist<T>::push_back(val);
}
bool deque()
{
return linklist<T>::erase(linklist<T>::head.next);
}
T front()
{
if (linklist<T>::__size == 0)
{
return *(new T(-1));
}
return linklist<T>::head.next->element;
}
void output()
{
std::cout << "[";
linknode<T>* p = (linklist<T>::head).next;
while (p != &(linklist<T>::end))
{
std::cout << p->element;
if (p != linklist<T>::end.prev) std::cout << ",";
p = p->next;
}
std::cout << "]\n";
}
};
构造函数:
和栈一样,队列不需要额外的操作,只需要调用父类的默认构造函数。
inque:
入队方法,也就是将新的元素插入在链表的尾部,调用push_back方法。
deque:
如果链表不为空的话,将链表的第一个节点删除。
front:
如果链表不为空,返回链表的第一个节点的element。