• 【数据结构初阶】一文详解顺序栈和链队列的基本操作


    目录

    1.栈的概念

     2.栈的结构

     3.实现栈的基本操作

    3.1栈的初始化

    3.2压栈

    3.3出栈

    3.4 取栈顶元素

    3.5 计算栈内元素个数

    3.6栈的判空

    3.7栈的销毁

    4.源代码

    4.1stack.c

    4.2stack.h

    4.3test.c

     4.4效果

    1.队列的概念

     2.队列的结构

     3.实现队列的基本操作

    3-1结构体定义

    3-2队列的初始化

    3-3入队列

    3-4出队列

    3-5取队头元素

    3-6取队尾元素

    3-7队列判空

    3-8队列长度

    3-9队列销毁

    4.源代码

    4-1queue.c

    4.2queue.h

    4.3test.c

    4.4效果图


    1.栈的概念

    栈,一种特殊的线性表,特殊在于只允许在固定的一端进行插入删除数据,插入和删除数据的一端是栈顶,另一端是栈底,已经在栈中的数据满足Fist In  Last Out的原则。

    压栈:栈顶插入数据

    出栈:栈顶弹出数据

     

     2.栈的结构

    总体而言,用顺序表和链表实现都可以,但是由于栈只支持在栈顶插入删除数据,且要满足后进先出,而顺序表尾插尾删的效率比链表高,(顺序表唯一的缺点在这就是扩容有性能和空间的消耗)同时也满足后进先出的原则,所以选择顺序表实现好!

    有人可能会说用链表,然后定义一个尾指针,这样尾插效率不是也很高吗?

    答:定义一个尾指针,链表的插入时很方便,但是尾删呐??

    其实顺序表,双向循环链表,头上操作单链表都行,但是由于顺序表命中率高的优点,还是选择顺序表。

     3.实现栈的基本操作

    3.1栈的初始化

    1.  选择哪一个方式初始化top都可以,但是记得做到和后面的push等做到统一。
    2.  建议再主函数内判空操作不直接自己if(ps->top==0)等,因为这个内部怎么实现的不一定是初始化为ps->top=0,而是建议调用函数去判空if(StackEmpty(&ST))
    1. void StackInit(Stack* ps)
    2. {
    3. assert(ps);
    4. ps->a = NULL;
    5. ps->top = ps->capacity = 0;
    6. }

    3.2压栈

    1. void StackPush(Stack* ps, STDateType x)
    2. {
    3. assert(ps);
    4. if(ps->top == ps->capacity)
    5. {
    6. int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;
    7. STDateType* temp = (STDateType*)realloc(ps->a, sizeof(STDateType)*newcapacity);
    8. if (temp == NULL)
    9. {
    10. perror("malloc fail.\n");
    11. exit(-1);
    12. }
    13. ps->capacity = newcapacity;
    14. ps->a = temp;
    15. }
    16. ps->a[ps->top] = x;
    17. ps->top++;
    18. }

    3.3出栈

     

    1. void StackPop(Stack* ps)
    2. {
    3. assert(ps);
    4. assert(!StackEmpty(ps));
    5. ps->top--;
    6. }

    3.4 取栈顶元素

    1. STDateType StackTop(Stack* ps)
    2. {
    3. assert(ps);
    4. assert(!StackEmpty(ps));
    5. return ps->a[ps->top - 1];
    6. }

    3.5 计算栈内元素个数

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

    3.6栈的判空

    1. bool StackEmpty(Stack* ps)
    2. {
    3. assert(ps);
    4. return ps->top == 0;
    5. }

    3.7栈的销毁

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

    4.源代码

    4.1stack.c

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"stack.h"
    3. void StackInit(Stack* ps)
    4. {
    5. assert(ps);
    6. ps->a = NULL;
    7. ps->top = ps->capacity = 0;
    8. }
    9. void StackPush(Stack* ps, STDateType x)
    10. {
    11. assert(ps);
    12. if(ps->top == ps->capacity)
    13. {
    14. int newcapacity = ps->capacity == 0 ? 4 : ps->capacity*2;
    15. STDateType* temp = (STDateType*)realloc(ps->a, sizeof(STDateType)*newcapacity);
    16. if (temp == NULL)
    17. {
    18. perror("malloc fail.\n");
    19. exit(-1);
    20. }
    21. ps->capacity = newcapacity;
    22. ps->a = temp;
    23. }
    24. ps->a[ps->top] = x;
    25. ps->top++;
    26. }
    27. void StackPop(Stack* ps)
    28. {
    29. assert(ps);
    30. assert(!StackEmpty(ps));
    31. ps->top--;
    32. }
    33. STDateType StackTop(Stack* ps)
    34. {
    35. assert(ps);
    36. assert(!StackEmpty(ps));
    37. return ps->a[ps->top - 1];
    38. }
    39. int StackSize(Stack* ps)
    40. {
    41. assert(ps);
    42. return ps->top;
    43. }
    44. bool StackEmpty(Stack* ps)
    45. {
    46. assert(ps);
    47. return ps->top == 0;
    48. }
    49. void StackDestory(Stack* ps)
    50. {
    51. assert(ps);
    52. free(ps->a);
    53. ps->a = NULL;
    54. ps->top = ps->capacity = 0;
    55. }

    4.2stack.h

     

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int STDateType;
    7. typedef struct Stack
    8. {
    9. STDateType* a;
    10. int top;
    11. int capacity;
    12. }Stack;
    13. void StackInit(Stack* ps);
    14. void StackPush(Stack* ps,STDateType x);
    15. void StackPop(Stack* ps);
    16. STDateType StackTop(Stack* ps);
    17. bool StackEmpty(Stack* ps);
    18. int StackSize(Stack* ps);
    19. void StackDestory(Stack* ps);

    4.3test.c

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"stack.h"
    3. int main()
    4. {
    5. Stack ST;
    6. StackInit(&ST);
    7. StackPush(&ST, 1);
    8. StackPush(&ST, 2);
    9. StackPush(&ST, 3);
    10. StackPush(&ST, 4);
    11. STDateType top = StackTop(&ST);
    12. printf("top:%d\n", top);
    13. StackPop(&ST);
    14. top = StackTop(&ST);
    15. printf("top:%d\n", top);
    16. int size = StackSize(&ST);
    17. printf("size:%d\n", size);
    18. StackDestory(&ST);
    19. return 0;
    20. }

     4.4效果图


    1.队列的概念

    队列是一种特殊的线性表,特殊在只能从一端进行插入操作,另一端进行删除操作,队列具有Fist  In First Out的原则。

    队尾:进行插入操作的一端,这个过程叫做入队列

    队头:进行删除操作的一端,这个过程叫做出队列

    抽号机:先来先服务,先给号码排队 (涉及嵌入式)

     

     

     2.队列的结构

    队列我们采用链表实现:顺序表在满了要扩容,删完了后再入队列的时候还得扩容

    链表的话,入队列就是尾插,定义一个尾指针。出队列就是头删,定义一个头指针

     3.实现队列的基本操作

    3-1结构体定义

     

    1. typedef int QDateType;
    2. typedef struct QueueNode
    3. {
    4. struct QueueNode* next;
    5. QDateType val;
    6. }QueueNode;
    7. typedef struct Queue
    8. {
    9. QueueNode* head;
    10. QueueNode* tail;
    11. }Queue;

    3-2队列的初始化

    这里的链表队列我并没有带头,没有带头就要在入队列和出队列时有一点特殊情况的考虑

    1. void QueueInit(Queue* ps)
    2. {
    3. assert(ps);
    4. ps->head = ps->tail = NULL;
    5. }

    3-3入队列

    相当于尾插,考虑特殊情况:队列为空的情况

    1. //入队列:尾插
    2. void QueuePush(Queue* ps,QDateType x)
    3. {
    4. assert(ps);
    5. QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
    6. newnode->next = NULL;
    7. newnode->val = x;
    8. if (newnode == NULL)
    9. {
    10. perror("malloc fail.");
    11. exit(-1);
    12. }
    13. if (ps->tail == NULL)
    14. {
    15. ps->head = ps->tail = newnode;
    16. }
    17. else
    18. {
    19. ps->tail->next = newnode;
    20. ps->tail = ps->tail->next;
    21. }
    22. }

    3-4出队列

    相当于头删,考虑特殊情况:只有一个结点的情况,出队列后要改变ps->tail

    1. void QueuePop(Queue* ps)
    2. {
    3. assert(ps);
    4. assert(!QueueEmpty(ps));
    5. if (ps->head->next == NULL)
    6. {
    7. free(ps->head);
    8. ps->head = ps->tail = NULL;
    9. }
    10. else
    11. {
    12. QueueNode* next = ps->head->next;
    13. free(ps->head);
    14. ps->head = next;
    15. }
    16. }

    3-5取队头元素

    1. QDateType QueueFront(Queue* ps)
    2. {
    3. assert(ps);
    4. assert(!QueueEmpty(ps));
    5. return ps->head->val;
    6. }

    3-6取队尾元素

    1. QDateType QueueBack(Queue* ps)
    2. {
    3. assert(ps);
    4. assert(!QueueEmpty(ps));
    5. return ps->tail->val;
    6. }

    3-7队列判空

    1. bool QueueEmpty(Queue* ps)
    2. {
    3. assert(ps);
    4. return ps->tail == NULL;
    5. }

    3-8队列长度

    1. int QueueSize(Queue* ps)
    2. {
    3. assert(ps);
    4. int size = 0;
    5. QueueNode* cur = ps->head;
    6. while(cur)
    7. {
    8. ++size;
    9. cur = cur->next;
    10. }
    11. return size;
    12. }

    3-9队列销毁

    1. void QueueDestory(Queue* ps)
    2. {
    3. assert(ps);
    4. QueueNode* cur = ps->head;
    5. while (cur)
    6. {
    7. QueueNode* next = cur->next;
    8. free(cur);
    9. cur = next;
    10. }
    11. ps->head = ps->tail = NULL;
    12. }

    4.源代码

    4-1queue.c

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"queue.h"
    3. void QueueInit(Queue* ps)
    4. {
    5. assert(ps);
    6. ps->head = ps->tail = NULL;
    7. }
    8. void QueueDestory(Queue* ps)
    9. {
    10. assert(ps);
    11. QueueNode* cur = ps->head;
    12. while (cur)
    13. {
    14. QueueNode* next = cur->next;
    15. free(cur);
    16. cur = next;
    17. }
    18. ps->head = ps->tail = NULL;
    19. }
    20. //入队列:尾插
    21. void QueuePush(Queue* ps,QDateType x)
    22. {
    23. assert(ps);
    24. QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
    25. newnode->next = NULL;
    26. newnode->val = x;
    27. if (newnode == NULL)
    28. {
    29. perror("malloc fail.");
    30. exit(-1);
    31. }
    32. if (ps->tail == NULL)
    33. {
    34. ps->head = ps->tail = newnode;
    35. }
    36. else
    37. {
    38. ps->tail->next = newnode;
    39. ps->tail = ps->tail->next;
    40. }
    41. }
    42. void QueuePop(Queue* ps)
    43. {
    44. assert(ps);
    45. assert(!QueueEmpty(ps));
    46. if (ps->head == ps->tail)
    47. {
    48. free(ps->head);
    49. ps->head = ps->tail = NULL;
    50. }
    51. else
    52. {
    53. QueueNode* next = ps->head->next;
    54. free(ps->head);
    55. ps->head = next;
    56. }
    57. }
    58. QDateType QueueFront(Queue* ps)
    59. {
    60. assert(ps);
    61. assert(!QueueEmpty(ps));
    62. return ps->head->val;
    63. }
    64. QDateType QueueBack(Queue* ps)
    65. {
    66. assert(ps);
    67. assert(!QueueEmpty(ps));
    68. return ps->tail->val;
    69. }
    70. bool QueueEmpty(Queue* ps)
    71. {
    72. assert(ps);
    73. return ps->tail == NULL;
    74. }
    75. int QueueSize(Queue* ps)
    76. {
    77. assert(ps);
    78. int size = 0;
    79. QueueNode* cur = ps->head;
    80. while(cur)
    81. {
    82. ++size;
    83. cur = cur->next;
    84. }
    85. return size;
    86. }

    4.2queue.h

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int QDateType;
    7. typedef struct QueueNode
    8. {
    9. struct QueueNode* next;
    10. QDateType val;
    11. }QueueNode;
    12. typedef struct Queue
    13. {
    14. QueueNode* head;
    15. QueueNode* tail;
    16. }Queue;
    17. void QueueInit(Queue* ps);
    18. void QueuePush(Queue* ps, QDateType x);
    19. void QueuePop(Queue* ps);
    20. QDateType QueueFront(Queue* ps);
    21. QDateType QueueBack(Queue* ps);
    22. bool QueueEmpty(Queue* ps);
    23. int QueueSize(Queue* ps);
    24. void QueueDestory(Queue* ps);

    4.3test.c

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"queue.h"
    3. int main()
    4. {
    5. Queue Q;
    6. QueueInit(&Q);
    7. QueuePush(&Q, 1);
    8. QueuePush(&Q, 2);
    9. QueuePush(&Q, 3);
    10. QueuePush(&Q, 4);
    11. QueuePush(&Q, 5);
    12. QDateType ret1 = QueueFront(&Q);
    13. printf("QueueFront:%d\n", ret1);
    14. QDateType ret2 = QueueBack(&Q);
    15. printf("QueueBack:%d\n", ret2);
    16. int size = QueueSize(&Q);
    17. printf("size:%d\n", size);
    18. while (!QueueEmpty(&Q))
    19. {
    20. printf("%d", QueueFront(&Q));
    21. QueuePop(&Q);
    22. }
    23. QueueDestory(&Q);
    24. return 0;
    25. }

    4.4效果图

     制作不易,敬请三连

  • 相关阅读:
    迈德威视工业相机 Linux驱动详细步骤
    智慧学习环境移动智能终端零信任安全机制改进方案
    [Python进阶] 消息框、弹窗:tkinter库
    spring5.3 十四:spring AOP源码分析
    基于JSP的图书销售管理系统
    web框架之路由列表及SQL语句查询数据库数据替换模板变量
    大华智慧园区前台任意文件上传(1day)
    Linux脚本练习之script083-nginx日志分析之查询某个IP的详细访问情况
    大学生川菜网页制作教程 学生HTML静态美食菜品网页设计作业成品 简单网页制作代码 学生美食网页作品免费设计
    【k8s】4、资源管理命令-陈述式
  • 原文地址:https://blog.csdn.net/qq_64428099/article/details/126173181