基本描述
生活当中只有一个出口的瓶子,装羽毛球的筒子,玩具枪有子弹的弹夹, 水枪 管道,北京胡同 水龙头 等等
游戏:老鹰捉小鸡
无论你怎么抓小只因都是抓取最后一个
出口 只有一个,入口也只有一个 尾部
栈原理精讲
栈是一个后进先出 的一种数据结构,
栈:受限线性结构;
栈::只允许后面出栈 后面入栈
栈的底部叫栈底
栈的顶部叫栈顶
出栈的时候有两种方法:
物理删除,逻辑删除
所谓的物理删除 该怎么删除就这么删除
逻辑删除:不去直接删除 而是直接访问下一个元素 所谓的:忽略 不去直接删除 好处 避免了大量的移动 效率高
**栈不支持遍历的操作 **
栈的算法实现:
顺序栈
顺序栈:用顺序表来做的栈 效果如上
初始化栈
尾部添加元素(往后添加)
尾部删除元素(逻辑删除)
访问栈顶
获取栈的元素个数
顺序栈
//元素类型
using ElementType = user-defined;
//顺序栈辅助
struct _SeqStackAuxiliary {
ElementType* top;//栈顶元素
ElementType* back;//插入元素
};
//顺序栈辅助
using SeqStackAuxiliary = struct _SeqStackAuxiliary;
//顺序栈
struct _SeqStack {
ElementType* element;
size_t Size;
SeqStackAuxiliary Auxiliary;
};
using SeqStack = struct _SeqStack;
//最大的顺序栈元素大小
const size_t SeqStackMaxSize = 1000;
顺序栈 操作算法声明
//初始化顺序栈
void initStack(SeqStack& Stack);
//入栈
void push_Stack(SeqStack& Stack, const ElementType& e);
//访问栈顶元素
ElementType& TopStack(SeqStack& Stack);
//顺序栈已满
bool fullStack(const SeqStack& Stack);
//顺序栈已空
bool emptyStack(const SeqStack& Stack);
//出栈
void pop_Stack(SeqStack& Stack);
//栈元素大小
const size_t& StackSize(const SeqStack& Stack);
//销毁顺序栈
void destroyStack(SeqStack& Stack);
//顺序栈辅助
SeqStackAuxiliary这个好像没有见过 全网的文章都没有 那是要不然怎么做原创嘛,
从定义来看
ElementType* top;//方便访问栈顶元素
ElementType* back;//方便添加元素
#include "SeqStack.h"
#include<stdexcept>
const size_t zero = 0u;
void initStack(SeqStack& Stack){
Stack.element = new ElementType[SeqStackMaxSize];
Stack.Size = zero;
Stack.Auxiliary = {
Stack.element,Stack.element };
}
void push_Stack(SeqStack& Stack, const ElementType& e){
const bool FullStack = fullStack(Stack);
if (!FullStack) {
*Stack.Auxiliary.back = e;
Stack.Auxiliary.top= ++Stack.Auxiliary.back;
++Stack.Size;
}
}
ElementType& TopStack(SeqStack& Stack){
const bool EmptyQueue = emptyStack(Stack);
ElementType* &top= --Stack.Auxiliary.top;
if (EmptyQueue) {
terminate();
}
return*top;
}
bool fullStack(const SeqStack& Stack){
return Stack.Size == SeqStackMaxSize;
}
bool emptyStack(const SeqStack& Stack){
return !Stack.Size;
}
void pop_Stack(SeqStack& Stack){
const bool EmptyQueue = emptyStack(Stack);
size_t& size = Stack.Size;
const ElementType* full = Stack.element + SeqStackMaxSize;
if (!EmptyQueue) {
if (Stack.Auxiliary.back == full) {
destroyStack(Stack);
terminate();
}
--size;
--Stack.Auxiliary.back;
return;
}
destroyStack(Stack);
terminate();
}
const size_t& StackSize(const SeqStack& Stack){
return Stack.Size;
}
void destroyStack(SeqStack& Stack){
delete[] Stack.element;
Stack.element = nullptr;
Stack.Size = zero;
Stack.Auxiliary = {
};
}
链式栈
链式栈以链表基础之上维护一个队列统称为:“链式栈”
如图:
可以看到链式栈是头部插入头部删除. -极简的方式
当然也可以从尾部插入,尾部删除 但需要找到尾部的前驱结点 然后让他的下一个指向尾部的下一个
效率大大的下降 所以采用头部插入头部删除
当然也有双向的的实现
链式栈声明
//元素类型
using ElementType = use defined;
using LinkListNode = struct _LinkListNode;
struct _LinkListNode {
ElementType value;
LinkListNode* next;
};
//链式栈辅助
struct _ListStackAuxiliary {
LinkListNode* back;
};
using ListStackAuxiliary = struct _ListStackAuxiliary;
//链式栈
struct _ListStack {
LinkListNode* List;
size_t size;
ListStackAuxiliary Auxiliary;
};
//链式栈
using ListStack = struct _ListStack;
//最大的链式栈元素大小
const size_t ListStackMaxSize = 1000;
链式栈 操作算法声明
//初始化链式栈
void initStack(ListStack