栈是一种常用的数据结构,简单的可以说是一种受限操作的线性表。下面就对栈的各种操作做一个总结。
栈的定义:栈是一种只能限制在一端进行操作的线性表。允许操作的一段成为栈顶,另一端成为栈低。没有元素的时候,为空栈;有元素的时候,如果元素出栈,那么在栈顶的顺序是后进先出。
栈的存储结构:
栈有三种存储结构:顺序静态存储结构、顺序动态存储结构和链式存储结构。
顺序静态存储结构:即存储结构大小在一开始就定义好,在以后的运算操作过程中,只是向已经分配的存储结构空间存放内容。
#define ElemType int
#define STACKSIZE 10//开始定义分配空间的大小
定义:
//栈静态顺序存储结构
typedef struct
{
ElemType elem[STACKSIZE];
int top;//指向栈顶的指针
}SqStack;
| |
操作:
(1) 静态栈的初始化
int initStack(SqStack &s)
{
//这里因为静态数据结构里面定义的数据是一个数组,所以不需要额外的使用malloc给数组元素分配空间
s.top=-1;//初始化为-1
return OK;
}
| |
(2) 静态栈的入栈操作
int pushStack(SqStack &s, ElemType &e)
{
if(s.top==-1)
{
cout<<"stack is NULL\n";
return ERROR;
}
s.top--;
e=s.elem[s.top];
return OK;
}
| |
(3) 静态栈的出栈操作
int popStack(SqStack &s, ElemType &e)
{
if(s.top>=STACKSIZE)
{
cout<<"stack is full\n";
return ERROR;
}
s.top++;
s.elem[s.top]=e;
return OK;
}
| |
顺序动态存储结构:在栈的一开始分配一定大小的空间,如果后面不够空间,可以动态分配。
定义:
#define STACK_INIT_SIZE 100 //开始分配空间的大小
#define STACK_INCREAMENT 10//动态分配追加的空间大小
//栈动态顺序存储结构
typedef struct
{
ElemType*top;//指向栈顶的指针
ElemType*base;//指向栈底的指针
intstacksize;
}SqDymaticStack;
操作:
(1)动态栈的初始化
int initStackDymatic(SqDymaticStack &s)
{
ElemType *p=NULL;
p=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));
if(p==NULL)
{
cout<<"alocate memory faile\n";
return ERROR;
}
s.base=s.top=p;
s.stacksize=STACK_INIT_SIZE;
return OK;
}
|
(2)动态栈的入栈操作
|
int pushStackDymatic(SqDymaticStack &s, ElemType &e)
{
if(s.top-s.base>=s.stacksize)
{ s.base=(ElemType*)realloc(s.base,(STACK_INIT_SIZE+STACK_INCREAMENT)*sizeof(ElemType));
if(s.base==NULL)return ERROR;
}
s.top++;
*s.top=e;
s.stacksize+=STACK_INCREAMENT;
return OK;
}
| (3)动态栈的出栈操作 |
(3)动态栈的出栈操作
int popStackDymatic(SqDymaticStack &s, ElemType &e)
{
if(s.top==s.base)
{
cout<<"the Stack is NULL\n";
return ERROR;
}
e=*s.top;
s.top--;
//cout<<s.base<<":"<<s.top<<endl;
return OK;
}
| |
链式存储结构:用链表来实现栈的数据结构,头结点为栈顶。
定义:
#define STACK_INIT_SIZE 100 //开始分配空间的大小
#define STACK_INCREAMENT 10//动态分配追加的空间大小
//栈链式存储结构
typedef struct StackNode
{
ElemTypedata;
StackNode*next;
}StackNode, *StackList;
操作:
(1)链表栈的初始化
int initStackList(StackList &s)
{
s=(StackNode*)malloc(sizeof(StackNode));
if(s==NULL)
{
cout<<"alocate memory faile\n";
return ERROR;
}
s->data=-1;
s->next=NULL;
return OK;
}
| |
(2)动态栈的入栈操作
int pushStackList(StackList &s, ElemType &e)
{
StackNode *sNode;
if(s==NULL)return ERROR;
sNode=(StackNode*)malloc(sizeof(StackNode));
sNode->data=e;
sNode->next=NULL;
sNode->next=s;
s=sNode;
return OK;
}
| |
(3)动态栈的出栈操作
int popStackList(StackList &s, ElemType &e)
{
if(s->next==NULL)
{
cout<<"the stack is NULL\n";
return ERROR;
}
s=s->next;
e=s->data;
return OK;
}
| |
由上而知,算法依赖于数据结构的定义,所以定义一个合理的数据结构能够简化很多算法。在关于栈的相关操作过程中,需要注意的是:空栈的判断,栈顶指针的移动,栈初始化规则(如栈顶指针在初始化的时候为-1)