目录
一、栈
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
对于栈的实现一般采用的是数组或者链表来实现的。但是我们一般采用的是数组来实现,因为栈的特性是后入先出,采用下标访问,比链表找尾效率要高很多。
#include <iostream>
using namespace std;
template <class T>
class Stack
{
protected:
T *_stack;
int _top;
int _capacity;
public:
// 值得注意的是当top初始化为0时,为了表示为空栈,让数据的个数就是top的值,以示区分
Stack(int capacity = 0) : _stack(nullptr), _top(0), _capacity(capacity)
{
if (_capacity)
{
_stack = new T[_capacity];
}
}
~Stack()
{
if(_stack)
{
while(_top!=0)
{
cout << _stack[--_top] << endl;
}
delete[] _stack;
}
_stack = nullptr;
}
void Push(T data)
{
// 进来先判断栈容量,为0就设置初始值,非0就扩2倍
if (_capacity == _top)
{
int new_capacity = _capacity == 0 ? 4 : _capacity * 2;
T *tmp = new T[new_capacity];
// 有数据就先挪动数据
for (int i = 0; i < _capacity; i++)
{
tmp[i] = _stack[i];
}
// 判断_stack是否为空,非空就释放掉权限
if (_stack)
{
delete[] _stack;
}
// 将tmp指向的栈交给_stack
_capacity = new_capacity;
_stack = tmp;
}
// 数据进栈(由于_top是从0开始的,所以是先使用,再自增)
_stack[_top++] = data;
}
// 数据出栈
void Pop()
{
// 注意 考虑_top自减后的结果,当_top为0时才能说栈已空,栈顶的元素的序号_top-1
if (_top > 0)
_top--;
else
{
cout << "Stack is empty!" << endl;
}
}
T Top()
{
if(_top>0)
{
return _stack[_top - 1];
}
cout << "No Data!" << endl;
return 0;
}
size_t size()
{
return _top;
}
bool empty()
{
return _top == 0;
}
};
二、队列
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,挪动数据效率比较低,链表更适合对头部进行操作。
#include <iostream>
using namespace std;
// 队列是一个先进先出FIFO的结构
template <class T>
struct Node
{
Node<T> *next;
T data;
Node(T _data = T()) : data(_data), next(nullptr) {}
};
template <class T>
class Queue
{
protected:
Node<T> *pHead;
Node<T> *pTail;
size_t size;
public:
Queue() : pHead(nullptr), pTail(nullptr),size(0) {}
~Queue()
{
while(!Empty())
{
Pop();
}
}
// 尾插
void Push(T data)
{
if (pHead == nullptr)
{
Node<T> *newNode = new Node<T>(data);
pHead = pTail = newNode;
}
else
{
Node<T> *newNode = new Node<T>(data);
if(pHead==pTail)
{
pHead->next = newNode;
pTail = newNode;
}
pTail->next = newNode;
pTail = newNode;
}
size++;
}
// 头删
void Pop()
{
if (pHead == pTail)
{
if (!pHead)
{
cout << "Queue is empty" << endl;
return;
}
else
{
delete pHead;
pHead = pTail = nullptr;
size--;
}
}
else
{
Node<T> *newHead = pHead->next;
delete pHead;
pHead = newHead;
size--;
}
}
T Front()
{
if (pHead == nullptr)
{
cout << "Queue is empty" << endl;
return NULL;
}
else
{
return pHead->data;
}
}
T Back()
{
if (pHead == nullptr)
{
cout << "Queue is empty" << endl;
return NULL;
}
else
{
return pTail->data;
}
}
size_t Size()
{
return size;
}
bool Empty()
{
return size == 0;
}
};
之后,会将循环队列单独列出来。