EN
/video/65615725.html

栈与队列OJ题精选,数据结构的实践应用

2025-06-24 12:19:34 来源: 新华社
字号:默认 超大 | 打印 |

系列文章目录

🎈 🎈 我的CSDN主页:OTWOL的主页,欢迎!!!👋🏼👋🏼
🎉🎉我的C语言初阶合集:C语言初阶合集,希望能帮到你!!!😍 😍
🔍🔍我的C语言进阶合集:我的C语言进阶合集,期待你的点击!!!🌈🌈
🎉🎉我的数据结构与算法合集:数据结构与算法合集,点进去看看吧!!! 🎊🎊
😍 👋🏼🎉🎊创作不易,欢迎大家留言、点赞加收藏!!! 🥳😁😍

文章目录

  • 系列文章目录
  • 一、有效的括号
    • (1)题目描述
    • (2)代码示例
  • 二、用队列实现栈
    • (1)题目描述
    • (2)代码示例
  • 三、用栈实现队列
    • (1)题目描述
    • (2)代码示例
  • 四、设计循环队列
    • (1)题目描述
    • (2)代码示例
  • END

一、有效的括号

(1)题目描述

下面是该题的链接🔗

有效的括号

(2)代码示例

写一个 顺序栈:

// 定义一个类型别名,将 char 类型重命名为 STDataType,方便后续代码中使用,提高代码可读性和可维护性typedefcharSTDataType;// 定义一个结构体,用于表示栈结构// 其中包含一个指向存储栈元素的数组指针 a,栈顶索引 top,以及栈的容量 capacitytypedefstructStack{ STDataType*a;inttop;intcapacity;}ST;// 初始化栈的函数// 接收一个指向栈结构体的指针 ps,用于对栈进行初始化操作voidSTInit(ST*ps){ // 断言传入的指针不为空,若为空则表示出现了错误情况,因为后续要通过该指针操作栈结构体assert(ps);// 初始设置栈的容量为 4ps->capacity =4;// 初始时 栈顶索引 为 0,表示栈为空ps->top =0;// 动态分配内存来存储栈元素,根据初始容量分配相应大小的内存空间// 将分配的内存地址强转为 STDataType* 类型后赋值给临时指针 tmpSTDataType*tmp =(STDataType*)malloc(ps->capacity *sizeof(STDataType));// 如果内存分配失败(返回的指针为NULL)if(tmp ==NULL){ // 输出错误信息,提示malloc分配内存失败perror("malloc fail");// 直接返回,不再进行后续初始化操作return;}// 将成功分配内存的地址赋值给栈结构体中的数组指针 a,使得栈可以使用这块内存来存储元素ps->a =tmp;}// 销毁栈的函数,用于释放栈所占用的内存资源等清理工作voidSTDestroy(ST*ps){ // 断言传入的指针不为空,确保操作的合法性assert(ps);// 释放栈中存储元素的数组所占用的内存空间free(ps->a);// 将栈结构体中的数组指针 a 置为 NULL,防止出现野指针情况ps->a =NULL;// 将 栈顶索引 和 容量 都重置为 0,恢复到初始的 “空” 状态表示ps->top =ps->capacity =0;}// 向栈中压入元素的函数// 接收一个指向栈结构体的指针 ps 以及要压入的元素 x(类型为 STDataType)voidSTPush(ST*ps,STDataType x){ // 断言传入的指针不为空,保证后续操作能正常进行assert(ps);// 检查栈是否已满(即当前元素个数等于栈的容量),如果已满则需要进行扩容操作if(ps->capacity ==ps->top){ // 使用 realloc 对栈的存储空间进行扩容,扩容为原来的 2 倍大小// 将重新分配后的内存地址强转为STDataType*类型后赋值给临时指针 tmpSTDataType*tmp =(STDataType*)realloc(ps->a,ps->capacity *2*sizeof(STDataType));// 如果扩容失败(返回的指针为 NULL)if(tmp ==NULL){ // 输出错误信息,提示 realloc 扩容失败perror("realloc fail");// 直接返回,不进行元素压入操作了return;}// 将扩容后成功分配的内存地址赋值给栈结构体中的数组指针 a,更新栈的存储空间ps->a =tmp;// 将栈的容量更新为原来的 2 倍ps->capacity *=2;}// 将元素 x 存放到栈顶位置,然后栈顶索引 top 自增 1,指向下一个空闲位置ps->a[ps->top++]=x;}// 判断栈是否为空的函数// 接收一个指向栈结构体的指针 psbool STEmpty(ST*ps){ // 断言传入的指针不为空,确保操作的合法性assert(ps);// 通过判断 栈顶索引 是否为 0 来确定栈是否为空,返回相应的布尔值return(ps->top ==0);}// 获取栈中元素个数的函数// 接收一个指向栈结构体的指针 psintSTSize(ST*ps){ // 断言传入的指针不为空,确保操作的合法性assert(ps);// 直接返回 栈顶索引 的值,因为 栈顶索引 的值就代表了当前栈中元素的个数return(ps->top);}// 弹出栈顶元素的函数(只是将 栈顶索引 减 1,逻辑上表示栈顶元素被移除了)// 接收一个指向栈结构体的指针 psvoidSTPop(ST*ps){ // 断言传入的指针不为空,保证操作的合法性assert(ps);// 断言栈不能为空,若为空则不能进行弹出操作,否则会出现错误情况assert(!STEmpty(ps));// 将 栈顶索引 减 1,实现逻辑上的弹出栈顶元素操作--ps->top;}// 获取栈顶元素的函数(但不会弹出栈顶元素)// 接收一个指向栈结构体的指针 psSTDataType STTop(ST*ps){ // 断言传入的指针不为空,保证操作的合法性assert(ps);// 断言栈不能为空,若为空则没有栈顶元素可供获取,会出现错误情况assert(!STEmpty(ps));// 返回栈顶元素的值(通过 栈顶索引 减 1 的索引来获取,因为数组下标从 0 开始)return(ps->a[ps->top -1]);}

判断有效括号

// 判断给定的括号字符串s是否有效(左右括号匹配)的函数bool isValid(char*s){ // 创建一个栈结构体实例 stST st;// 初始化栈stSTInit(&st);// 遍历字符串s,直到遇到字符串结束符'\0'while(*s){ // 如果当前字符是左括号('(' 或 '[' 或 '{ ')if(*s =='('||*s =='['||*s =='{ '){ // 将该左括号压入栈st中STPush(&st,*s);}else{ // 如果栈为空,说明没有与之匹配的左括号了,括号字符串无效if(STEmpty(&st)){ // 销毁栈,释放资源STDestroy(&st);returnfalse;}// 如果栈不为空,说明有对应的左括号else{ // 获取栈顶元素STDataType top =STTop(&st);// 弹出栈顶元素(因为已经获取到了,并且后续要检查匹配情况,所以可以弹出)STPop(&st);// 检查当前右括号与获取到的栈顶左括号是否匹配,如果不匹配则括号字符串无效if(*s ==')'&&top!='('||*s ==']'&&top!='['||*s =='}'&&top!='{ '){ // 销毁栈,释放资源STDestroy(&st);returnfalse;}}}// 移动指针到下一个字符继续检查++s;}// 遍历完字符串后,检查栈是否为空,如果为空则说明所有括号都匹配,返回true,否则返回falsebool ret =STEmpty(&st);// 销毁栈,释放资源STDestroy(&st);returnret;}

二、用队列实现栈

(1)题目描述

下面是该题的链接🔗

用队列实现栈

(2)代码示例

写一个 链式队列:

// 定义一个类型别名,将 int 类型重命名为 QDataType,方便后续代码中使用,增强代码可读性和可维护性typedefintQDataType;// 定义结构体 QNode,表示队列中的节点// 其中包含一个数据域 data,用于存储节点的数据(类型为 QDataType,即int)// 以及一个指针域 next,用于指向下一个节点,从而构成链式结构typedefstructQNode{ QDataType data;structQNode*next;}QNode;// 定义结构体 Queue,用于表示队列// 包含指向队头节点的指针 head、指向队尾节点的指针 tail,以及记录队列中元素个数的 sizetypedefstructQueue{ QNode*head;QNode*tail;intsize;}Queue;// 初始化队列的函数// 接收一个指向 Queue 结构体的指针 q,用于对队列进行初始化操作voidQInit(Queue*q){ // 断言传入的指针不为空,若为空则表示出现了错误情况,因为后续要通过该指针操作队列结构体assert(q);// 初始化时,队头和队尾指针都设为 NULL,表示队列为空q->head =q->tail =NULL;// 队列中元素个数初始化为 0q->size =0;}// 销毁队列的函数,用于释放队列及其节点所占用的内存资源等清理工作voidQDestroy(Queue*q){ // 断言传入的指针不为空,确保操作的合法性assert(q);// 从队头开始遍历队列的每个节点QNode*cur =q->head;while(cur){ // 保存当前节点的下一个节点指针,方便后续释放当前节点内存后能继续遍历下一个节点QNode*next =cur->next;// 释放当前节点所占用的内存空间free(cur);// 将指针更新为下一个节点的指针,继续循环释放下一个节点内存cur =next;}// 释放完所有节点后,将队头和队尾指针都置为 NULL,表示队列已被销毁q->head =q->tail =NULL;// 队列元素个数也重置为 0q->size =0;}// 判断队列是否为空的函数// 接收一个指向 Queue 结构体的指针 qbool QEmpty(Queue*q){ // 断言传入的指针不为空,确保操作的合法性assert(q);// 通过判断队列元素个数是否为 0 来确定队列是否为空,返回相应的布尔值return(q->size ==0);}// 获取队列中元素个数的函数// 接收一个指向 Queue 结构体的指针 qintQSize(Queue*q){ // 断言传入的指针不为空,确保操作的合法性assert(q);// 直接返回队列中元素个数 size 的值return(q->size);}// 向队列中插入元素的函数(队尾插入操作)// 接收一个指向 Queue 结构体的指针 q 以及要插入的元素 x(类型为 QDataType,即 int)voidQPush(Queue*q,QDataType x){ // 断言传入的指针不为空,保证后续操作能正常进行assert(q);// 申请一个新的队列节点空间QNode*newnode =(QNode*)malloc(sizeof(QNode));// 如果内存分配失败(返回的指针为 NULL)if(newnode ==NULL){ // 输出错误信息,提示 malloc 分配内存失败perror("malloc fail");// 直接返回,不再进行元素插入操作return;}// 给新节点的数据域赋值为要插入的元素 xnewnode->data =x;// 新节点的 next 指针初始化为 NULL,因为它目前是队尾节点,后面没有其他节点newnode->next =NULL;// 如果队列当前为空(队头指针为 NULL)if(q->head ==NULL){ // 断言队尾指针也必然为 NULL,确保队列状态的一致性assert(q->tail ==NULL);// 将队头和队尾指针都指向新创建的节点,因为此时队列中只有这一个节点q->head =q->tail =newnode;}else{ // 将当前队尾节点的 next 指针指向新节点,即将新节点连接到队列末尾q->tail->next =newnode;// 更新队尾指针为新插入的节点,使其始终指向队尾q->tail =q->tail->next;}// 队列元素个数自增 1,表示插入了一个新元素++q->size;}// 从队列中弹出元素的函数(队头删除操作)// 接收一个指向 Queue 结构体的指针 qvoidQPop(Queue*q){ // 断言传入的指针不为空,保证操作的合法性assert(q);// 断言队列不能为空,若为空则不能进行弹出操作,否则会出现错误情况assert(!QEmpty(q));// 进行队头删除操作// 如果队列中只有一个元素(元素个数为 1)if(q->size ==1){ // 释放队头节点所占用的内存空间free(q->head);// 将队头和队尾指针都置为 NULL,因为此时队列已为空q->head =q->tail =NULL;}else{ // 保存队头节点的下一个节点指针,方便后续更新队头指针QNode*next =q->head->next;// 释放当前队头节点所占用的内存空间free(q->head);// 更新队头指针为之前保存的下一个节点指针,实现队头节点的删除q->head =next;}// 队列元素个数自减 1,表示弹出了一个元素--q->size;}// 获取队列队头元素的函数// 接收一个指向 Queue 结构体的指针 qQDataType QFront(Queue*q){ // 断言传入的指针不为空,保证操作的合法性assert(q);// 断言队列不能为空,若为空则没有队头元素可供获取,会出现错误情况assert(!QEmpty(q));// 返回队头节点的数据域的值,即获取队头元素return(q->head->data);}// 获取队列队尾元素的函数(但不会删除队尾元素)// 接收一个指向 Queue 结构体的指针 qQDataType QBack(Queue*q){ // 断言传入的指针不为空,保证操作的合法性assert(q);// 断言队列不能为空,若为空则没有队尾元素可供获取,会出现错误情况assert(!QEmpty(q));// 返回队尾节点的数据域的值,即获取队尾元素return(q->tail->data);}

用队列实现栈

// 定义一个结构体 MyStack,它内部包含两个 Queue 类型的成员 q1 和 q2// 这里是通过组合两个队列来模拟实现栈的功能typedefstruct{ Queue q1;Queue q2;}MyStack;// 创建一个 MyStack 结构体实例的函数,并进行初始化操作// 返回指向新创建的 MyStack 结构体的指针MyStack*myStackCreate(){ // 动态分配内存来存储一个 MyStack 结构体大小的空间MyStack*obj =(MyStack*)malloc(sizeof(MyStack));// 如果内存分配失败(返回的指针为 NULL)if(obj ==NULL){ // 输出错误信息,提示 malloc 分配内存失败perror("malloc fail");// 返回 NULL,表示创建失败returnNULL;}// 初始化 MyStack 结构体中的 q1 队列QInit(&(obj->q1));// 初始化 MyStack 结构体中的 q2 队列QInit(&(obj->q2));// 返回指向初始化好的 MyStack 结构体的指针returnobj;}// 向模拟栈( MyStack 结构体表示)中压入元素的函数// 参数 obj 是指向 MyStack 结构体的指针,x 是要压入的元素(int 类型)voidmyStackPush(MyStack*obj,intx){ // 如果 q1 队列不为空if(!QEmpty(&(obj->q1))){ // 将元素 x 压入q1队列QPush(&(obj->q1),x);}else{ // 否则将元素 x 压入 q2 队列QPush(&(obj->q2),x);}}// 从模拟栈( MyStack 结构体表示)中弹出元素的函数// 参数 obj 是指向 MyStack 结构体的指针,返回弹出的栈顶元素( int 类型)intmyStackPop(MyStack*obj){ // 先假设 q1 队列为空队列,q2 队列为非空队列(后续会根据实际情况调整)Queue*emptyq =&(obj->q1);Queue*noemptyq =&(obj->q2);// 如果实际情况是 q1 队列不为空if(!QEmpty(&(obj->q1))){ // 则交换假设,让 q2 队列为空队列,q1 队列为非空队列emptyq =&(obj->q2);noemptyq =&(obj->q1);}// 将非空队列(除了最后一个元素外)中的元素依次转移到空队列中while(QSize(noemptyq)>1){ // 取出 非空队列 的队头元素,并将其压入 空队列QPush(emptyq,QFront(noemptyq));// 弹出非空队列的队头元素(完成转移操作)QPop(noemptyq);}// 获取非空队列此时剩下的最后一个元素(即 栈顶 元素)inttop =QFront(noemptyq);// 弹出这个最后元素,完成 出栈 操作QPop(noemptyq);// 返回弹出的 栈顶元素returntop;}// 获取模拟栈( MyStack 结构体表示)的栈顶元素的函数(但不弹出元素)// 参数 obj 是指向 MyStack 结构体的指针,返回栈顶元素( int 类型)intmyStackTop(MyStack*obj){ // 如果 q1 队列不为空if(!QEmpty(&(obj->q1))){ // 返回 q1 队列的队尾元素作为栈顶元素(因为模拟栈的栈顶元素相当于非空队列的队尾元素)returnQBack(&(obj->q1));}else{ // 否则返回 q2 队列的队尾元素作为栈顶元素returnQBack(&(obj->q2));}}// 判断模拟栈( MyStack 结构体表示)是否为空的函数// 参数 obj 是指向 MyStack 结构体的指针,返回布尔值表示栈是否为空bool myStackEmpty(MyStack*obj){ // 当 q1 队列和 q2 队列都为空时,模拟栈为空,返回 true,否则返回falsereturnQEmpty(&(obj->q1))&&QEmpty(&(obj->q2));}// 释放模拟栈( MyStack 结构体表示)所占用的内存资源的函数// 参数 obj 是指向 MyStack 结构体的指针voidmyStackFree(MyStack*obj){ // 先销毁 MyStack 结构体中的 q1 队列,释放其占用的内存QDestroy(&(obj->q1));// 再销毁 MyStack 结构体中的 q2 队列,释放其占用的内存QDestroy(&(obj->q2));// 释放 MyStack 结构体本身所占用的内存空间free(obj);}

三、用栈实现队列

(1)题目描述

下面是该题的链接🔗

用栈实现队列

(2)代码示例

写一个 顺序栈:

// 定义一个类型别名,将 char 类型重命名为 STDataType,方便后续代码中使用,提高代码可读性和可维护性typedefcharSTDataType;// 定义一个结构体,用于表示栈结构// 其中包含一个指向存储栈元素的数组指针 a,栈顶索引 top,以及栈的容量 capacitytypedefstructStack{ STDataType*a;inttop;intcapacity;}ST;// 初始化栈的函数// 接收一个指向栈结构体的指针 ps,用于对栈进行初始化操作voidSTInit(ST*ps){ // 断言传入的指针不为空,若为空则表示出现了错误情况,因为后续要通过该指针操作栈结构体assert(ps);// 初始设置栈的容量为 4ps->capacity =4;// 初始时 栈顶索引 为 0,表示栈为空ps->top =0;// 动态分配内存来存储栈元素,根据初始容量分配相应大小的内存空间// 将分配的内存地址强转为 STDataType* 类型后赋值给临时指针 tmpSTDataType*tmp =(STDataType*)malloc(ps->capacity *sizeof(STDataType));// 如果内存分配失败(返回的指针为NULL)if(tmp ==NULL){ // 输出错误信息,提示malloc分配内存失败perror("malloc fail");// 直接返回,不再进行后续初始化操作return;}// 将成功分配内存的地址赋值给栈结构体中的数组指针 a,使得栈可以使用这块内存来存储元素ps->a =tmp;}// 销毁栈的函数,用于释放栈所占用的内存资源等清理工作voidSTDestroy(ST*ps){ // 断言传入的指针不为空,确保操作的合法性assert(ps);// 释放栈中存储元素的数组所占用的内存空间free(ps->a);// 将栈结构体中的数组指针 a 置为 NULL,防止出现野指针情况ps->a =NULL;// 将 栈顶索引 和 容量 都重置为 0,恢复到初始的 “空” 状态表示ps->top =ps->capacity =0;}// 向栈中压入元素的函数// 接收一个指向栈结构体的指针 ps 以及要压入的元素 x(类型为 STDataType)voidSTPush(ST*ps,STDataType x){ // 断言传入的指针不为空,保证后续操作能正常进行assert(ps);// 检查栈是否已满(即当前元素个数等于栈的容量),如果已满则需要进行扩容操作if(ps->capacity ==ps->top){ // 使用 realloc 对栈的存储空间进行扩容,扩容为原来的 2 倍大小// 将重新分配后的内存地址强转为STDataType*类型后赋值给临时指针 tmpSTDataType*tmp =(STDataType*)realloc(ps->a,ps->capacity *2*sizeof(STDataType));// 如果扩容失败(返回的指针为 NULL)if(tmp ==NULL){ // 输出错误信息,提示 realloc 扩容失败perror("realloc fail");// 直接返回,不进行元素压入操作了return;}// 将扩容后成功分配的内存地址赋值给栈结构体中的数组指针 a,更新栈的存储空间ps->a =tmp;// 将栈的容量更新为原来的 2 倍ps->capacity *=2;}// 将元素 x 存放到栈顶位置,然后栈顶索引 top 自增 1,指向下一个空闲位置ps->a[ps->top++]=x;}// 判断栈是否为空的函数// 接收一个指向栈结构体的指针 psbool STEmpty(ST*ps){ // 断言传入的指针不为空,确保操作的合法性assert(ps);// 通过判断 栈顶索引 是否为 0 来确定栈是否为空,返回相应的布尔值return(ps->top ==0);}// 获取栈中元素个数的函数// 接收一个指向栈结构体的指针 psintSTSize(ST*ps){ // 断言传入的指针不为空,确保操作的合法性assert(ps);// 直接返回 栈顶索引 的值,因为 栈顶索引 的值就代表了当前栈中元素的个数return(ps->top);}// 弹出栈顶元素的函数(只是将 栈顶索引 减 1,逻辑上表示栈顶元素被移除了)// 接收一个指向栈结构体的指针 psvoidSTPop(ST*ps){ // 断言传入的指针不为空,保证操作的合法性assert(ps);// 断言栈不能为空,若为空则不能进行弹出操作,否则会出现错误情况assert(!STEmpty(ps));// 将 栈顶索引 减 1,实现逻辑上的弹出栈顶元素操作--ps->top;}// 获取栈顶元素的函数(但不会弹出栈顶元素)// 接收一个指向栈结构体的指针 psSTDataType STTop(ST*ps){ // 断言传入的指针不为空,保证操作的合法性assert(ps);// 断言栈不能为空,若为空则没有栈顶元素可供获取,会出现错误情况assert(!STEmpty(ps));// 返回栈顶元素的值(通过 栈顶索引 减 1 的索引来获取,因为数组下标从 0 开始)return(ps->a[ps->top -1]);}

用栈实现队列:

// 定义一个结构体 MyQueue,它内部包含两个 ST 类型的结构体成员 pushst 和 popst// 这里通过两个栈来模拟实现队列的功能typedefstruct{ ST pushst;ST popst;}MyQueue;// 创建一个 MyQueue 结构体实例的函数,并进行初始化操作// 返回指向新创建的 MyQueue 结构体的指针MyQueue*myQueueCreate(){ // 动态分配内存来存储一个 MyQueue 结构体大小的空间MyQueue*obj =(MyQueue*)malloc(sizeof(MyQueue));// 如果内存分配失败(返回的指针为 NULL)if(obj ==NULL){ // 输出错误信息,提示 malloc 分配内存失败perror("malloc fail");// 返回 NULL,表示创建失败returnNULL;}// 初始化 MyQueue 结构体中的 pushst 栈STInit(&(obj->pushst));// 初始化 MyQueue 结构体中的 popst 栈STInit(&(obj->popst));// 返回指向初始化好的 MyQueue 结构体的指针returnobj;}// 向模拟队列( MyQueue 结构体表示)中插入元素的函数// 参数 obj 是指向 MyQueue 结构体的指针,x 是要插入的元素( int 类型)voidmyQueuePush(MyQueue*obj,intx){ // 调用栈的入栈函数,将元素 x 压入 pushst 栈,模拟队列的入队操作STPush(&(obj->pushst),x);}// 获取模拟队列( MyQueue 结构体表示)队头元素的函数// 参数 obj 是指向 MyQueue 结构体的指针,返回队头元素( int 类型)intmyQueuePeek(MyQueue*obj){ // 如果 popst 栈为空if(STEmpty(&(obj->popst))){ // 当 pushst 栈不为空时,将 pushst 栈中的元素依次弹出并压入popst 栈while(!STEmpty(&(obj->pushst))){ // 取出 pushst 栈的栈顶元素STDataType top =STTop(&(obj->pushst));// 将该元素压入 popst 栈STPush(&(obj->popst),top);// 弹出 pushst 栈的栈顶元素STPop(&(obj->pushst));}}// 获取 popst 栈的栈顶元素,即为模拟队列的队头元素intfront =STTop(&(obj->popst));// 返回队头元素returnfront;}// 从模拟队列( MyQueue 结构体表示)中删除队头元素的函数// 参数 obj 是指向 MyQueue 结构体的指针,返回被删除的队头元素( int 类型)intmyQueuePop(MyQueue*obj){ // 先调用 myQueuePeek 函数获取队头元素(同时也会在 popst 栈为空时进行元素转移操作)intfront =myQueuePeek(obj);// 弹出 popst 栈的栈顶元素,模拟队列的出队操作STPop(&(obj->popst));// 返回被删除的队头元素returnfront;}// 判断模拟队列(MyQueue结构体表示)是否为空的函数// 参数 obj 是指向 MyQueue 结构体的指针,返回布尔值表示队列是否为空bool myQueueEmpty(MyQueue*obj){ // 当 pushst 栈和 popst 栈都为空时,模拟队列为空,返回 true,否则返回 falsereturnSTEmpty(&(obj->pushst))&&STEmpty(&(obj->popst));}// 释放模拟队列( MyQueue 结构体表示)所占用的内存资源的函数// 参数 obj 是指向 MyQueue 结构体的指针voidmyQueueFree(MyQueue*obj){ // 销毁 MyQueue 结构体中的 pushst 栈,释放其占用的内存STDestroy(&(obj->pushst));// 销毁 MyQueue 结构体中的 popst 栈,释放其占用的内存STDestroy(&(obj->popst));// 释放 MyQueue 结构体本身所占用的内存空间free(obj);}

四、设计循环队列

(1)题目描述

下面是该题的链接🔗

设计循环队列

(2)代码示例

// 定义一个循环队列的结构体typedefstruct{ intk;// 队列的容量(最大元素个数)int*a;// 指向队列数组的指针inthead;// 队列的头部索引inttail;// 队列的尾部索引}MyCircularQueue;// 创建一个循环队列的函数MyCircularQueue*myCircularQueueCreate(intk){ // 分配内存空间给队列结构体MyCircularQueue*obj =(MyCircularQueue*)malloc(sizeof(MyCircularQueue));if(obj ==NULL){ perror("malloc fail");// 如果分配失败,输出错误信息returnNULL;}// 分配内存空间给队列数组,容量为 k+1(多一个空位用于区分空和满)int*tmp =(int*)malloc((k+1)*sizeof(int));if(tmp ==NULL){ perror("malloc fail");// 如果分配失败,输出错误信息returnNULL;}obj->a =tmp;// 将数组指针赋值给结构体的a成员obj->k =k;// 设置队列的容量obj->head =obj->tail =0;// 初始化头尾索引为 0returnobj;// 返回创建的队列对象}// 判断队列是否为空的函数bool myCircularQueueIsEmpty(MyCircularQueue*obj){ return(obj->head ==obj->tail);// 如果头尾索引相同,则队列为空}// 判断队列是否已满的函数bool myCircularQueueIsFull(MyCircularQueue*obj){ // 如果尾部索引加1后模(k+1)等于头部索引,则队列已满return((obj->tail +1)%(obj->k +1)==obj->head);}// 向队列中插入元素的函数bool myCircularQueueEnQueue(MyCircularQueue*obj,intvalue){ if(myCircularQueueIsFull(obj))// 如果队列已满returnfalse;else{ obj->a[obj->tail++]=value;// 将元素插入尾部,并将尾部索引加 1obj->tail %=(obj->k +1);// 尾部索引模(k+1)以循环returntrue;}}// 从队列中删除元素的函数bool myCircularQueueDeQueue(MyCircularQueue*obj){ if(myCircularQueueIsEmpty(obj))// 如果队列为空returnfalse;else{ ++obj->head;// 将头部索引加 1obj->head %=(obj->k +1);// 头部索引模(k+1)以循环returntrue;}}// 获取队列头部元素的函数intmyCircularQueueFront(MyCircularQueue*obj){ if(myCircularQueueIsEmpty(obj))// 如果队列为空return-1;returnobj->a[obj->head];// 返回头部元素}// 获取队列尾部元素的函数intmyCircularQueueRear(MyCircularQueue*obj){ if(myCircularQueueIsEmpty(obj))// 如果队列为空return-1;else{ // 计算尾部元素的索引,考虑循环的情况return(obj->a[(obj->tail-1+obj->k +1)%(obj->k +1)]);}}// 释放队列内存的函数voidmyCircularQueueFree(MyCircularQueue*obj){ free(obj->a);// 释放队列数组的内存free(obj);// 释放队列结构体的内存    }

END

每天都在学习的路上!
On The Way Of Learning

【我要纠错】责任编辑:新华社