• 【数据结构】栈和队列


    目录

    一 栈的概念及结构

    二 栈的实现

     1 包含所有接口(Stack.h) 

     2 初始化和销毁 (Stack.c)

     3 插入 (Stack.c)

     4 删除 (Stack.c)

     5 返回栈顶元素 (Stack.c)

     6 返回大小和判断是否为空 (Stack.c)

     7 测试(Test.c)

    三 队列的概念及其结构

    四 队列的实现 

     1 先包含所有接口(Queue.h)

     2 初始化和销毁(Queue.c)

     3 插入(Queue.c)

     4 删除(Queue.c)

     5 返回首队头数据和队尾数据(Queue.c)

     6 判断是否为空(Queue.c)

     7 返回size(Queue.c)

     8 测试(Test.c)


    一 栈的概念及结构

    栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。

    栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 出栈:栈的删除操作叫做出栈。出数据也在栈顶。

     

    二 栈的实现

    栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的 代价比较小。

    代码实现

    1 包含所有接口(Stack.h) 

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int STDataType;
    7. typedef struct Stack
    8. {
    9. STDataType* a;
    10. int top;
    11. int capacity;
    12. }ST;
    13. //初始化
    14. void STInit(ST* ps);
    15. //销毁
    16. void STDestroy(ST* ps);
    17. //插入
    18. void STPush(ST* ps, STDataType x);
    19. //删除
    20. void STPop(ST* ps);
    21. //返回栈顶元素
    22. STDataType STTop(ST* ps);
    23. //计算大小
    24. int STSize(ST* ps);
    25. //判断是否为空
    26. bool STEmpty(ST* ps);

     2 初始化和销毁 (Stack.c)

    1. //初始化
    2. void STInit(ST* ps)
    3. {
    4. assert(ps);
    5. ps->a = NULL;
    6. ps->top = 0;
    7. ps->capacity = 0;
    8. }
    9. //销毁
    10. void STDestroy(ST* ps)
    11. {
    12. assert(ps);
    13. free(ps->a);
    14. ps->a = NULL;
    15. ps->top = ps->capacity = 0;
    16. }

     3 插入 (Stack.c)

    1. //插入
    2. void STPush(ST* ps, STDataType x)
    3. {
    4. assert(ps);
    5. //检查是否扩容
    6. if (ps->top == ps->capacity)
    7. {
    8. int newCapacity = ps->capacity == 0 ? 4 : ps->capacity *2;//扩两倍
    9. STDataType tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * (newCapacity));//realloc也可以原地扩容
    10. if (tmp == NULL)
    11. {
    12. perror("realloc failed");
    13. exit(-1);
    14. }
    15. ps->a = tmp;
    16. ps->capacity = newCapacity;
    17. }
    18. //插入
    19. ps->a[ps->top] = x;
    20. ps->top++;//top是栈顶的下一个位置
    21. }

    4 删除 (Stack.c)

    1. //删除
    2. void STPop(ST* ps)
    3. {
    4. assert(ps);
    5. assert(ps->top > 0);
    6. ps->top--;
    7. }

     5 返回栈顶元素 (Stack.c)

    1. //返回栈顶元素
    2. STDataType STTop(ST* ps)
    3. {
    4. assert(ps);
    5. assert(ps->top > 0);
    6. return ps->a[ps->top - 1];
    7. }

     6 返回大小和判断是否为空 (Stack.c)

    1. //计算大小
    2. int STSize(ST* ps)
    3. {
    4. assert(ps);
    5. return ps->top;
    6. }
    7. //判断是否为空
    8. bool STEmpty(ST* ps)
    9. {
    10. assert(ps);
    11. return ps->top == 0;
    12. }

    7 测试(Test.c)

    1. #include "Stack.h"
    2. void TestStack1()
    3. {
    4. ST st;
    5. STInit(&st);
    6. STPush(&st, 1);
    7. STPush(&st, 2);
    8. STPush(&st, 3);
    9. STPush(&st, 4);
    10. STPush(&st, 5);
    11. while (!STEmpty(&st))
    12. {
    13. printf("%d ", STTop(&st));
    14. STPop(&st);
    15. }
    16. printf("\n");
    17. STDestroy(&st);
    18. }
    19. int main()
    20. {
    21. TestStack1();
    22. return 0;
    23. }

    三 队列的概念及其结构

    队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

    四 队列的实现 

    队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数 组头上出数据,效率会比较低

     1 先包含所有接口(Queue.h)

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int QDataType;
    7. typedef struct QueueNode
    8. {
    9. struct QueueNode* next;
    10. QDataType data;
    11. }QNode;
    12. typedef struct Queue
    13. {
    14. QNode* head;
    15. QNode* tail;
    16. int size;
    17. }Que;
    18. //初始化
    19. void QueueInit(Que* pq);
    20. //销毁
    21. void QueueDestroy(Que* pq);
    22. //插入
    23. void QueuePush(Que* pq, QDataType x);
    24. //删除
    25. void QueuePop(Que* pq);
    26. //返回第一个
    27. QDataType QueueFront(Que* pq);
    28. //返回末尾
    29. QDataType QueueBack(Que* pq);
    30. //是否为空
    31. bool QueueEmpty(Que* pq);
    32. //计算大小
    33. int QueueSize(Que* pq);

      2 初始化和销毁(Queue.c)

    1. //初始化
    2. void QueueInit(Que* pq)
    3. {
    4. assert(pq);
    5. pq->head = pq->tail = NULL;
    6. pq->size = 0;
    7. }
    8. //销毁
    9. void QueueDestroy(Que* pq)
    10. {
    11. assert(pq);
    12. QNode* cur = pq->head;
    13. while (cur)
    14. {
    15. QNode* next = cur->next;
    16. free(cur);
    17. cur = next;
    18. }
    19. pq->head = pq->tail = NULL;
    20. pq->size = 0;
    21. }

    3 插入(Queue.c)

    1. //插入
    2. void QueuePush(Que* pq, QDataType x)
    3. {
    4. assert(pq);
    5. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    6. if (newnode == NULL)
    7. {
    8. perror("malloc fail");
    9. exit(-1);
    10. }
    11. newnode->data = x;
    12. newnode->next = NULL;
    13. if (pq->tail == NULL)
    14. {
    15. pq->head = pq->tail = newnode;
    16. }
    17. else
    18. {
    19. pq->tail->next = newnode;
    20. pq->tail = newnode;
    21. }
    22. pq->size++;
    23. }

    4 删除(Queue.c)

    1. //删除
    2. void QueuePop(Que* pq)
    3. {
    4. assert(pq);
    5. assert(!QueueEmpty(pq));
    6. if (pq->head->next == NULL)
    7. {
    8. free(pq->head);
    9. pq->head = pq->tail = NULL;
    10. }
    11. else
    12. {
    13. QNode* newhead = pq->head->next;
    14. free(pq->head);
    15. pq->head = newhead;
    16. }
    17. pq->size--;
    18. }

    5 返回首队头数据和队尾数据(Queue.c)

    1. QDataType QueueFront(Que* pq)
    2. {
    3. assert(pq);
    4. assert(!QueueEmpty(pq));
    5. return pq->head->data;
    6. }
    7. QDataType QueueBack(Que* pq)
    8. {
    9. assert(pq);
    10. assert(!QueueEmpty(pq));
    11. return pq->tail->data;
    12. }

    6 判断是否为空(Queue.c)

    1. bool QueueEmpty(Que* pq)
    2. {
    3. assert(pq);
    4. return pq->head == NULL;
    5. }

    7 返回size(Queue.c)

    1. int QueueSize(Que* pq)
    2. {
    3. assert(pq);
    4. return pq->size;
    5. }

    8 测试(Test.c)

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"Queue.h"
    3. Test()
    4. {
    5. Que pq;
    6. QueueInit(&pq);
    7. QueuePush(&pq, 1);
    8. QueuePush(&pq, 2);
    9. QueuePush(&pq, 3);
    10. QueuePush(&pq, 4);
    11. QueuePush(&pq, 5);
    12. while(!QueueEmpty(&pq))
    13. {
    14. printf("%d ", QueueFront(&pq));
    15. QueuePop(&pq);
    16. }
    17. QueueDestroy(&pq);
    18. }
    19. int main()
    20. {
    21. Test();
    22. return 0;
    23. }

    栈和队列感觉就是链表和顺序表的变形, 很容易理解,下一章我会对栈和队列的OJ进行整理和讲解, 继续加油!

  • 相关阅读:
    PHP:比较运算符
    【详细教程】手把手教你开通YouTube官方API接口(youtube data api v3)
    3D感知(一):初步认识
    NLP中基于Bert的数据预处理
    SpringMVC系列(六)之JSON数据返回以及异常处理机制
    Nvidia-docker运行错误- Nvidia-docker : Unknown runtime specified nvidia
    鉴源论坛 · 观擎丨基于模型的方法在民机机载软件中的应用
    模仿学习(DMP与GMM应用)
    HMM代码参数
    前端第一阶段测试
  • 原文地址:https://blog.csdn.net/yf214wxy/article/details/133209199