• C语言描述数据结构 —— 栈和队列


    1. 栈

    1.1 栈的概念以及结构

    栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出(先进后出)的原则。

    压栈:栈的插入草错叫做进栈、压栈、入栈。

     

    出栈:栈的删除操作叫做出栈。

    1.2 栈的实现

    我们介绍过顺序表和链表,那么要实现栈的数据结构用顺序表合适还是用链表合适呢?一般都是用顺序表,因为对于栈的数据结构来说,只涉及到尾插尾删,所以综合顺序表和链表,顺序表是更占优势的。 

     

    1. //Stack.h 头文件
    2. #include
    3. #include
    4. #include
    5. #include
    6. //可以动态开辟空间的栈
    7. typedef int StackData;
    8. typedef struct Stack
    9. {
    10. StackData* a;
    11. int top;//与顺序表的 size 一致
    12. int capacity;
    13. }Stack;
    14. void StackInit(Stack* ps);//栈初始化
    15. void StackPush(Stack* ps,StackData x);//入栈
    16. void StackPop(Stack* ps);//出栈
    17. StackData StackTop(Stack* ps);//获取栈顶元素
    18. bool StackEmpty(Stack* ps);//判断栈是否为空
    19. int StackSize(Stack* ps);//计算栈元素个数
    20. void StackDestroy(Stack* ps);//栈销毁
    1. #include "Stack.h"
    2. //初始化栈
    3. void StackInit(Stack* ps)
    4. {
    5. assert(ps);
    6. //栈的初始容量置空
    7. ps->a = NULL;
    8. ps->top = ps->capacity = 0;
    9. }
    10. //入栈
    11. void StackPush(Stack* ps,StackData x)
    12. {
    13. assert(ps);
    14. //入栈只有一种方式,所以不需要将扩容独立封装
    15. if (ps->top == ps->capacity)
    16. {
    17. int NewCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
    18. StackData* tmp = (StackData*)realloc(ps->a, NewCapacity*sizeof(StackData));
    19. assert(tmp);
    20. ps->a = tmp;
    21. ps->capacity = NewCapacity;
    22. }
    23. ps->a[ps->top] = x;
    24. ps->top++;
    25. }
    26. //出栈
    27. void StackPop(Stack* ps)
    28. {
    29. assert(ps);
    30. assert(!StackEmpty(ps));
    31. ps->top--;
    32. }
    33. //获取栈顶元素
    34. StackData StackTop(Stack* ps)
    35. {
    36. assert(ps);
    37. return ps -> a[ps->top - 1];
    38. }
    39. //判断栈是否为空
    40. bool StackEmpty(Stack* ps)
    41. {
    42. assert(ps);
    43. return ps->top == 0;//等于 0 则返回true,即栈为空
    44. }
    45. //计算栈中元素个数
    46. int StackSize(Stack* ps)
    47. {
    48. assert(ps);
    49. return ps->top;
    50. }
    51. //栈销毁
    52. void StackDestroy(Stack* ps)
    53. {
    54. assert(ps);
    55. free(ps->a);
    56. ps->a = NULL;
    57. ps->top = ps->capacity = 0;
    58. }
    1. //test.c 源文件
    2. #include "Stack.h"
    3. void StackTest()
    4. {
    5. Stack s;
    6. StackInit(&s);//栈初始化
    7. //入栈测试
    8. StackPush(&s, 10);
    9. StackPush(&s, 20);
    10. StackPush(&s, 30);
    11. printf("%d\n", StackSize(&s));
    12. while (!StackEmpty(&s))
    13. {
    14. printf("%d ", StackTop(&s));
    15. StackPop(&s);
    16. }
    17. printf("\n");
    18. printf("%d\n", StackSize(&s));
    19. StackDestroy(&s);
    20. }
    21. int main()
    22. {
    23. StackTest();
    24. return 0;
    25. }

    2. 队列

    2.1 队列的概念及结构

    队列只运训在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。队列具有先进先出的特点。进行插入操作的一段称为队尾,进行删除操作的一端称为队头

     2.2 队列的实现

    我们采用无头单向不循环链表来实现队列。因为队列的特性,用链表描述可以说只涉及到尾插、头删。那么单链表是非常符合这个特性的。

    1. // Queue.h 头文件
    2. #include
    3. #include
    4. #include
    5. #include
    6. //链表的结点
    7. typedef int QueueData;
    8. typedef struct QueueNode
    9. {
    10. QueueData val;
    11. struct QueueNode* next;
    12. }QueueNode;
    13. //存储头、尾结点地址的指针
    14. typedef struct HeadTail
    15. {
    16. QueueNode* head;
    17. QueueNode* tail;
    18. int size;//记录队列有几个元素
    19. }HeadTail;
    20. void QueueInit(HeadTail* p);//初始化队列
    21. void QueuePush(HeadTail* p,QueueData x);//进入队列
    22. QueueData QueueHead(HeadTail* p);//获取队头元素
    23. QueueData QueueTail(HeadTail* p);//获取队尾元素
    24. void QueuePop(HeadTail* p);//删除操作,出队
    25. bool QueueEmpty(HeadTail* p);//检查队列是否为空
    26. int QueueSize(HeadTail* p);//获取队列元素个数
    27. void QueueDestroy(HeadTail* p);//销毁队列
    1. // Queue.c 源文件
    2. #include "Queue.h"
    3. //初始化
    4. void QueueInit(HeadTail* p)
    5. {
    6. assert(p);
    7. p->head = p->tail = NULL;
    8. p->size = 0;
    9. }
    10. //队列尾插
    11. void QueuePush(HeadTail* p, QueueData x)
    12. {
    13. assert(p);
    14. //创建一个新结点
    15. QueueNode* newnode = (QueueNode*)calloc(1, sizeof(QueueNode));
    16. assert(newnode);
    17. newnode->val = x;
    18. newnode->next = NULL;
    19. //如果链表内没有结点,头尾指针指向同一个结点
    20. if (p->head == NULL)
    21. {
    22. p->head = newnode;
    23. p->tail = newnode;
    24. }
    25. //否则尾指针需要变化
    26. else
    27. {
    28. p->tail->next = newnode;
    29. p->tail = newnode;
    30. }
    31. p->size++;
    32. }
    33. //获取队头元素
    34. QueueData QueueHead(HeadTail* p)
    35. {
    36. assert(p);
    37. assert(!QueueEmpty(p));
    38. return p->head->val;
    39. }
    40. //获取队尾元素
    41. QueueData QueueTail(HeadTail* p)
    42. {
    43. assert(p);
    44. assert(!QueueEmpty(p));
    45. return p->tail->val;
    46. }
    47. //删除、出队
    48. void QueuePop(HeadTail* p)
    49. {
    50. assert(p);
    51. assert(!QueueEmpty(p));
    52. //如果链表只有一个结点
    53. if (p->head == p->tail)
    54. {
    55. free(p->head);
    56. p->head = p->tail = NULL;
    57. }
    58. //否则进行头删
    59. else
    60. {
    61. QueueNode* cur = p->head;
    62. p->head = p->head->next;
    63. free(cur);
    64. cur = NULL;
    65. }
    66. p->size--;
    67. }
    68. //检测队列是否为空
    69. bool QueueEmpty(HeadTail* p)
    70. {
    71. assert(p);
    72. return p->head == NULL && p->tail == NULL;
    73. }
    74. //获取队列元素个数
    75. int QueueSize(HeadTail* p)
    76. {
    77. assert(p);
    78. return p->size;
    79. }
    80. //销毁队列
    81. void QueueDestroy(HeadTail* p)
    82. {
    83. assert(p);
    84. QueueNode* cur = p->head;
    85. while (cur)
    86. {
    87. QueueNode* del = cur;
    88. cur = cur->next;
    89. free(del);
    90. }
    91. }
    1. // test.c 源文件
    2. #include "Queue.h"
    3. void TestQueue()
    4. {
    5. HeadTail p;
    6. QueueInit(&p);
    7. QueuePush(&p, 1);
    8. QueuePush(&p, 2);
    9. QueuePush(&p, 3);
    10. QueuePush(&p, 4);
    11. printf("%d\n", QueueSize(&p));
    12. //进入队列的顺序为 1、2、3、4
    13. while (!QueueEmpty(&p))
    14. {
    15. //所以打印的顺序也为 1、2、3、4
    16. //先进先出
    17. printf("%d ", QueueHead(&p));
    18. QueuePop(&p);
    19. }
    20. printf("\n");
    21. printf("%d\n", QueueSize(&p));
    22. QueueDestroy(&p);
    23. }
    24. int main()
    25. {
    26. TestQueue();
    27. return 0;
    28. }

     

  • 相关阅读:
    1.7 Elasticsearch分词与内置分词器
    搜索引擎研究-如何分词-高级分词-基础分词后组合复合词汇
    超详细的Pycharm.2023下载与安装教程
    测试项目中的风险管理
    LeetCode题解:剑指 Offer 03. 数组中重复的数字,原地置换,JavaScript,详细注释
    古代汉语 郭锡良版本 复习要点
    3D激光点云霍夫变换拟合直线
    CS224W2.2——传统基于特征的方法(边层级特征)
    德鲁克《卓有成效的管理者》学习&读书-总结
    基于百度地图实现矩形绘制/电子围栏/自定义覆盖物选择、点击、区域选中、轨迹绘制
  • 原文地址:https://blog.csdn.net/weixin_59913110/article/details/126179062