• 《数据结构与算法》-栈的概念和栈的实现


    目录

    概念

    思路和源代码

    思路

    源代码

    头文件(主题框架)

    源文件,各个接口的实现

    结构体的初始化

    压栈

    出栈

    判断是否为空

    获取栈顶元素

    获取元素个数

    销毁

    test.c源文件(main函数所在的.c源文件)

    Stack.c各个接口的实现源文件的整合


    概念

    栈是一种特殊的线性表,遵循先进后出(后进先出)的原则,只允许在固定的一端进行插入和删除,而这一端称为栈顶,另一端称为栈底

    压栈:插入元素到栈顶,也称进栈、入栈

    出栈:删除元素在栈顶。

    注:操作系统的栈与数据结构的栈不同,但是都是后进先出,比如操作系统的栈后开辟的栈区先释放

    思路和源代码

    思路

    顺序表比链表更容易操作尾插尾删,并且顺序表可以随机访问,开辟和释放内存也是更适合栈的实现,所以栈的实现是利用顺序表来实现的,即数组,malloc或realloc开辟的连续的空间。

    栈的操作是在栈顶,所以我们实现接口也是着重实现栈顶元素的删除(出栈),在栈顶加载上元素(压栈),获取栈顶的元素,其余就是初始化栈、获取元素的个数、顺序表是否为空(空会影响到压栈和出栈,压栈是否需要扩容,出栈判断元素为空时断言防止越界访问)、顺序表的销毁这些接口的实现。

    源代码

    头文件(主题框架)

    1. #include
    2. #include /*realloc,free*/
    3. #include /*assert*/
    4. #include /*bool*/
    5. typedef int DataType;
    6. typedef struct Stack
    7. {
    8. DataType* a;/*动态内存开辟的顺序表*/
    9. int capicity;/*容量*/
    10. int top;/*栈顶下标+1*/
    11. }ST;
    12. /*初始化*/
    13. void StackInit(ST* ps);
    14. /*销毁*/
    15. void Destroy(ST* ps);
    16. /*压栈*/
    17. void StackPush(ST* ps, DataType x);
    18. /*出栈*/
    19. void StackPop(ST* ps);
    20. /*判断是否为空*/
    21. bool StackEmpty(ST* ps);
    22. /*栈顶元素*/
    23. DataType StackTop(ST* s);
    24. /*元素个数*/
    25. int StackSize(ST* ps);

    源文件,各个接口的实现

    结构体的初始化

    1. /*初始化*/
    2. void StackInit(ST* ps)
    3. {
    4. assert(ps);
    5. ps->a = NULL;
    6. ps->top = ps->capicity = 0;
    7. }

    压栈

    1. /*压栈*/
    2. void StackPush(ST* ps,DataType x)
    3. {
    4. assert(ps);
    5. if (ps->top == ps->capicity)/*空间满或未开辟空间*/
    6. {
    7. int newcapicity = ps->capicity == 0 ? 4 : ps->capicity * 2;/*重新开辟空间,原来的2倍最好*/
    8. DataType* ptr = (DataType*)realloc(ps->a, sizeof(DataType) * newcapicity);
    9. if (ptr == NULL)
    10. {
    11. perror("realloc fail");
    12. exit(-1);
    13. }
    14. ps->a = ptr;
    15. ps->capicity = newcapicity;/*栈顶不变,容量变*/
    16. }
    17. ps->a[ps->top] = x;
    18. ++ps->top;
    19. }

    出栈

    1. /*出栈*/
    2. void StackPop(ST* ps)
    3. {
    4. assert(ps);
    5. assert(!StackEmpty(ps));/*防止越界访问*/
    6. --ps->top;
    7. }

    判断是否为空

    1. /*判断是否为空*/
    2. bool StackEmpty(ST* ps)/*传指针是因为如果传值,临时变量还需要耗费一定的空间*/
    3. {
    4. assert(ps);
    5. return ps->top == 0;
    6. }

    获取栈顶元素

    1. /*栈顶元素*/
    2. DataType StackTop(ST* ps)
    3. {
    4. assert(ps);
    5. assert(!StackEmpty(ps));/*空为真,不断言,所以反逻辑后的断言*/
    6. return ps->a[ps->top-1];/*top代表着栈顶的元素+1.比如top初始化为0,第一次压栈后top就从0变成了1*/
    7. }

    获取元素个数

    1. /*元素个数*/
    2. int StackSize(ST* ps)
    3. {
    4. assert(ps);
    5. return ps->top;
    6. }

    销毁

    1. void StackDestroy(ST* ps)
    2. {
    3. assert(ps);
    4. free(ps->a);
    5. ps->a = NULL;
    6. ps->capacity = ps->top = 0;
    7. }

    test.c源文件(main函数所在的.c源文件)

    1. #include "stack.h"
    2. void test()
    3. {
    4. ST st;
    5. StackInit(&st);
    6. StackPush(&st, 1);
    7. StackPush(&st, 2);
    8. StackPush(&st, 3);
    9. printf("%d ", StackTop(&st));
    10. StackPop(&st);
    11. printf("%d ", StackTop(&st));
    12. StackPop(&st);
    13. StackPush(&st, 4);
    14. StackPush(&st, 5);
    15. while (!StackEmpty(&st))
    16. {
    17. printf("%d ", StackTop(&st));
    18. StackPop(&st);
    19. }
    20. printf("\n");
    21. Destroy(&st);
    22. }
    23. int main()
    24. {
    25. test();
    26. return 0;
    27. }

    Stack.c各个接口的实现源文件的整合

    1. #include "stack.h"
    2. /*初始化*/
    3. void StackInit(ST* ps)
    4. {
    5. assert(ps);
    6. ps->a = NULL;
    7. ps->top = ps->capicity = 0;
    8. }
    9. /*销毁*/
    10. void Destroy(ST* ps)
    11. {
    12. assert(ps);
    13. free(ps->a);
    14. ps->a = NULL;
    15. ps->top = ps->capicity = 0;
    16. }
    17. /*压栈*/
    18. void StackPush(ST* ps,DataType x)
    19. {
    20. assert(ps);
    21. if (ps->top == ps->capicity)/*空间满或未开辟空间*/
    22. {
    23. int newcapicity = ps->capicity == 0 ? 4 : ps->capicity * 2;/*重新开辟空间,原来的2倍最好*/
    24. DataType* ptr = (DataType*)realloc(ps->a, sizeof(DataType) * newcapicity);
    25. if (ptr == NULL)
    26. {
    27. perror("realloc fail");
    28. exit(-1);
    29. }
    30. ps->a = ptr;
    31. ps->capicity = newcapicity;/*栈顶不变,容量变*/
    32. }
    33. ps->a[ps->top] = x;
    34. ++ps->top;
    35. }
    36. /*出栈*/
    37. void StackPop(ST* ps)
    38. {
    39. assert(ps);
    40. assert(!StackEmpty(ps));/*防止越界访问*/
    41. --ps->top;
    42. }
    43. /*判断是否为空*/
    44. bool StackEmpty(ST* ps)/*传指针是因为如果传值,临时变量还需要耗费一定的空间*/
    45. {
    46. assert(ps);
    47. return ps->top == 0;
    48. }
    49. /*栈顶元素*/
    50. DataType StackTop(ST* ps)
    51. {
    52. assert(ps);
    53. assert(!StackEmpty(ps));/*空为真,不断言,所以反逻辑后的断言*/
    54. return ps->a[ps->top-1];/*top代表着栈顶的元素+1.比如top初始化为0,第一次压栈后top就从0变成了1*/
    55. }
    56. /*元素个数*/
    57. int StackSize(ST* ps)
    58. {
    59. assert(ps);
    60. return ps->top;
    61. }

  • 相关阅读:
    【Linux】vim工具的使用
    记录一次项目依赖升级
    【Java探索之旅】运算符解析 算术运算符,关系运算符
    网站安全防护措施有哪些
    一个合约能存储多少数据?
    【MySQL】存储引擎简介、存储引擎特点、存储引擎区别
    STM32F4X UCOSIII 互斥量
    02 kafka 记录的获取
    PTA 7-18 二分法求多项式单根---代码+详细注释
    扩容磁盘的inode数量
  • 原文地址:https://blog.csdn.net/Scholar_zhang/article/details/126298530