• 数据结构——3道栈和队列OJ题


    目录

    习题1 用队列实现栈

    队列的实现

    通过队列实现栈 

     结构体的建立

     初始化

    压栈 

     出栈

     返回栈顶

     判断是否为空

     销毁空间

     用队列实现栈 

     栈的实现

     结构体创建

     结构体的初始化

     元素入队

     将Push元素倒到Pop中

    返回头元素然后移除

     返回头元素

     判断是否为空

     空间的销毁

    设计循环队列

     结构体的定义

     初始化

    判断是否为空 

    判断是否满了 

     在队列内插入元素

    删除队列内元素 

     返回队首元素

     获得队尾元素

     空间释放


    习题1 用队列实现栈

    225. 用队列实现栈 - 力扣(LeetCode)

    1.把有数据队列的内容,传到没数据的队列中,传一个之后,再原队列中删一个

    2.等q1中剩一个元素的时候,让这个元素出队

    这样就可以达到栈的效果,1,2,3,4,5,让5先出栈,之后再按照同样的方法把q1看作空(压栈的时候要往有元素的队里压),开始倒数据即可 

     

     

    队列的实现

    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;
    13. void QueueInit(Queue* pq);
    14. void QueueDestory(Queue* pq);
    15. void QueuePush(Queue *pq, QDataType x);
    16. void QueuePop(Queue* pq);
    17. QDataType QueueFront(Queue* pq);
    18. QDataType QueueBack(Queue* pq);
    19. bool QueueEmpty(Queue* pq);
    20. int QueueSize(Queue* pq);
    21. void QueueInit(Queue* pq)
    22. {
    23. assert(pq);
    24. pq->head = pq->tail = NULL;
    25. pq->size = 0;
    26. }
    27. void QueueDestory(Queue* pq)
    28. {
    29. assert(pq);
    30. QNode* cur = pq->head;
    31. while (cur)
    32. {
    33. QNode* del = cur;
    34. cur = cur->next;
    35. free(del);
    36. del = NULL;
    37. }
    38. pq->head = pq->tail = NULL;
    39. }
    40. void QueuePush(Queue* pq, QDataType x)
    41. {
    42. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    43. assert(newnode);
    44. newnode->data = x;
    45. newnode->next = NULL;
    46. if (pq->tail == NULL)
    47. {
    48. pq->head = pq->tail = newnode;
    49. }
    50. else
    51. {
    52. pq->tail->next = newnode;
    53. pq->tail = pq->tail->next;
    54. }
    55. pq->size++;
    56. }
    57. void QueuePop(Queue* pq)
    58. {
    59. assert(pq);
    60. assert(!QueueEmpty(pq));
    61. if (pq->head->next == NULL)
    62. {
    63. free(pq->head);
    64. pq->head = pq->tail = NULL;
    65. }//如果只剩一个节点,单独处理,防止tail变为野指针
    66. else
    67. {
    68. QNode* cur = pq->head;
    69. pq->head = pq->head->next;
    70. free(cur);
    71. cur = NULL;
    72. }
    73. pq->size--;
    74. }
    75. QDataType QueueFront(Queue* pq)//取头数据
    76. {
    77. assert(pq);
    78. assert(!QueueEmpty(pq));
    79. return pq->head->data;
    80. }
    81. QDataType QueueBack(Queue* pq)//取尾数据
    82. {
    83. assert(pq);
    84. assert(!QueueEmpty(pq));
    85. return pq->tail->data;
    86. }
    87. bool QueueEmpty(Queue* pq)
    88. {
    89. assert(pq);
    90. return pq->head==NULL && pq->tail==NULL;
    91. }
    92. int QueueSize(Queue* pq)
    93. {
    94. return pq->size;
    95. }

    通过队列实现栈 

     结构体的建立

    1. typedef struct {
    2. Queue q1; //建立俩个
    3. Queue q2;
    4. } MyStack;
    5. //也可用Queue*,但是这样的话要用malloc给q1和q2开辟空间

     初始化

    1. MyStack* myStackCreate() {
    2. MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
    3. QueueInit(&obj->q1);
    4. QueueInit(&obj->q2);
    5. return obj;
    6. }//直接传参即可

    压栈 

    1. void myStackPush(MyStack* obj, int x) {
    2. if(!QueueEmpty(&obj->q1))
    3. {
    4. QueuePush(&obj->q1,x);
    5. }//如果q1不是空,把元素压到q1
    6. else
    7. {
    8. QueuePush(&obj->q2,x);
    9. }
    10. }

     出栈

    1. int myStackPop(MyStack* obj) {
    2. Queue *empty=&obj->q1;//假设q1为空
    3. Queue *noempty=&obj->q2;//假设q2不是空
    4. if(!QueueEmpty(&obj->q1))
    5. {
    6. noempty=&obj->q1;
    7. empty=&obj->q2;
    8. while(QueueSize(noempty)>1) //将有元素的队列的数据,倒到只剩最后一个元素
    9. {
    10. QueuePush(empty,QueueFront(noempty));
    11. QueuePop(noempty);
    12. }
    13. int top=QueueFront(noempty);//该元素就是栈顶
    14. QueuePop(noempty);
    15. return top;//返回栈顶
    16. }

     返回栈顶

    1. int myStackTop(MyStack* obj) {
    2. if(!QueueEmpty(&obj->q1))
    3. {
    4. return QueueBack(&obj->q1);
    5. }
    6. else
    7. {
    8. return QueueBack(&obj->q2);
    9. }
    10. }//直接调用返回队尾的函数即可

     判断是否为空

    1. bool myStackEmpty(MyStack* obj) {
    2. return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
    3. }

     销毁空间

    1. void myStackFree(MyStack* obj) {
    2. QueueDestory(&obj->q1);
    3. QueueDestory(&obj->q2);
    4. free(obj);
    5. }

    这里不能直接free(obj),因为q1和q2是链表,链表的内存不连续,如果释放掉boj,则q1和q2没有释放,会造成内存泄漏

     用队列实现栈 

     232. 用栈实现队列 - 力扣(LeetCode)

     若队列中是1 2 3 4 5,则按照栈的规则,此时出栈顺序应该是 5 4 3 2 1,我们可以用俩个队列来实现栈

    1.把PushST里面的数据倒到PopST

    2.出栈的时候,我们只需要出PopST里面的元素就可以,当有元素要填充时,填充到PushST就行

     栈的实现

    1. typedef int 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. typedef struct {
    2. ST PushST;
    3. ST PopST;
    4. } MyQueue;

     结构体的初始化

    1. MyQueue* myQueueCreate() {
    2. MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    3. StackInit(&obj->PushST);
    4. StackInit(&obj->PopST);
    5. return obj;
    6. }

     元素入队

    1. void myQueuePush(MyQueue* obj, int x) {
    2. StackPush(&obj->PushST,x);
    3. }

     将Push元素倒到Pop中

    1. void PushSTTOPopsT(MyQueue* obj)
    2. {
    3. if(StackEmpty(&obj->PopST))//如果Pop栈内为空,并且Push不为空就给元素
    4. {
    5. while(!StackEmpty(&obj->PushST))//当Push不为空
    6. {
    7. StackPush(&obj->PopST,StackTop(&obj->PushST));
    8. StackPop(&obj->PushST);
    9. }
    10. }
    11. }

    返回头元素然后移除

    1. int myQueuePop(MyQueue* obj) {
    2. PushSTTOPopsT(obj);
    3. int front=StackTop(&obj->PopST);
    4. StackPop(&obj->PopST);
    5. return front;
    6. }

     返回头元素

    1. int myQueuePeek(MyQueue* obj) {
    2. PushSTTOPopsT(obj);
    3. return StackTop(&obj->PopST);
    4. }

     判断是否为空

    1. bool myQueueEmpty(MyQueue* obj) {
    2. return StackEmpty(&obj->PopST)&&StackEmpty(&obj->PushST);
    3. }

     空间的销毁

    1. void myQueueFree(MyQueue* obj) {
    2. StackDestory(&obj->PushST);
    3. StackDestory(&obj->PopST);
    4. free(obj);
    5. }

    设计循环队列

    622. 设计循环队列 - 力扣(LeetCode)

     ​​​​​​​

     

     

     这里采用数组实现(链表有缺点后面会讲到),front指向首元素,back指向最后元素的下一个空间,空间大小为4,多开辟一个空间,即总共开辟五个空间,使得back+1的位置是front

     结构体的定义

    1. typedef struct {
    2. int *a;
    3. int front;
    4. int back;
    5. int N; //用来统计空间的总个数
    6. } MyCircularQueue;

     初始化

    1. MyCircularQueue* myCircularQueueCreate(int k) {
    2. MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    3. obj->a=(int *)malloc(sizeof(int)*(k+1)); //多开辟一个空间
    4. obj->back=obj->front=0;
    5. obj->N=k+1;
    6. return obj;
    7. }

    判断是否为空 

    1. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    2. return obj->back==obj->front;
    3. }//当back==front时,就是空

    判断是否满了 

     元素满了之后back指向红框,back+1,back指向数组外,此时让back%N,back就会回到首元素位置

     

     

    1. bool myCircularQueueIsFull(MyCircularQueue* obj) {
    2. return (obj->back+1)%obj->N==obj->front;
    3. }//当back的下一个位置是front时候是满

     在队列内插入元素

    1. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    2. if (myCircularQueueIsFull(obj))
    3. return false; //如果满了则退出
    4. obj->a[obj->back]=value;
    5. obj->back=(obj->back+1)%obj->N; //插入之后,back要走到下一个位置
    6. return true;
    7. }

     

    删除队列内元素 

    1. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    2. if(myCircularQueueIsEmpty(obj))
    3. return false;
    4. obj->front++;
    5. obj->front=obj->front%obj->N; //跟back一样,要防止越界
    6. return true;
    7. }

     返回队首元素

    1. int myCircularQueueFront(MyCircularQueue* obj) {
    2. if( myCircularQueueIsEmpty(obj))
    3. return -1;
    4. else
    5. return obj->a[obj->front];
    6. } //如果不为空,返回队首元素

     获得队尾元素

    1. int myCircularQueueRear(MyCircularQueue* obj) {
    2. if(myCircularQueueIsEmpty(obj))
    3. return -1;
    4. else
    5. return obj->a[(obj->back-1+obj->N)%obj->N];
    6. }

     

     back的上一个位置就是队尾元素,队back-1即可,但是存在一个问题

     当back位于该位置时,back-1就是-1,此时我们可以(back-1+N)%N,使back回到最后一个位置,不用链表实现该题是因为,当获取back所在元素时,链表需要遍历,而数组可以直接访问

    小练习题:

    5.现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N-1。其队内有效长度为?(假设 队头不存放数据)

    A (rear - front + N) % N + 1

    B (rear - front + N) % N

    C ear - front) % (N + 1)

    D (rear - front + N) % (N - 1)

    选B,

     空间释放

     

    1. void myCircularQueueFree(MyCircularQueue* obj) {
    2. free(obj->a); //先释放数组空间,再释放给结构体创建的空间
    3. free(obj);
    4. }

     

     

  • 相关阅读:
    2022-08-26 第二小组 张明旭 前端学习记录
    Linux - Python安装
    liquibase学习记录
    10.1 调试事件读取寄存器
    自己封装 vue3+ts 组件库并且发布到 NPM
    docker 镜像重启报错问题处理
    JRebel在IDEA中实现热部署 (JRebel实用版)
    学生环境保护绿色家园 WEB静态网页作业模板 大学生环境保护网页代码 dreamweaver网页设计作业制作 dw个人网页作业成品
    QGIS空间分析项目实战
    云计算的两地三中心和灾备介绍
  • 原文地址:https://blog.csdn.net/weixin_49449676/article/details/126183480