栈是应用很广泛的数据结构,属于操作“受限”的线性表。
一、栈的基本概念
栈:是限制在表的一端进行插入和删除操作的线性表。又称为后进先出LIFO (Last In First Out)或先进后出FILO (First In Last Out)线性表。
栈顶:进行操作的一端,用栈顶指针来指示栈顶元素。
栈底:固定端。
二、栈的结构和操作
1、栈的顺序存储表示:顺序存储又分为静态顺序栈和动态顺序栈,静态的实现简单,但不能根据需要增加栈的容量;动态的可以根据需要增大栈的空间。
1)、静态顺序栈
typedef struct
{
DataType stack[MaxStackSize];
int top;
}SeqStack;
void StackInitiate(SeqStack *S)
{
S->top=0;
}
int StackNotEmpty(SeqStack S)
{
if(S.top<=0) return 0;
else return 1;
}
int StackPush(SeqStack *S,DataType x)
{
if(S->top>=MaxStackSize)
{
printf("栈溢出!");
return 0;
}
else
{
S->stack[S->top]=x;
S->top++;
return 1;
}
}
int StackPop(SeqStack *S,DataType *d)
{
if(S->top<=0)
{
printf("栈空!");
return 0;
}
else
{
S->top--;
*d=S->stack[S->top];
return 1;
}
}
int StackTop(SeqStack S,DataType *d)
{
if(S.top<=0)
{
printf("栈空!");
return 0;
}
else
{
*d=S.stack[S.top-1];
return 1;
}
}
上边的代码很简单,大家参考咋们前边实现的顺序线性表,这里只是规定了数据操作的方向而已。
2)、动态顺序栈
#include <malloc.h>
#include <stdlib.h>
#define STACK_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define ERROR -1
typedef int Status;
typedef int ElemType;
typedef struct Dysqstack
{
ElemType *top;
ElemType *bottom;
int stacksize;
}DySqStack;
//init
Status DySqStack_Init(DySqStack &S)
{
S.bottom=(ElemType *)malloc(STACK_SIZE*sizeof(ElemType));
if(!S.bottom) return ERROR;
S.top=S.bottom;
S.stacksize=STACK_SIZE;
return OK;
}
//push data to stack
Status DySqStack_Push(DySqStack &S,ElemType e)
{
//if size of stack is not enough,add the size by function named realloc
if(S.top-S.bottom>=S.stacksize-1)
{
S.bottom=(ElemType *)realloc(S.bottom,(STACKINCREMENT+STACK_SIZE)*sizeof(ElemType));
if(!S.bottom) return ERROR;
S.top=S.bottom+S.stacksize;
S.stacksize=S.stacksize+STACKINCREMENT;
}
S.top++;
*(S.top)=e;
return OK;
}
//pop data from stack
Status DySqStack_Pop(DySqStack &S,ElemType *e)
{
if(S.bottom==S.top)
{
std::cout<<"stack is empty!"<<std::endl;
return ERROR;
}
*e=*(S.top);
S.top--;
return OK;
}
Status DySqStack_notEmpty(DySqStack &S)
{
if(S.bottom==S.top)
{
std::cout<<"stack is empty!"<<std::endl;
return ERROR;
}
return OK;
}
Status DySqStack_Top(DySqStack &S,ElemType *e)
{
if(S.bottom==S.top)
{
std::cout<<"stack is empty!"<<std::endl;
return ERROR;
}
*e=*(S.top);
return OK;
}
上边的代码函数形参是按引用传递,这个读者可以理解为隐式指针,共用内存中的数据,仅仅传递的变量地址;如果按值传递,实际是传递的变量副本,当函数退出时自动释放,会引起内存操作错误;当然用指针也可以,读者可以自行改写。
2、栈的链式存储表示:链式存储可以有两种实现,头插入法和尾插入法,头插入法就是将栈顶放在链表头部,每次从头部插入;尾插入法就是栈顶放在尾部;这里给出头插入法,尾插入法读者自行实现
typedef struct pointstack
{
DataType data;
struct pointstack *next;
}PointStack;
int StackInitiate(PointStack *head)
{
// head=(PointStack *)malloc(sizeof(PointStack));
head->next=NULL;
head->data=0;
return 1;
}
int StackNotEmpty(PointStack *head)
{
if(head->next==NULL) return 0;
else return 1;
}
int StackPush(PointStack *head,DataType e)
{
PointStack *p,*q;
p=head->next;
// while(p->next!=NULL)
// p=p->next;
q=(PointStack *)malloc(sizeof(PointStack));
q->data=e;
q->next=p;
head->next=q;
return 1;
}
int StackPop(PointStack *head,DataType *x)
{
PointStack *p;
// pre=head;
p=head->next;
// while(p->next->next!=NULL)
// {
// p=p->next;
// }
*x=p->data;
head->next=p->next;
free(p);
return 1;
}
鉴于篇幅有限,这里不再给出测试代码,读者自行编写。
进行插入和删除操作的线性表。
进行插入和删除操作的线性表。又称