栈的定义和特点
栈是限定仅在表尾进行插入删除的线性表;
对栈来说,表尾端有其特殊含义,称为“栈顶(top)”,相应的,表头端为栈底(bottom);
不含任何元素的空表,称为“空栈”;
因此,栈又称为“后进先出”
栈的表示和操作实现
和线性表类似,栈有两种存储方法,分别称为顺序栈和链栈;
栈的基本操作
“创建&销毁”
InitStack(&S) 初始化栈:构造一个空栈S,分配内存空间;
DestroyStack(&S) 销毁栈:销毁并释放栈S所占用的内存空间;
“增&删”
Push(&S, x) 进栈:若栈S未满,则将x加入使其成为新栈顶;
Pop(&S, &x) 出栈:若栈S非空,则弹出(删除)栈顶元素,并用x返回;
“查&其他”
GetTop(S, &x) 读取栈顶元素:若栈S非空,则用x-返回栈顶元素;(栈的使用场景大多只访问栈顶元素);
StackEmpty(S) 判空: 断一个栈S是否为空,若S为空,则返回true,否则返回false;
StackLength(S)求栈长度
ClearStack(S)栈置空操作
顺序栈操作与实现
- 顺序栈的存储结构
#define MAXSIZE 100
typedef struct{
SElemType *base;//栈底指针
SElemType *top;//栈顶指针
int stacksize;//栈可用最大容量
}SqStack;
- 初始化
Status InitStack(SqStack &S){
S.base=new SElemType[MAXSIZE];//分配一个最大容量空间
if(!S.base) exit(OVERFLOW);//存储分配失败
S.top=S.base;//栈顶指针等于栈底指针
S.stacksize=MAXSIZE;
return OK;
}
- 入栈
Status Pop(SqStack &S,SElemType &e){
if(S.top==S.base) return ERROR;//栈满
//e=*--S.top
--(S.top);
e=*S.top;
return OK;
}
- 出栈
Status Pop(SqStack &S,SElemType &e){
if(S.top==S.base) return ERROR;//栈满
//e=*--S.top
--(S.top);
e=*S.top;
return OK;
}
- 取栈顶元素
SElemType GetTop(SqStack S){
if(S.top!=S.base)
return *(S.top-1);
}
栈链操作与实现
通常链栈用单链表表示,只在链表头部进行操作;
以链表的头部作为栈顶较为方便,不需要附加一个头结点;
空栈相当于头指针指向空;
- 储存结构
typedef struct{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStack;
- 初始化
Status InitStack(LinkStack &S){
S=NULL;
return OK;
}
- 入栈
Status Push(LinkStack &S,SElemType e){
StackNode *p;
p=new StackNode; // 生成新节点p
p->data=e; // 将新节点数据域置为e
p->next=S; // 将新节点插入栈顶
S=p; // 修改栈顶指针
return OK;
}
- 出栈
Status Pop(LinkStack &S,SElemType &e){
if(S==NULL) return ERROR;
e=S->data;
StackNode *p;
p=S; //临时保存栈顶元素空间,以备释放
S=S->next; //修改栈顶指针
delete p;
return OK;
}
- 取栈顶元素
SElemType GetTop(LinkStack S){
if(S!=NULL){
return S->data;
}
}
栈完整代码
#include <iostream>
using namespace std;
#define MAX_SIZE 5 //数组大小
struct stack {
int top;
int ans[MAX_SIZE];
};
typedef struct stack Stack;
void InitStack(Stack *ptr) { //初始化栈
ptr->top = 0;
}
bool StackFull (Stack *ptr) { //判断栈是否满
if (ptr->top < MAX_SIZE)
return false;
else
return true;
}
bool StackEmpty (Stack *ptr) { //判断栈是否空
if (ptr->top == 0)
return true;
else
return false;
}
void Push(Stack *ptr, int item) { //入栈
if (StackFull(ptr))
cerr << "栈满,不能入栈!" << endl;
else {
ptr->ans[ptr->top] = item;
ptr->top ++;
}
}
int GetTop(Stack *ptr) { //返回栈顶值
return ptr->ans[ptr->top - 1];
}
int Pop(Stack *ptr) { //出栈,返回栈顶值
if (StackEmpty(ptr)) {
cerr << "栈空,不能出栈!" << endl;
return -1;
}
else
return ptr->ans[--ptr->top];
}
int StackSize (Stack *ptr) { //返回栈长度
if (ptr->top == 0)
return 0;
else
return ptr->top;
}
void ClearStack(Stack *ptr) { //清空栈
ptr->top = 0;
}
int main(){
Stack *ptr = (Stack *)malloc(sizeof(Stack));
InitStack(ptr); //初始化栈
//入栈
Push(ptr, 4);
Push(ptr, 10);
Push(ptr, 21);
Push(ptr, 19);
Push(ptr, 12);
Push(ptr, 13);
cout << "当前栈顶值为: " << GetTop(ptr) << endl;
cout << "当前栈顶指针为: " << ptr->top << endl; //输出栈顶值
cout << "当前栈长度为: " << StackSize(ptr) << endl;
cout << "栈顶出队: " << Pop(ptr) << endl; //出栈
cout << "当前栈长度为: " << StackSize(ptr) << endl;
ClearStack(ptr); //清空栈
cout << "清空栈后栈的长度为: " << StackSize(ptr) << endl;
return 0;
}
运行结果:栈满,不能入栈!
当前栈顶值为: 12
当前栈顶指针为: 5
当前栈长度为: 5
栈顶出队: 12
当前栈长度为: 4
清空栈后栈的长度为: 0
栈与递归
【算法步骤】
1、如果p为NULL,递归结束返回
2.否则输出p->data,p指向后继结点继续递归
void TraverseList(LinkList P)
{
if(p==NULL)
return; //递归终止
else
{
cout<<p->data<<end1; //输出当前结点的数据域
TraverseList (p->next); //p指向后继结点继续递归
}
}