之前的头插法天然满足先进后出,后进先出这个特点。所以我们可以使用链表。
设计时选择表头,作为栈顶指针,而不是表尾(单向链表(不含头节点))。不同于线式存储,所以不需要作判满操作。
链式存储实现代码如下:
因为有bool变量,用了C++实现
mystack.h
#include<stdio.h>
#include<stdlib.h>
struct Node
{
char data; //这里用char类型
Node* next;
};
struct Stack
{
Node* top;
};
void initStack(Stack *s); //先初始化
bool isStackEmpty(Stack *s);//判断是否为空
void push(Stack *s,char ch); //往里压
char pop(Stack *s); //往外弹
void resetStack(Stack*s); //复位
void destroyStack(Stack*s); //销毁
mystack.cpp
#include"mystack.h"
void initStack(Stack *s) //先初始化
{
s->top=(Node*)malloc(sizeof(Node)); //相当于链表初始化
s->top->next=NULL;
}
bool isStackEmpty(Stack *s)//判断是否为空
{
return s->top->next==NULL; //若一开始的节点的next为空,则栈为空
}
void push(Stack *s,char ch) //往里压
{
Node *cur=(Node*)malloc(sizeof(Node));
cur->data=ch;
cur->next=s->top->next; //链表的头插法,若不明白可以看我单向链表的博客文章
s->top->next=cur;
}
char pop(Stack *s) //往外弹
{
Node*t=s->top->next; //找一个替身
s->top->next=t->next; //把头节点后面的首节点拿下来,实现先进后出,后进先出
char ch=t->data; //因为要释放 t ,而且需要返回char,所以创建个变量记录下
free(t);
return ch;
}
void resetStack(Stack*s) //复位
{
while(!isStackEmpty)//一直弹出就行,pop函数里已经有释放
pop(s);
}
void destroyStack(Stack*s) //销毁
{
resetStack(s);
free(s->top);
}
main函数
#include <iostream>
#include"mystack.h"
using namespace std;
int main()
{
Stack s;
initStack(&s);
for(char ch='A';ch<='Z';ch++) //这里不需要判满,默认堆上开辟可以无限开辟
push(&s,ch);
// resetStack(&s);
while(!isStackEmpty(&s))
printf("%c ",pop(&s));
destroyStack(&s);
return 0;
}