栈和队列(一)
栈
()
从图 我们看到,栈存储结构与之前所学的线性存储结构有所差异,这缘于栈对数据 “存” 和 “取” 的过程有特殊的要求:
(1)栈只能从表的一端存取数据,另一端是封闭的,如图 1 所示;
(2)在栈中,无论是存数据还是取数据,都必须遵循"先进后出"的原则,即最先进栈的元素最后出栈。拿图 1 的栈来说,从图中数据的存储状态可判断出,元素 1 是最先进的栈。因此,当需要从栈中取出元素 1 时,根据"先进后出"的原则,需提前将元素 3 和元素 2 从栈中取出,然后才能成功取出元素 1。
因此,我们可以给栈下一个定义,即栈是一种只能从表的一端存取数据且遵循 “先进后出” 原则的线性存储结构。
通常,栈的开口端被称为栈顶;相应地,封口端被称为栈底。因此,栈顶元素指的就是距离栈顶最近的元素,拿图 2 来说,栈顶元素为元素 4;同理,栈底元素指的是位于栈最底部的元素,图 2 中的栈底元素为元素 1。
进栈和出栈
基于栈结构的特点,在实际应用中,通常只会对栈执行以下两种操作:
向栈中添加元素,此过程被称为"进栈"(入栈或压栈);
从栈中提取出指定元素,此过程被称为"出栈"(或弹栈)
顺序栈
//栈
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
#define MaxSize 100
typedef struct{
ElemType data[MaxSize];
int top;
}SeqStack;
//置空栈
SeqStack *InitStack(){
SeqStack *s;
s=(SeqStack *)malloc(sizeof(SeqStack));
s->top =-1;
return s;
}
//判空栈
int Empty(SeqStack *s){
if(s->top ==-1)
return 1;
return 0;
}
//入栈
int Push(SeqStack *s,ElemType x){
if(s->top == MaxSize-1)
return 0; //栈满不能入栈
else{
s->data[++(s->top )]=x;
return 1;
}
}
//出栈
int Pop(SeqStack *s,ElemType *x){
if(Empty(s) )
return 0; //栈空不能出栈
else{
*x=s->data[s->top --];
return 1;
}
}
//取栈顶元素
ElemType GetTop(SeqStack *s){
if(Empty(s))
return 0;
else
{
return(s->data [s->top ]);
}
}
int main(){
SeqStack *s=InitStack();
printf("%d\n",Empty(s));
int a=1,b=2;
printf("%d\n",Push(s,a));
printf("%d\n",Push(s,b));
int *x;
x=(int *)malloc(sizeof(int));
Pop(s,x);
printf("%d",*x);
}
顺序栈(共享)
//多栈共享邻接空间
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
#define MaxSize 100
typedef struct{
ElemType data[MaxSize];
int Ltop;
int Rtop;
}DupStack;
//初始化操作
DupStack *InitDupStack(){
DupStack *s;
//创建两个共享邻接空间的空栈由指针s指出
if((s=(DupStack *)malloc(sizeof(DupStack)))==NULL)
return NULL;//指针开辟空间失败
s->Ltop =-1;
s->Rtop =MaxSize;
return s;
}
//入栈操作
int PushDupStack(DupStack *s,char status,ElemType x){
//把数据压入左栈或者右栈
if(s->Ltop +1==s->Rtop ){
printf("栈满");
return -1;//栈满
}
else if(status=='L'){
s->data[++s->Ltop ]=x;
}
else if(status=='R')
s->data[--s->Rtop ]=x;
else
return -1;
return 1;
}
//出栈操作
ElemType PopDupStack(DupStack *s,char status){
//从左栈(status=='L')或者右栈(status=='R')退出栈顶元素
if(status == 'L')
{
if(s->Ltop <0) return NULL; //左栈为空
else return(s->data[s->Ltop --]);
}
else if(status == 'R'){
if(s->Rtop>MaxSize-1 ) return NULL;// 右栈为空
else return(s->data[s->Rtop++ ]);
}
else return NULL;//参数错误
}
int main(){
DupStack *s;
s=InitDupStack();//初始化;
int a=1,b=2;
char L='L',R='R';
PushDupStack(s,L,a);
PushDupStack(s,L,b);
PushDupStack(s,R,b);
PushDupStack(s,R,a);
printf("%d",PopDupStack(s,R));
}
链栈
//链栈
#include<stdio.h>
#include<stdlib.h>
typedef struct StackNode{
int data;
struct StackNode *next;
}slStacktype;
//入栈
int PushStack(StackNode *top,int x){
StackNode *p;
p=(StackNode *)malloc(sizeof(StackNode));
p->next =NULL;
if(!p)
return -1;
p->data =x;
p->next =top->next ;
top->next = p;
return 1;
}
//出栈
int PopStack(slStacktype *top)
{
slStacktype *p;
int x;
if(!top->next )
{
printf("空栈");
return -1;
}
p=top->next ;
top->next =p->next ;
x=p->data ;
free(p);
return x;
}
int main()
{
StackNode *top=(StackNode *)malloc(sizeof(StackNode));
top->next =NULL;
int x=5;
int n=PushStack(top,x);
printf("%d\n",n);
printf("%d",PopStack(top));
}
环队
增设tag数据成员以区分队满还是队空
tag表示0的情况下,若因删除导致front==rear,则队空;
tag等于1的情况,若因插入导致front==rear则队满
//队列(循环队列防止假溢出)
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
typedef int ElemType;
typedef struct{
ElemType elem[MAXSIZE];
int rear; //队尾
int front; //队头
int tag; //判断队空与队满
}CSeQueue;
//置空队
CSeQueue *InitSeQueue(){
CSeQueue *q;
q=((CSeQueue *)malloc(sizeof(CSeQueue)));
q->front =q->rear =MAXSIZE-1;
return q;
}
//入队
int InSeQueue(CSeQueue *q,ElemType x){
if((q->rear +1)%MAXSIZE==q->front )//队满不能入队
{
printf("队满");
return -1;
}
else{
q->rear =(q->rear +1)%MAXSIZE;
q->elem [q->rear ]=x;
q->tag=1;
return 1; //成功入队
}
}
//出队
int OutSeQueue(CSeQueue *q,ElemType *x){
if(q->front ==q->rear )
{
printf("队空");
return -1;
}
else
{
q->front =(q->front +1)%MAXSIZE;
*x=q->elem [q->front ];
q->tag =0;
return 1 ;// 出队成功
}
}
//判队空
int EmptySeQueue(CSeQueue *q){
if(q->front ==q->rear&&q->tag==0 )
return 1;
return -1;
}
int main(){
}