1、概念
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶(top),相对地,把另一端称为栈底(bottom)。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。【LIFO】“last in first out” 后进先出
【两种:顺序结构栈、链式结构栈】
2、栈的特点
1)栈是线性表,一种特殊线性表。特殊在于插入,删除位置
2)栈的插入操作:又称进栈,入栈等
3)栈的删除操作:又称出栈、弹栈等
4)Question:最先进栈的元素是不是只能最后出栈?
**答案:**肯定是不对的,因为栈只是对线性表的插入,删除操作位置进行限定,但是没有在时间上做出要求。如下所示,一种5种,这里只写了三种。
3、栈的抽象数据结构
1)常用操作
InitStack(*S); //初始化操作,建立一个空栈
DestroyStack(*S); //若栈存在,则销毁它
ClearStack(*S); //清空栈
StackEmpty(S); //判断栈是不是空的,true or flase
GetTop(S,*e); //若栈存在且非空,返回顶端元素
Push(*S,e); //若栈存在,则插入元素e,且使其成为顶端元素
Pop(*S,*e); //删除顶端元素,以e返回
StackLength(S); //返回栈中元素个数
4、栈的顺序存储结构
4.1)栈的结构代码
typedef int SElemType;
typedef int Status;
struct sqstack{
SElemType data[MAXSIZE];
int top; //用于栈顶指针
};
4.2)栈的初始化
void STACK::InitStack(sqstack *s) //初始化顺序栈
{
s->top = -1;
for (int i = 0; i < MAXSIZE - 1; i++)
s->data[i] = 0;
}
4.3)栈的插入
STACK::Status STACK::Push(sqstack *s, SElemType e)
{
if (s->top == MAXSIZE - 1) //若栈已经满了,抛出异常
return ERROR;
s->top++;
s->data[s->top] = e;
return OK;
}
4.4)栈的删除
STACK::Status STACK::Pop(sqstack *s, SElemType *e)
{
if (s->top == -1) //判断是不是空栈
return ERROR;
*e = s->data[s->top];
s->top--;
return OK;
}
4.5、两顺序结构栈空间共享
https://blog.youkuaiyun.com/weixin_43340991/article/details/86375829
//两栈(相同类型)栈空间共享
struct sqdoublestack{
SElemType data[MAXSIZE];
int top1; //用于栈1顶指针
int top2; //用于栈2顶指针
};
STACK::Status STACK::Push_Double(sqdoublestack *s, SElemType e, int stacknumber)
{
if (s->top1 + 1 == s->top2) //栈满
return ERROR;
if (stacknumber == 1) //表示栈1有元素进入
s->data[++s->top1] = e;
else if (stacknumber == 1)
s->data[--s->top2] = e;
return OK;
}
STACK::Status STACK::Pop_Double(sqdoublestack *s, SElemType *e, int stacknumber)
{
if (stacknumber == 1) //表示栈1有元素进入
{
if (s->top1 == -1)
return ERROR;
*e = s->data[s->top1--];
}
else if (stacknumber == 2) //表示栈1有元素进入
{
if (s->top1 == MAXSIZE)
return ERROR;
*e = s->data[s->top2++];
}
return OK;
}
5、链式存储结构栈
//栈的链式存储结构
struct stacknode{
SElemType data;
stacknode *next;
};
typedef stacknode *StackNodeptr; //定义指向结构体stacknode类型的指针
/*链式结构栈数据结构*/
struct LinkStack{
StackNodeptr top;
int count;
};
5.1 链式结构初始化
//栈的新元素插入操作
void LinkSTACK::InitStack(LinkStack *s)
{
s->top = NULL;
s->count = 0;
}
5.2 链式结构进栈操作
LinkSTACK::Status LinkSTACK::Push(LinkStack *s, SElemType e)
{
StackNodeptr p = new stacknode; //产生新节点
p->data = e; //新节点赋值数据
p->next = s->top; //新节点更新指针域
s->top = p;
s->count++;
return OK;
}
5.3 链式结构栈删除操作
LinkSTACK::Status LinkSTACK::Push(LinkStack *s, SElemType e)
{
StackNodeptr p = new stacknode; //产生新节点
p->data = e; //新节点赋值数据
p->next = s->top; //新节点更新指针域
s->top = p;
s->count++;
return OK;
}
6 链式与顺序存储结构栈完整代码
1)stack.h
#pragma once
namespace STACK{
#define MAXSIZE 10
typedef int SElemType;
typedef int Status;
struct sqstack{
SElemType data[MAXSIZE];
int top; //用于栈顶指针
};
//两栈(相同类型)栈空间共享
struct sqdoublestack{
SElemType data[MAXSIZE];
int top1; //用于栈1顶指针
int top2; //用于栈2顶指针
};
void InitStack(sqstack *);
Status Push(sqstack *, SElemType);
Status Pop(sqstack *, SElemType *);
Status StackLength(sqstack);
Status Push_Double(sqdoublestack *, SElemType, int);
Status Pop_Double(sqdoublestack *, SElemType *, int);
}
namespace LinkSTACK{
#define MAXSIZE 10
#define ERROR 0
#define OK 1
typedef int SElemType;
typedef int Status;
//栈的链式存储结构
struct stacknode{
SElemType data;
stacknode *next;
};
typedef stacknode *StackNodeptr; //定义指向结构体stacknode类型的指针
/*链式结构栈数据结构*/
struct LinkStack{
StackNodeptr top;
int count;
};
void InitStack(LinkStack *);
Status Push(LinkStack *, SElemType);
Status StackEmpty(LinkStack);
Status Pop(LinkStack *, SElemType *);
}
2)顺序存储栈代码stack.cpp
#include"iostream"
#include"stack.h"
using namespace std;
/*
InitStack(*S); //初始化操作,建立一个空栈
DestroyStack(*S); //若栈存在,则销毁它
ClearStack(*S); //清空栈
StackEmpty(S); //判断栈是不是空的,true or flase
GetTop(S,*e); //若栈存在且非空,返回顶端元素
Push(*S,e); //若栈存在,则插入元素e,且使其成为顶端元素
Pop(*S,*e); //删除顶端元素,以e返回
StackLength(S); //返回栈中元素个数
*/
//栈的顺序存储结构
#define ERROR 0
#define OK 1
void STACK::InitStack(sqstack *s) //初始化顺序栈
{
s->top = -1;
for (int i = 0; i < MAXSIZE - 1; i++)
s->data[i] = 0;
}
STACK::Status STACK::Push(sqstack *s, SElemType e)
{
if (s->top == MAXSIZE - 1) //若栈已经满了,抛出异常
return ERROR;
s->top++;
s->data[s->top] = e;
return OK;
}
STACK::Status STACK::Pop(sqstack *s, SElemType *e)
{
if (s->top == -1) //判断是不是空栈
return ERROR;
*e = s->data[s->top];
s->top--;
return OK;
}
STACK::Status STACK::StackLength(sqstack s)
{
if (s.top == -1)
return 0;
return s.top + 1;
}
STACK::Status STACK::Push_Double(sqdoublestack *s, SElemType e, int stacknumber)
{
if (s->top1 + 1 == s->top2) //栈满
return ERROR;
if (stacknumber == 1) //表示栈1有元素进入
s->data[++s->top1] = e;
else if (stacknumber == 1)
s->data[--s->top2] = e;
return OK;
}
STACK::Status STACK::Pop_Double(sqdoublestack *s, SElemType *e, int stacknumber)
{
if (stacknumber == 1) //表示栈1有元素进入
{
if (s->top1 == -1)
return ERROR;
*e = s->data[s->top1--];
}
else if (stacknumber == 2) //表示栈1有元素进入
{
if (s->top1 == MAXSIZE)
return ERROR;
*e = s->data[s->top2++];
}
return OK;
}
3)链式存储结构栈代码LinkStack.cpp
#include"iostream"
#include"stack.h"
using namespace std;
/*
InitStack(*S); //初始化操作,建立一个空栈
DestroyStack(*S); //若栈存在,则销毁它
ClearStack(*S); //清空栈
StackEmpty(S); //判断栈是不是空的,true or flase
GetTop(S,*e); //若栈存在且非空,返回顶端元素
Push(*S,e); //若栈存在,则插入元素e,且使其成为顶端元素
Pop(*S,*e); //删除顶端元素,以e返回
StackLength(S); //返回栈中元素个数
*/
//栈的新元素插入操作
void LinkSTACK::InitStack(LinkStack *s)
{
s->top = NULL;
s->count = 0;
}
LinkSTACK::Status LinkSTACK::Push(LinkStack *s, SElemType e)
{
StackNodeptr p = new stacknode; //产生新节点
p->data = e; //新节点赋值数据
p->next = s->top; //新节点更新指针域
s->top = p;
s->count++;
return OK;
}
LinkSTACK::Status LinkSTACK::StackEmpty(LinkStack s)
{
if (s.top == NULL)
return true;
return false;
}
LinkSTACK::Status LinkSTACK::Pop(LinkStack *s, SElemType *e)
{
StackNodeptr p ; //产生新节点
if (StackEmpty(*s)) //栈为空时
return ERROR;
*e = s->top->data;
p = s->top; //将删除的数据地址赋给指针p
s->top = p->next;
delete p;
s->count--;
return OK;
}