1.栈
栈,又名堆栈,是一种运算受限的线性表,因为其仅允许在表的一端进行插入和删除。这一端被称为栈顶,相应的另一端被称为栈底。
按照先进后出的原则存储数据,最先进入的数据被压入栈底,最后进入的数据在栈顶。读取数据的时候从栈顶开始弹出数据。栈具有记忆作用,对栈插入与删除不需要改变栈底指针。
示意图:
栈的基本运算:
构造空栈:Init(S)、
判空: Empty(S)、
判满: Full(S)、
进栈: Push(S,x)、可理解为压入,这时栈中会多一个元素。
退栈: Pop(S) 、 可理解为弹出,弹出后栈中就无此元素。
取栈顶元素:StackTop(S),不同与弹出,只是使用栈顶元素的值,该元素仍在栈顶不会改变。
因为栈后进先出的操作方式,所以顺序表实现起来较为简单。
栈的模拟实现:
#pragma once
#include <string>
#include <iostream>
using namespace std;
//栈
//后进先出
template<class T>
class Stack
{
public:
Stack() //构造函数
:_a(NULL)
, _size(0)
, _capacity(0)
{}
//拷贝构造
//赋值运算符重载
//内置类型与string
~Stack() { //析构函数
if (_a) {
delete []_a;
_a = NULL;
}
}
public:
void Push(T a) { //压栈
CheckCapatcity();
_a[_size] = a;
_size++;
}
void Pop() { //出栈
if (Top != NULL) {
_size--;
}
}
size_t Size() { //返回大小
return _size;
}
bool Empty() { //判空
return Top == NULL;
}
T& Top() { //返回栈顶元素
return _a[_size - 1];
}
void Display() { //打印
size_t i = 0;
for (i = 0; i < _size; i++) {
cout << _a[i] << endl;
}
}
protected:
void CheckCapatcity() { //获取空间
if (_size == _capacity) {
size_t newCpaticy = _capacity == 0 ? 3 : _capacity * 2;
T* p1 = new T[newCpaticy];
//内置类型与string
size_t i = 0;
for (i = 0; i < _size; i++) {
p1[i] = _a[i];
}
delete _a;
_a = p1;
_capacity = newCpaticy;
}
}
protected:
T* _a;
size_t _size; //大小
size_t _capacity; //容量
};
2.队列
队列(Queue)也是一种运算受限的线性表,它的运算限制与栈不同,是两头都有限制,插入只能在表的一端进行(只进不出),而删除只能在表的另一端进行(只出不进),允许删除的一端称为队尾(rear),允许插入的一端称为队头 (Front)
因为尾插头删的特性,用链表实现起来更为简单一些,并用一个front指针和一个rear指针来维护数据:
实现操作:
判队空:Empty(Q)
判队满: Full(Q)
入队 :Push(Q,x)
出队 : Pop(Q)
#pragma once
#include <iostream>
#include <string>
#include <assert.h>
using namespace std;
//队列
//单链表实现
//先进先出
template<typename T>
class LinkQueue
{
public:
LinkQueue()
:_a(NULL)
,next(NULL)
{}
LinkQueue(const T& t)
:_a(t)
,next(NULL)
{}
~LinkQueue()
{}
public:
T _a;
LinkQueue *next;
};
template<typename T>
class Queue
{
public:
Queue()
:_front(NULL)
, _rear(NULL)
{}
void Push(T t) { //尾部插入
if (_front == NULL) //
{
_front = new LinkQueue<T>(t);
_rear = _front;
}
else {
_rear->next = new LinkQueue<T>(t);
_rear = _rear->next;
}
}
void Pop(){ //头部删除
assert(this->_front&&this->_rear);
if (_front == _rear) {
return;
}
LinkQueue<T> *cur = _front->next;
_front->next = cur->next;
delete cur;
cur = NULL;
}
size_t Size() {
assert(this);
size_t count = 1;
LinkQueue<T> *cur ;
cur = _front->next;
while (cur != NULL) {
cur = cur->next;
count++;
}
return count;
}
bool Empty(){
return _front == _rear;
}
~Queue(){
LinkQueue<T> *next = _front->next;
while (next != NULL) {
delete _front;
_front = next;
next = next->next;
}
}
T& Top() {
if (!Empty()) {
LinkQueue<T> * Node = _front->next;
return *(Node->_a);
}
return NULL;
}
public:
LinkQueue<T> *_front;
LinkQueue<T> *_rear;
};