【数据结构与算法】栈的实现(附源码)

简介: 【数据结构与算法】栈的实现(附源码)

一.栈的概念和结构

1.一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作

2.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底

3.栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则;

压栈:向栈中插入数据;

出栈:从栈中取出数据;

图示:

 

其实用链表和数组都可以实现栈,但栈底就相当于链表的头,数组的第一个元素,栈顶就相当与链表的尾,数组的最后一个元素,当我们进行压栈或是出栈操作时,链表就需要找到尾,所以时间复杂度为O(N),而数组则是O(1),所以这里选择用数组实现栈比较好

用数组实现的话,就和前面的顺序表类似了。

顺序表

二.接口实现

A.初始化  Stackinit   销毁  Stackdestroy

1.Stackinit

1.这里数组的初始化就和顺序表那里是一样的了,需要用到动态内存管理的函数,如果不懂的话,建议去补一下这一块的知识哦;

2.这个top用来记录实时数据的数量,和顺序表那里的 sz 是一样的,但注意:

 <1>  如果初始化成0,那么这个 top 就指的是栈顶的下一个位置;

 <2>  如果初始化成-1,那么这个 top 就指的是栈顶的位置;

3.初始化容量,这由你自己决定。

1. void Stackinit(Stack* ps)
2. {
3.  assert(ps);
4. 
5.  ps->arr = (STdatatype*)malloc(sizeof(STdatatype) * MR_CAP);
6.  if (ps->arr == NULL)
7.  {
8.    perror("malloc fail");
9.    exit(-1);
10.   }
11.   ps->top = 0;   //表示的是栈顶的下一个位置
12.   ps->capacity = MR_CAP;   //默认容量
13. }

2.Stackdestroy

这个非常简单,直接看代码吧。

1. void Stackdestroy(Stack* ps)
2. {
3.  assert(ps);
4. 
5.  free(ps->arr);
6.  ps->arr = NULL;
7.  ps->top = 0;
8.  ps->capacity = 0;
9. }

B.插入 Stackpush  删除  Stackpop

1.Stackpush

在插入前,我们需要判断容量是否已满,若已满,则需要扩容。

1. void Stackpush(Stack* ps, STdatatype x)
2. {
3.  assert(ps);
4.  if (ps->top == ps->capacity)   //判断是否已满
5.  {
6.    STdatatype* tmp = (STdatatype*)realloc(ps->arr, 2 * sizeof(STdatatype) * ps->capacity);
7.    if (tmp == NULL)
8.    {
9.      perror("realloc fail");
10.       exit(-1);
11.     }
12.     ps->arr = tmp;
13.     ps->capacity *= 2;
14.   }
15.   ps->arr[ps->top] = x;
16.   ps->top++;   //数据入栈后,实时数据数量加1
17. }

2.Stackpop

删除前要注意栈是否为空,若为空则不能进行删除操作;

删除就是使 top 减1。

1. void Stackpop(Stack* ps)
2. {
3.  assert(ps);
4.  assert(ps->top);   //判断栈是否为空
5. 
6.  ps->top--;  //删除数据
7. }

C.出栈 Stacktop

出栈前需要判断栈是否为空,为空则无数据可出栈;

因为前面初始化的 top 是0,所以栈顶数据的下标是 top-1 ,如果初始化的 top 是-1,那么栈顶数据的下标则是 top 。

1. STdatatype Stacktop(Stack* ps)
2. {
3.  assert(ps);
4.  assert(ps->top);  //判断栈是否为空
5.  return ps->arr[ps->top - 1];  //栈顶数据的下标是 top-1
6. }

D. 栈的有效元素  Stacksize  判空 Stackempty

1.Stacksize

1.若初始化的 top 是0,则 top 就是栈的有效元素个数;

2.若初始化的 top 是-1,则 top+1 为栈的有效元素个数。

1. int Stacksize(Stack* ps)
2. {
3.  assert(ps);
4. 
5.  return ps->top;
6. }

2.Stackempty

1.如果 top 是0,则为空,返回 true;

2.如果 top 不是0,则不为空,返回 false 。

1. bool Stackempty(Stack* ps)
2. {
3.  assert(ps);
4. 
5.  return ps->top == 0;  //如果 top ==0 ,则这句代码为真,返回 true;反之,返回 false
6. }

三.源码

Stack.h

1. #include <stdio.h>
2. #include <stdlib.h>
3. #include <assert.h>
4. #include <stdbool.h>
5. 
6. #define MR_CAP 5
7. 
8. typedef int STdatatype;
9. 
10. typedef struct Stack
11. {
12.   STdatatype* arr;
13.   int top;
14.   int capacity;
15. }Stack;
16. 
17. void Stackinit(Stack* ps);
18. 
19. void Stackpush(Stack* ps,STdatatype x);
20. 
21. void Stackpop(Stack* ps);
22. 
23. STdatatype Stacktop(Stack* ps);
24. 
25. int Stacksize(Stack* ps);
26. 
27. bool Stackempty(Stack* ps);
28. 
29. void Stackdestroy(Stack* ps);

Stack.c

1. #include "Stack.h"
2. 
3. void Stackinit(Stack* ps)
4. {
5.  assert(ps);
6. 
7.  ps->arr = (STdatatype*)malloc(sizeof(STdatatype) * MR_CAP);
8.  if (ps->arr == NULL)
9.  {
10.     perror("malloc fail");
11.     exit(-1);
12.   }
13.   ps->top = 0;
14.   ps->capacity = MR_CAP;
15. }
16. 
17. void Stackpush(Stack* ps, STdatatype x)
18. {
19.   assert(ps);
20.   if (ps->top == ps->capacity)
21.   {
22.     STdatatype* tmp = (STdatatype*)realloc(ps->arr, 2 * sizeof(STdatatype) * ps->capacity);
23.     if (tmp == NULL)
24.     {
25.       perror("realloc fail");
26.       exit(-1);
27.     }
28.     ps->arr = tmp;
29.     ps->capacity *= 2;
30.   }
31.   ps->arr[ps->top] = x;
32.   ps->top++;
33. }
34. 
35. void Stackpop(Stack* ps)
36. {
37.   assert(ps);
38.   assert(ps->top);
39. 
40.   ps->top--;
41. }
42. 
43. STdatatype Stacktop(Stack* ps)
44. {
45.   assert(ps);
46.   assert(ps->top);
47.   return ps->arr[ps->top - 1];
48. }
49. 
50. int Stacksize(Stack* ps)
51. {
52.   assert(ps);
53. 
54.   return ps->top;
55. }
56. 
57. bool Stackempty(Stack* ps)
58. {
59.   assert(ps);
60. 
61.   return ps->top == 0;
62. }
63. 
64. void Stackdestroy(Stack* ps)
65. {
66.   assert(ps);
67. 
68.   free(ps->arr);
69.   ps->arr = NULL;
70.   ps->top = 0;
71.   ps->capacity = 0;
72. }

test.c

1. #include "Stack.h"
2. 
3. void testStack()
4. {
5.  Stack st;
6. 
7.  Stackinit(&st);
8. 
9.  int i = 0;
10.   for (i = 1; i <= 8; i++)
11.   {
12.     Stackpush(&st, i);
13.   }
14.   printf("%d\n ", Stacksize(&st));
15.   /*while (!Stackempty(&st))
16.   {
17.     printf("%d  ", Stacktop(&st));
18.     Stackpop(&st);
19.   }*/
20.   printf("\n");
21.   Stackdestroy(&st);
22. }
23. 
24. int main()
25. {
26.   testStack();
27. 
28.   return 0;
29. 
30. }

🐲👻关于栈的讲解就到这里了,若有错误或是建议欢迎小伙伴们指出。🐯🤖

🥰🤩希望小伙伴们可以多多支持博主哦。😍😃

😁😄谢谢你的阅读。😼😸


目录
相关文章
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
42 1
|
2天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
112 75
|
2天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
24 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
2天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
27 9
|
2天前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
21 7
|
16天前
|
算法
【算法】栈
栈相关算法题,供参考,附有链接地址及板书
|
24天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
77 3
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
78 5
|
2月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
161 7