找回密码
 立即注册
首页 业界区 业界 栈的两种存储结构(顺序存储和链式存储) ...

栈的两种存储结构(顺序存储和链式存储)

骂治并 2025-8-10 16:46:57
栈的操作实现

栈的概念

栈是一种后进先出(LIFO)的线性数据结构,只允许在一端(栈顶)进行插入和删除操作。新元素总是添加到栈顶,而删除也总是从栈顶移除最上面的元素。栈常用于函数调用、表达式求值、括号匹配等场景。
代码实现---顺序存储(Array-based Stack)
  1. #include <stdio.h>        // 标准输入输出库,用于 printf 等函数
  2. #include <stdbool.h>// 布尔类型库,提供 bool、true、false
  3. #include <stdlib.h> // 标准库,提供 malloc/calloc/free 和 exit 等函数
  4. // 定义栈元素的类型为 int
  5. typedef int DataType_t;
  6. // 定义栈的元素结构体
  7. typedef struct SequenceStack
  8. {
  9.         DataType_t *Bottom;
  10.         unsigned int Size;
  11.         int                  Top;
  12. } SeqStack_t;
  13. SeqStack_t* SeqStack_init(unsigned int size)
  14. {
  15.         //calloc 返回的是 void * 类型指针,可以隐式转换为任何其他指针类型(如 int*、char*),所以强制类型转换不是必须的
  16.         SeqStack_t *Manager = (SeqStack_t *)calloc(1,sizeof(SeqStack_t));
  17.         if(Manager == NULL){
  18.                 perror("calloc for Manager is failed!\n");
  19.                 exit(-1);
  20.         }
  21.         Manager->Bottom = (DataType_t *)calloc(size,sizeof(DataType_t));
  22.        
  23.         if(Manager->Bottom == NULL){
  24.                 perror("calloc for stackEelement is failed\n");
  25.                 free(Manager);
  26.                 exit(-1);
  27.         }
  28.         Manager->Size = size;
  29.         Manager->Top = -1;//没有元素,初始化为-1,新增一个元素后下标就可以等于0
  30.         return Manager;
  31. }
  32. //判断栈是不是满
  33. bool SeqStackIsfull(SeqStack_t *Manager)
  34. {
  35.         //假设stacksize是8,Top的值已经为7,则栈满
  36.         return (Manager->Top+1 == Manager->Size)?true:false;
  37. }
  38. //判断栈是不是空
  39. bool SeqStackIsEmpty(SeqStack_t *Manager)
  40. {
  41.         //Top初始值为-1,下次判断依然是-1则栈是空
  42.         return (Manager->Top == -1)?true:false;
  43. }
  44. //入栈
  45. bool SeqStack_Push(SeqStack_t *Manager,DataType_t data)
  46. {       
  47.         //添加元素需要先判断栈有没有满
  48.         if(SeqStackIsfull(Manager)){
  49.                 printf("SeqStack is Full!\n");
  50.                 return false;
  51.         }
  52.         Manager->Bottom[++Manager->Top] = data;
  53.         return true;
  54. }
  55. //出栈
  56. DataType_t SeqStack_Pop(SeqStack_t *Manager)
  57. {
  58.         if (SeqStackIsEmpty(Manager)) {
  59.     printf("SeqStack is Empty!\n");
  60.     return;
  61.         }
  62.         //栈顶元素出栈,Top-1
  63.         DataType_t temp = Manager->Bottom[Manager->Top--];
  64.        
  65.         return temp;
  66. }
  67. //遍历栈
  68. void SeqStack_Print(SeqStack_t *Manager)
  69. {
  70.         for(int i=0;i<= Manager->Top;i++){
  71.                 printf("Stack Element[%d] = %d\n",i,Manager->Bottom[i]);
  72.         }
  73. }
  74. int main(int argc, char const *argv[])
  75. {
  76.     // 初始化大小为 4 的栈
  77.     SeqStack_t *stack = SeqStack_init(4);
  78.     // 测试空栈出栈
  79.     printf("尝试从空栈出栈:\n");
  80.     SeqStack_Pop(stack);
  81.     // 入栈测试
  82.     printf("入栈: 10, 20, 30\n");
  83.     SeqStack_Push(stack, 10);
  84.     SeqStack_Push(stack, 20);
  85.     SeqStack_Push(stack, 30);
  86.     // 打印栈
  87.     printf("当前栈内容:\n");
  88.     SeqStack_Print(stack);
  89.     // 测试栈满
  90.     printf("继续入栈: 40, 50\n");
  91.     SeqStack_Push(stack, 40);
  92.     SeqStack_Push(stack, 50);  // 应提示栈满
  93.     // 出栈两次
  94.     printf("出栈两次:\n");
  95.     printf("出栈元素: %d\n", SeqStack_Pop(stack));
  96.     printf("出栈元素: %d\n", SeqStack_Pop(stack));
  97.     // 再打印栈
  98.     printf("出栈后内容:\n");
  99.     SeqStack_Print(stack);
  100.     return 0;
  101. }
复制代码
运行结果

1.png

代码实现---链式存储(Linked Stack)
  1. /**
  2. * @fire name:Linkedstack.c
  3. * @brief:/**
  4. * @fire name:SeqList.c
  5. * @brief:这个程序实现栈的入栈、出栈(链式存储)
  6. * @author:13642563766@163.com
  7. * @date:2025/7/18
  8. * @version:1.0
  9. *  @note:None
  10. * Copyright (c)  2021-2022  13642563766@163.com  All right Reserved
  11. */
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. // 定义栈中存储的数据类型为 int
  15. typedef int DataType;
  16. // 链栈的节点结构体:每个节点包含数据和指向下一个节点的指针
  17. typedef struct StackNode {
  18.         DataType        data;
  19.         struct StackNode *next;
  20. }StackNode;
  21. // 链栈管理结构体:用于管理整个栈的状态
  22. typedef struct{
  23.         int size;
  24.         StackNode *top;// 指向栈顶节点的指针(NULL 表示空栈)
  25. }LinkedStack;
  26. // 为 LinkedStack* 定义别名 Stack,表示一个栈的指针
  27. typedef LinkedStack* Stack;
  28. /**
  29. * 初始化栈
  30. * @param s 指向栈指针的指针(二级指针),用于返回栈的地址
  31. * @return 成功返回 1,失败返回 0
  32. */
  33. int InitStack(Stack *s)
  34. {
  35.         *s = (Stack)malloc(sizeof(LinkedStack));
  36.         if(*s == NULL){
  37.                 return 0;
  38.         }
  39.         (*s)->top = NULL;
  40.         (*s)->size = 0;
  41.         return 1;
  42. }
  43. /**
  44. * 入栈操作:将一个新元素压入栈顶
  45. * @param s 栈指针
  46. * @param data 要入栈的数据
  47. * @return 成功返回 1,失败返回 0
  48. */
  49. int Push(Stack s, DataType data)
  50. {
  51.         if (s == NULL) {
  52.         return 0; // 指针无效
  53.     }
  54.     StackNode *newNode = (StackNode*)malloc(sizeof(StackNode));
  55.     if (newNode == NULL) {
  56.         return 0; // 指针无效
  57.     }
  58.     // 设置新节点的数据和指针
  59.     newNode->next = s->top;/
  60.     newNode->data = data;
  61.     s->top = newNode;//更新top指向新结点
  62.     s->size++;//每入栈一个元素size++
  63.     return 1;
  64. }
  65. /**
  66. * 出栈操作:弹出栈顶元素,并通过指针返回其值
  67. * @param s 栈指针
  68. * @param data 用于接收出栈元素值的输出参数
  69. * @return 成功返回 1,栈为空或指针无效返回 0
  70. */
  71. int Pop(Stack s, DataType *data)
  72. {
  73.         if(s == NULL || s->top == NULL){
  74.                 return 0; // 栈为空或栈指针无效,无法出栈
  75.         }
  76.     // 保存当前栈顶节点,便于后续释放
  77.         StackNode *Temp = s->top;
  78.     // 将栈顶指针移动到下一个节点
  79.         s->top = s->top->next;
  80.         *data = Temp->data;
  81.         free(Temp);
  82.         s->size--;
  83.         return 1;
  84. }
  85. //获得栈顶元素的值
  86. int GetTop(Stack s, DataType *data)
  87. {
  88.         if(s == NULL || s->top == NULL){
  89.                 return 0; // 栈为空或栈指针无效
  90.         }
  91.         *data = s->top->data;
  92.         return 1;
  93. }
  94. int IsEmpty(Stack s)
  95. {
  96.         if(s == NULL){
  97.                  return 1;
  98.         }
  99.         return(s->top == NULL);
  100. }
  101. /**
  102. * 销毁整个栈,释放所有内存
  103. * @param s 指向栈的指针的指针
  104. */
  105. void DestroyStack(Stack *s) {
  106.     if (s == NULL || *s == NULL) {
  107.         return;
  108.     }
  109.     StackNode *current = (*s)->top;
  110.     StackNode *next;
  111.     // 逐个释放节点
  112.     while (current != NULL) {
  113.         next = current->next;
  114.         free(current);
  115.         current = next;
  116.     }
  117.     // 释放栈结构本身
  118.     free(*s);
  119.     *s = NULL; // 防止野指针
  120. }
  121. int main() {
  122.     Stack myStack;
  123.     DataType value;
  124.     // 1. 初始化栈
  125.     if (!InitStack(&myStack)) {
  126.         printf("初始化栈失败!\n");
  127.         return -1;
  128.     }
  129.     printf("栈初始化成功。\n");
  130.     // 2. 入栈操作
  131.     printf("入栈: 10, 20, 30\n");
  132.     Push(myStack, 10);
  133.     Push(myStack, 20);
  134.     Push(myStack, 30);
  135.     // 3. 查看栈顶元素
  136.     if (GetTop(myStack, &value)) {
  137.         printf("当前栈顶元素: %d\n", value);
  138.     } else {
  139.         printf("栈为空,无法获取栈顶元素。\n");
  140.     }
  141.     // 4. 出栈操作
  142.     printf("开始出栈:\n");
  143.     while (!IsEmpty(myStack)) {
  144.         if (Pop(myStack, &value)) {
  145.             printf("弹出: %d\n", value);
  146.         }
  147.     }
  148.     // 5. 再次尝试出栈 (栈已空)
  149.     if (Pop(myStack, &value)) {
  150.         printf("弹出: %d\n", value);
  151.     } else {
  152.         printf("栈已空,无法弹出元素。\n");
  153.     }
  154.     // 6. 销毁栈
  155.     DestroyStack(&myStack);
  156.     printf("栈已销毁。\n");
  157.     return 0;
  158. }
复制代码
运行结果

2.png


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册