• 数据结构——栈和队列


    目录

    习题 

     结构体的创建

    初始化 

    销毁开辟空间 

    入栈 

    出栈 

    当前栈顶

    判断栈是否为空 

    统计个数 

    力扣习题——有效的括号 

     队列

     结构体的建立

    初始化 

    动态内存销毁 

    入队

     出队

     提取数据

     判断是否为空

    队内元素个数统计 


     栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。栈向下增长
    压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
    出栈:栈的删除操作叫做出栈。出数据也在栈顶

     

     动态开辟在堆区,堆向上增长,递归次数过多会导致栈溢出

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

    习题 

     1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出
    栈的顺序是( )。
    A 12345ABCDE
    B EDCBA54321
    C ABCDE12345
    D 54321EDCBA

    B 先进后出

    2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是()
    A 1,4,3,2
    B 2,3,4,1
    C 3,1,4,2
    D 3,4,2,1
    C A1先入,再出1,然后入2,3,4,出4,3,2

        B先入1,2出2,入3,出3,入4,出4,出1

        D入1,2,3出3,入4,出4,出2,出1

     结构体的创建

    1. typedef int STDdtaTtype;
    2. typedef struct Stcak
    3. {
    4. STDdtaTtype* data;
    5. int top;
    6. int capacity;
    7. }ST;

    初始化 

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

    销毁开辟空间 

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

    入栈 

    1. void StackPush(ST* ps, STDdtaTtype x)//注意要看top的位置是0还是-1
    2. {
    3. assert(ps);
    4. int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
    5. if (ps->capacity == ps->top)//判断是否满了
    6. {
    7. STDdtaTtype* tmp = realloc(ps->data, sizeof(ps) * newcapacity);
    8. if (tmp == NULL)
    9. {
    10. perror("realloc fail");
    11. exit(-1);
    12. }
    13. ps->data = tmp;
    14. ps->capacity = newcapacity;
    15. }
    16. ps->data[ps->top] = x;
    17. ps->top++;
    18. }

    出栈 

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

    当前栈顶

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

    判断栈是否为空 

    1. bool StackEmpty(ST* ps)//判断是否为空栈
    2. {
    3. assert(ps);
    4. return ps->top == 0;
    5. }

    统计个数 

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

    力扣习题——有效的括号 

     20. 有效的括号 - 力扣(LeetCode)

     

    当s指向左括号时,把该括号放入栈内

    入完栈之后s不等于左括号,s等于右括号,然后将栈内的元素一个个拿出来跟s所指括号比较,若能匹配成功,则进行下一轮比较,反之则直接返回false

    1. typedef char STDdtaTtype;
    2. typedef struct Stcak
    3. {
    4. STDdtaTtype* data;
    5. int top;
    6. int capacity;
    7. }ST;
    8. void StackInit(ST* ps);
    9. void StackDestory(ST* ps);
    10. void StackPush(ST* ps, STDdtaTtype x);
    11. void StackPop(ST* ps);
    12. bool StackEmpty(ST* ps);
    13. int StackSize(ST* ps);
    14. STDdtaTtype StackTop(ST* ps);
    15. void StackInit(ST* ps)
    16. {
    17. assert(ps);
    18. ps->data = NULL;
    19. ps->capacity = ps->top = 0;
    20. }
    21. void StackDestory(ST* ps)
    22. {
    23. assert(ps);
    24. free(ps->data);
    25. ps->capacity = ps->top = 0;
    26. ps->data = NULL;
    27. }
    28. void StackPush(ST* ps, STDdtaTtype x)//注意要看top的位置是0还是-1
    29. {
    30. assert(ps);
    31. int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
    32. if (ps->capacity == ps->top)//判断是否满了
    33. {
    34. STDdtaTtype* tmp = realloc(ps->data, sizeof(ps) * newcapacity);
    35. if (tmp == NULL)
    36. {
    37. perror("realloc fail");
    38. exit(-1);
    39. }
    40. ps->data = tmp;
    41. ps->capacity = newcapacity;
    42. }
    43. ps->data[ps->top] = x;
    44. ps->top++;
    45. }
    46. void StackPop(ST* ps)
    47. {
    48. assert(ps);
    49. assert(!StackEmpty(ps));
    50. --ps->top;
    51. }
    52. STDdtaTtype StackTop(ST* ps)
    53. {
    54. assert(ps);
    55. assert(!StackEmpty(ps));
    56. return ps->data[ps->top - 1];
    57. }
    58. bool StackEmpty(ST* ps)//判断是否为空栈
    59. {
    60. assert(ps);
    61. return ps->top == 0;
    62. }
    63. int StackSize(ST* ps)
    64. {
    65. assert(ps);
    66. return ps->top;
    67. }

     把上面栈的函数都复制下来,进行括号匹配

    1. bool isValid(char * s){
    2. ST st;
    3. StackInit(&st);
    4. while(*s)
    5. {
    6. if(*s=='['||*s=='{'||*s=='(')
    7. {
    8. StackPush(&st,*s);
    9. }
    10. else
    11. {
    12. if(StackEmpty(&st))//若栈内为空,直接返回false,这种情况如只S数组只有一个[
    13. {
    14. StackDestory(&st);//防止内存泄漏
    15. return false;
    16. }
    17. STDdtaTtype top=StackTop(&st);
    18. StackPop(&st);
    19. if(*s==']'&&top!='['
    20. ||*s=='}'&&top!='{'
    21. ||*s==')'&&top!='(')
    22. {
    23. return false;
    24. }
    25. }
    26. s++;
    27. }
    28. bool flag=(StackEmpty(&st));//若全部匹配则,栈内为空,若没有则不为空
    29. StackDestory(&st);
    30. return flag;
    31. }

     队列

     队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
    FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头,一般用单链表实现队列,双向链表比较浪费

     结构体的建立

    1. typedef int QDataType;
    2. typedef struct QueueNode
    3. {
    4. struct QueueNode* next;
    5. QDataType data;
    6. }QNode;
    7. typedef struct Queue
    8. {
    9. QNode* head;
    10. QNode* tail;
    11. size_t size;
    12. }Queue;

    初始化 

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

    动态内存销毁 

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

    入队

    1. void QueuePush(Queue* pq, QDataType x)
    2. {
    3. assert(pq);
    4. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    5. assert(newnode);
    6. newnode->data = x;
    7. newnode->next = NULL;
    8. if (pq->tail == NULL)
    9. {
    10. pq->head = pq->tail = newnode;
    11. }
    12. else
    13. {
    14. pq->tail->next = newnode;
    15. pq->tail = pq->tail->next;
    16. }
    17. pq->size++;
    18. }

     出队

    1. void QueuePop(Queue* pq)
    2. {
    3. assert(pq);
    4. assert(!QueueEmpty(pq));
    5. if (pq->head->next == NULL)
    6. {
    7. free(pq->head);
    8. pq->head = pq->tail = NULL;
    9. }//如果只剩一个节点,单独处理,要不染当head遍历到tail时候,tail会成为野指针,这里要防止tail变为野指针
    10. else
    11. {
    12. QNode* cur = pq->head;
    13. pq->head = pq->head->next;
    14. free(cur);
    15. cur = NULL;
    16. }
    17. pq->size--;
    18. }

     提取数据

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

     判断是否为空

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

    队内元素个数统计 

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

  • 相关阅读:
    助力Java开发者成功,微软是认真的
    zhang-suen算法提取裂缝图骨架
    Django实战项目-学习任务系统-用户注册
    L76.linux命令每日一练 -- 第11章 Linux系统管理命令 -- free和iftop
    AWS安全性身份和合规性之IAM Identity Center(AWS Single Sign-On)
    LeetCode刷题日记003——无重复最长子串
    回归预测 | MATLAB实现基于RF随机森林的用水量预测(多因素、多指标)
    移动应用开发与测试赛题2
    Java项目:JSP家教服务找家教平台网站项目
    React Hook的使用
  • 原文地址:https://blog.csdn.net/weixin_49449676/article/details/126160953