栈的定义
栈是一种只能在一端进行插入或删除操作的线性表。 表中允许进行插入、删除作的一端称为栈顶.栈顶的当前位置是动态的,栈顶的当前位置由一个称为栈顶指针的位置指示器指示。表的另一端称为栈底。当栈中没有数据元素时,称为空栈。栈的插入操作通常称为进栈或入栈,栈的删除操作通 常称为退栈或出栈。
特点:是“后进先出”,即后进栈的元素先出栈。
栈的顺序存储结构
顺序栈:利用顺序存储方式实现的栈称为顺序栈
先来定义一下顺序栈的数据类型
typedef struct {
int data[maxsize];
int top; //栈顶指针
} SqStack;
栈的几种基本运算如下:
-
InitStack(&s):初始化栈。构造一个空栈s。
void InitStack(SqStack *&s){ s=(SqStack*)malloc(sizeof(SqStack)); s->top = -1;//开始是空栈 } // 栈空条件:top=-1 //栈满条件:top=MaxSize-1 //进栈e操作:top++; 将e放在top处 //退栈操作:从top处取出元素e; top--;
-
DestroyStack(&s):销毁栈。释放栈s占用的存储空 间。
void ClearStack(SqStack *&s){ free(s); }
-
StackEmpty(s):判断栈是否为空:若栈s为空,则 返回真;否则返回假。
bool IsEmpty(SqStack *s){ return (s->top==-1); }
-
Push(&S,e):进栈。将元素e插入到栈s中作为栈顶 元素。
在栈不满的条件下,先将栈指针增1,然后在该位置上插 入元素ebool Push(SqStack *&s,int e){ if (s->top==maxsize-1) return false;//已经满了 else{ s->top++; s->data[s->top]=e; return true; } }
-
Pop(&s,&e):出栈。从栈s中退出栈顶元素,并将 其值赋给e。
bool Pop(SqStack *&s, int &e){ if(s->top==-1) return false;//空栈 else{ e=s->data[s->top]; s->top--; return true; } }
-
GetTop(s,&e):取栈顶元素。返回当前的栈顶元素, 并将其值赋给e
bool GetTop(SqStack *s,int &e) { if (s->top==-1) //栈为空的情况,即栈下溢出 return false; e=s->data[s->top]; //取栈顶指针元素的元素 return true; }
看完上面的封装好的函数,我们把代码整合在一起操作一下
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
const int maxsize = 10;
typedef struct {
int data[maxsize];
int top; //栈顶指针
} SqStack;
void InitStack(SqStack *&s){
s=(SqStack*)malloc(sizeof(SqStack));
s->top = -1;//开始是空栈
}
// 栈空条件:top=-1
//栈满条件:top=MaxSize-1
void ClearStack(SqStack *&s){ free(s);
bool IsEmpty(SqStack *s){ return (s->top==-1); }
bool Push(SqStack *&s,int e){
if (s->top==maxsize-1)
return false;//已经满了
else{
s->top++;
s->data[s->top]=e;
return true;
}
}
bool Pop(SqStack *&s, int &e){
if(s->top==-1)
return false;//空栈
else{
e=s->data[s->top];
s->top--;
return true;
}
}
bool GetTop(SqStack *s,int &e) {
if (s->top==-1) //栈为空的情况,即栈下溢出
return false;
e=s->data[s->top]; //取栈顶指针元素的元素
return true;
}
int main(){
SqStack *z;
int s,p,e;
int a[]={12,5,8,1,7,5,4,6,20};
InitStack(z);
if(IsEmpty(z))
s=0;
else
s=1;
printf("%d\n",s);
for(int i=0;i<9;i++)
Push(z,a[i]);
GetTop(z,e);
printf("%d\n",e);
for(int i=0;i<2;i++){
Pop(z,e);
printf("%d\n",e);
}
}
栈的链式存储结构
链栈**:利用单链表存储方式实现的栈称为顺序栈
链栈的优点是不存在栈满上溢的情况
先来定义一下链栈的数据类型
typedef struct linknode {
int data; //数据域
struct linknode *next; //指针域
} LiStack;
栈的几种基本运算如下:
-
InitStack(&s):初始化栈。构造一个空栈s。
void InitStack(LiStack *&s){ s=(LiStack*)malloc(sizeof(LiStack)); s->next = NULL; } //栈空条件:s->next=NULL //栈满条件:不考虑
-
DestroyStack(&s):销毁栈。释放栈s占用的存储空 间。
void ClearStack(LiStack *&s){ LiStack *p=s,*q=s->next; while(q!=NULL){ free(p); p=q; q=q->next; } free(p);//把尾节 }
-
DestroyStack(&s):销毁栈。释放栈s占用的存储空 间。
void ClearStack(LiStack *&s){ LiStack *p=s,*q=s->next; while(q!=NULL){ free(p); p=q; q=q->next; } free(p);//把尾节点也释放 }
-
StackEmpty(s):判断栈是否为空:若栈s为空,则 返回真;否则返回假。
bool IsEmpty(LiStack *s){ return (s->next==NULL); }
-
Push(&S,e):进栈。将元素e插入到栈s中作为栈顶 元素。
在栈不满的条件下,先将栈指针增1,然后在该位置上插 入元素evoid Push(LiStack *&s,int e){ LiStack *p; p = (LiStack*)malloc(sizeof(LiStack)); p->data =e; p->next = s->next; s->next = p; }
-
Pop(&s,&e):出栈。从栈s中退出栈顶元素,并将 其值赋给e。
bool Pop(LiStack *&s, int &e){ LiStack *p; if(s->next==NULL) return false;//空栈 else{ p=s->next; e=p->data; s->next = p->next; free(p); return true; } }
-
GetTop(s,&e):取栈顶元素。返回当前的栈顶元素, 并将其值赋给e。
bool GetTop(LiStack *s,int &e) { if (s->next==NULL) //栈空的情况 return false; e=s->next->data; return true; }
一般的多用的是顺序栈,对于链栈的使用不多,链栈具体代码整合于顺序栈类似,这里就不再赘述。