C语言用链表(LinkedList)实现堆栈

简介

上一篇文章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的测试结果
i=5的时候测试函数输出结果

总结

相比较与数组作为存储结构,链表使用起来更加的灵活,只要内存够大就能不断地申请到空间,不像数组是固定大小的。不过对于堆栈来说用数组实现起来比较简单,如果要实现队列用数组作为存储空间的话实现出队操作的时候
就要移动太多元素了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值