链栈是基于单链表实现的,所以要先掌握链表的基本操作:遍历、增加节点、删除节点等。
1,链栈的结构
链栈的节点,负责保存元素的值。
typedef struct tagLinkStackNode
{
char data; //数据域
struct tagLinkStack *next;//指针域
}LinkStackNode;
链栈中维护一个长度变量 l e n g t h length length和栈顶指针 t o p top top。
typedef struct tagLinkStack
{
int length; //链栈长度
LinkStackNode *top; //top指针
}LinkStack;
2,初始化
这里初始化为空栈。
//初始化
void init(LinkStack *stack)
{
stack->length = 0;
stack->top = NULL;
}
还可以考虑带数据的初始化。接口如下:
void initWithData(LinkStack *stack, char *arr, int length)
3,判空
// 判空
int isEmpty(LinkStack *stack)
{
return !stack->length;
}
4,入栈
链栈并没有长度限制,可以根据需要不断添加节点,只要内存足够。
首先,生成新节点并赋值。然后,看栈是否为空。若空,则让top指向它,尾端为NULL;否则,先将该节点尾端指向原栈顶元素,然后,让top指向该节点。最后,长度加1。
// 入栈
void push(LinkStack *stack, char item)
{
LinkStackNode *node = malloc(sizeof(LinkStackNode));
if (!node)
{
printf("No more memory!\n");
}
node->data = item; //新节点数据域赋值
if (isEmpty(stack))
{
node->next = NULL;
}
else
{
node->next = stack->top;
}
stack->top = node; // 栈顶指针指向压入节点
stack->length++;
}
5,出栈
出栈前需要判空。记得释放删除的节点所占内存。
//出栈
void pop(LinkStack *stack, char *item)
{
if (isEmpty(stack))
{
printf("Stack is empty!\n");
}
else
{
LinkStackNode *tempNode;
tempNode = stack->top;
*item = stack->top->data;
stack->top = stack->top->next;
stack->length--;
free(tempNode);
}
}
6,打印链栈
从栈顶向栈底遍历并打印元素的值。
// 打印链栈,从栈顶开始
void show(LinkStack *stack)
{
if (isEmpty(stack))
{
printf("Stack is empty!\n");
}
else
{
LinkStackNode *tempNode;
tempNode = stack->top;
for (int i = 0; i < stack->length; ++i)
{
printf("%c", tempNode->data);
tempNode = tempNode->next;
}
printf("\n");
}
}
7,测试代码
void test()
{
//测试字符数组
char str[] = "Hello World!";
//定义栈并初始化
LinkStack stack;
init(&stack);
//入栈并显示
for (int i = 0; i < strlen(str); ++i)
{
push(&stack, str[i]);
}
show(&stack);
//出栈并显示
char item;
for (int i = 0; i < strlen(str); ++i)
{
pop(&stack, &item);
printf("%c\n", item);
}
//对空栈进行pop
pop(&stack, &item);
}
运行结果:
!dlroW olleH
!
d
l
r
o
W
o
l
l
e
H
Stack is empty!