栈的定义以及基本操作C语言实现
栈本身就是线性表,只不过是操作受限制,数据元素后进后出
用顺序表表示栈
- 栈的声明
#define InitSize 5
#define Elemtype int
#define Status int
#define OK 1//返回的操作结果,比如某个操作是否成功
#define OVERFLOW -1
#define ERROR -1
typedef struct{
Elemtype *base;
Elemtype *top;
int StackSize;
}Stack;
- 初始化栈,我这里用top==base来表示空栈,base指向数组的首地址,top指向数据上方第一个非空的位置
Status InitStack(Stack *S){
S->base=(Elemtype *)malloc(InitSize*sizeof(Elemtype));
if(!S->base) exit(OVERFLOW); //存储分配失败
S->top=S->base;
S->StackSize=InitSize;
return OK;
}
-
判断栈是否为空
int IsEmpty(Stack S){ if(S->top==S->base) return 1; else return 0; }
-
push–压栈
#define StackInsertNum 5//栈满后每次增加的栈空间
Status PushStack(Stack *S,Elemtype e){
if(S->top-S->base>=S->StackSize)//数组的指针之间的减号会直接计算相差的元素个数
{//栈满
S->base=(Elemtype *)realloc(S->base,(S->StackSize+StackInsertNum)*sizeof(Elemtype));
if(!S->base) exit(OVERFLOW);
S->StackSize+=StackInsertNum;
*(S->top)=e;
S->top++;
}
else{
*(S->top)=e;
S->top++;
}
return OK;
}
- pop–出栈
Status PopStack(Stack *S,Elemtype *e){
if(S->base==S->top) exit(ERROR);
e=*(S->top-1);
S->top--;
return OK;
}
链式栈的实现
链式栈相对于线性栈来说,内存管理更方便,但是存储密度小
-
栈的声明
typedef struct stackNode{//栈中的单个节点 Elemtype data; struct stackNode *next; }StackNode; typedef struct stack{ StackNode *top; int count;//记录栈中元素的个数 }Stack;
-
初始化栈
void InitStack(Stack *S){ S->top=NULL; S->count=0; }
-
压栈Push
Status PushStack(Stack *S,Elemtype e){ StackNode *topNode=(StackNode *)malloc(sizeof(StackNode)); if(!topNode) return ERROR; topNode->data=e; topNode->next=S->top; S->top=topNode; S->count++; return OK; }
这个函数在我第一次写的时候有个疑惑,就是那个topNode是个局部变量,作用域仅仅在这个函数中,那退出这个函数的时候新节点会被回收吗,后来我想了想,其实道理很简单,malloc开辟的空间在堆内存中,而那个topNode的指针变量才是在这个函数的栈帧中,退出这个函数的时候只会回收topNode这个指针变量,对于新节点所在空间没有影响。
-
出栈Pop
Status PopStack(Stack *S,Elemtype *e){ if(!(S->top)) return ERROR;//栈空,返回ERROR *e=S->top->data; StackNode *tmp=S->top; S->top=S->top->next; S->count--; free(tmp); return OK; }