顺序栈
特点
是只在表尾端进行插入,删除操作的线性表
表尾端为栈顶(top)
后进先出(Last In First Out)
具体实现
定义
typedef struct{
int* base;
int* top; //栈顶向上增长
int StackSize;
}SqStack;
初始化
top指向“下标”为0位置,而非-1位置
参考单链表的实现,仍然传指针(若直接传s,则对s的副本操作)
void init(SqStack* s){
s->base = (int*)malloc(sizeof(int)*MAXSIZE);
s->top = s->base; //栈空
s->StackSize = MAXSIZE;
}
入栈
注意top指向栈的下一个空闲位置
void push(SqStack* s,int e){ //传址或传指针
if(s->top - s->base == MAXSIZE)
return; //栈满
*s->top++ = e; //成员选择优先级较高
}
出栈
出栈时返回栈顶元素
int pop(SqStack* s){
if(s->top != s->base){
return *(--s->top); //top指向首个空闲位置
}
}
其他小操作
获取栈顶元素值
top指向栈顶元素下一位
int GetTop(SqStack s){
if(s.top!=s.base)
return *(s.top-1);
}
判断是否为空
int IsEmpty(SqStack s){
return s.top == s.base;
}
栈的长度
int length(SqStack s){
return s.top - s.base;
}
CHECK
int main(){
SqStack(s);
init(&s);
printf("是否为空:\n");
printf("%d\n",IsEmpty(s));
for(int i = 0;i < 10;i++){
push(&s,i);
}
printf("长度:\n");
printf("%d\n",length(s));
printf("栈顶元素:\n");
printf("%d\n",GetTop(s));
printf("出栈:\n");
for(int i = 0;i < 10;i++){
printf("%d%c",pop(&s),(i == 9 ? '\n' : ' '));
}
printf("是否为空:\n");
printf("%d\n",IsEmpty(s));
}
输出如下:
是否为空:
1
长度:
10
栈顶元素:
9
出栈:
9 8 7 6 5 4 3 2 1 0
是否为空:
1
链栈
定义
typedef struct StackNode{
int data;
struct StackNode* next;
}StackNode,*LinkStack;
初始化
void InitStack(LinkStack* S){ //二级指针
*S = (StackNode*)malloc(sizeof(StackNode));
if(*S == NULL)
return;
(*S)->next = NULL;
}
入栈
使用头指针
头插法
在头结点与首元结点间插入
栈顶为头指针
void Push_h(LinkStack* S,int e){
StackNode* p = (StackNode*)malloc(sizeof(StackNode));
p->data = e;
p->next = (*S)->next; //S为头指针
(*S)->next = p;
}
使用尾指针
更接近顺序栈方式(top指针向上增长)
栈顶为尾指针
void Push_r(LinkStack* S,int e){
StackNode* p = (StackNode*)malloc(sizeof(StackNode));
p->data = e;
StackNode *r = *S;
while(r->next != NULL){
r = r->next;
}
r->next = p;
p->next = NULL;
}
出栈
使用头指针
void Pop_h(LinkStack* S){
if((*S)->next == NULL) //空栈
return;
StackNode* p = (*S)->next;
(*S)->next = p->next;
free(p);
使用尾指针
有点牵强
void Pop_r(LinkStack* S){
if((*S)->next == NULL) //空栈
return;
StackNode* r = (*S);
while(r->next->next != NULL){
r = r->next; //此时尾指针指向栈顶下一个元素
}
StackNode* q = r->next; //栈顶元素
r->next = NULL;
free(q);
}
获取栈顶
使用头指针
int GetTop_h(LinkStack S){
if(S->next != NULL)
return S->next->data;
使用尾指针
int GetTop_r(LinkStack S){
StackNode* r = S->next;
while(r->next != NULL){
r = r->next;
}
return r->data;
}
其他
判断空栈
int Empty(LinkStack S){
return S->next == NULL;
}
元素个数
int size(LinkStack S){
StackNode* p = S->next;
int cnt = 0;
while(p != NULL){
cnt++;
p = p->next;
}
return cnt;
}
CHECK
int main(){
LinkStack S;
InitStack(&S);
printf("是否为空:\n");
printf("%d\n",Empty(S));
for(int i = 0;i < 10;i++){
Push_h(&S,i);
}
printf("长度:\n");
printf("%d\n",size(S));
printf("栈顶元素:\n");
printf("%d\n",GetTop_h(S));
printf("出栈:\n");
for(int i = 0;i < 10;i++){
printf("%d%c",GetTop_h(S),(i == 9 ? '\n' : ' '));
Pop_h(&S); //当然也可以用单链表方式遍历
}
printf("是否为空:\n");
printf("%d\n",Empty(S));
}
输出如下
是否为空:
1
长度:
10
栈顶元素:
9
出栈:
9 8 7 6 5 4 3 2 1 0
是否为空:
1