简介
上一篇文章C语言实现栈(Stack)数据结构是用数组作为存储结构,本篇文章介绍如何使用链表作为栈的存储结构。
栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的顶部进行。
此时这里就会有个问题栈顶的指针Top应该在链表的头部还是尾部呢?
答案其实很简单,栈顶指针Top应该在链表头部表示。如果在链表尾部表示栈顶指针,在进行出栈Pop操作时
无法获取删除操作结束后栈顶指针的位置Top,不过用双向链表应该可以解决这个问题。
代码实现
linked_list_stack.h头文件
#ifndef C_LINKED_LIST_STACK_H
#define C_LINKED_LIST_STACK_H
#include <stdbool.h>
// 定义链表结点指针类型
typedef struct StackNode *PStackNode;
// 定义链表结点类型
typedef struct StackNode {
int data;
PStackNode next;
} SNode;
// 定义栈类型和栈指针类型
typedef struct {
PStackNode top;
} LLStack, *LLStackPtr;
void linkedListStackInit(LLStackPtr stackPtr);
void linkedListStackPush(LLStackPtr stackPtr, int item);
int linkedListStackPop(LLStackPtr stackPtr);
int linkedListStackPeek(LLStackPtr stackPtr);
bool isLinkedListStackEmpty(LLStackPtr stackPtr);
void linkedListStackTestFunc(void);
#endif //C_LINKED_LIST_STACK_H
linked_list_stack.c文件
#include "linked_list_stack.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
// 初始化
void linkedListStackInit(LLStackPtr stackPtr) {
stackPtr->top = NULL;
}
// 入栈
void linkedListStackPush(LLStackPtr stackPtr, int item) {
PStackNode p = (PStackNode) malloc(sizeof(SNode));
if (p == NULL) {
printf("无法申请到结点的内存空间,入栈失败!!!");
} else {
p->data = item;
p->next = stackPtr->top;// 新元素插入到栈的链表头部
stackPtr->top = p;// 将链表头部指向新元素
}
}
// 出栈
int linkedListStackPop(LLStackPtr stackPtr) {
int ret = NULL;
// 栈顶部不为NULL时说明有元素
if (stackPtr->top) {
PStackNode p = stackPtr->top;// 保存一下当前栈顶指针
stackPtr->top = p->next;// 将栈顶指向后一个元素
ret = p->data;// 将需要弹出的元素赋值给ret
free(p);// 回收弹出结点的内存空间
}
return ret;
}
// 只查看栈顶元素,并不弹出
int linkedListStackPeek(LLStackPtr stackPtr) {
int ret = NULL;
if (stackPtr->top) {
ret = stackPtr->top->data;
}
return ret;// 这里不严谨如果栈内也有-1的情况要怎么办
}
// 是否空栈
bool isLinkedListStackEmpty(LLStackPtr stackPtr) {
return stackPtr->top == NULL;
}
// 测试函数
void linkedListStackTestFunc() {
LLStack myStack;
LLStackPtr stack = &myStack;
linkedListStackInit(stack);
const int Size = 5;
printf("pushStack:\n");
for (int i = 0; i < Size; ++i) {
int item = rand() % 101;
printf("%d\n", item);
linkedListStackPush(stack, item);
}
printf("popStack:\n");
for (int i = 0; i < Size; ++i) {
printf("%d\n", linkedListStackPop(stack));
}
}
测试函数运行结果
Size等于5的测试结果
总结
相比较与数组作为存储结构,链表使用起来更加的灵活,只要内存够大就能不断地申请到空间,不像数组是固定大小的。不过对于堆栈来说用数组实现起来比较简单,如果要实现队列用数组作为存储空间的话实现出队操作的时候
就要移动太多元素了。