栈是一种特殊操作的线性表。因为他满足线性表的三个特征,元素类型相同,个数有限,有顺序。
栈特殊操作为LIFO,后进先出。
线性表分为两类,第一类为顺序表,第二类为链表。那么栈也可以由此分为两类,称为顺序栈与链栈。
由于栈限制了操作,所以操作不想普通线性表如此复杂,一般只包含这几种:
- 初始化 InitStack
- 入栈 push
- 出栈 pop
- 判空 isEmpty
- 获得栈顶getTop
- 析构 destroy
获得栈顶getTop与pop的区别在于,getTop不会将栈顶弹出,只会返回值,pop也会返回值,但是也弹出的栈顶。
顺序栈
顺序栈即为顺序表实现,即为数组,通常包含栈顶下标充当栈顶指针作用。一般写法也有两种,栈顶指针初始化为-1与栈顶指针初始化为0,差别不大。在此以栈顶指针初始化为-1为例。
#define MaxSize 10
typedef struct {
ElemType data[MaxSize];
int top;
}Stack;
//初始化
void InitStack(Stack &s){
s.top = -1;
}
bool isEmpty(Stack s){
return s.top == -1;
}
bool push(Stack &s, ElemType e){
if (top == MaxSize)
return false;
data[++top] = e;
return true;
}
ElemType pop(Stack &s){
if (top == -1);
return NULL;
return data[top--];
}
ElemType getTop(Stack &s){
if (top == -1);
return NULL;
return data[top];
}
void destroy(Stack &s){
s.top = -1;
}
链栈
以含有头指针的链表为例子。
typedef struct Node {
ElemType data;
Node * next;
}SNode, *Stack;
void InitStack(Stack & s){
s = (SNode *)malloc(sizeof(SNode));
s->next = NULL;
}
bool isEmpty(Stack &s){
return s->next == NULL;
}
bool push(Stack &s, ElemType e){
SNode *p = (SNode * )malloc(sizeof(SNode));
if (p == NULL)
return false;
p->next = s->next;
p->data = e;
s->next = p;
return true;
}
bool pop(Stack &s, ElemType &e){
if (isEmpty(s))
return false;
SNode *p = s->next;
e = s->data;
s->next = p->next;
free(p);
return true;
}
bool getTop(Stack &s, ElemType &e){
if (isEmpty(s))
return false;
e = s->next->data;
return true;
}
void destroy(Stack &s){
LNode * p = s;
while (p != NULL){
LNode * tem = p;
p = p->next;
free(tem);
}
}