目录
一、栈
1.1 概念
栈:是一种特殊的线性表,它只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的元素需要满足先入先出的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈,出数据也在栈顶。
我们可以通过下图来理解:
1.2 栈的实现
在栈的操作中,我们着重去说明栈的底层结构选择和初始化操作,其余的操作由于与之前的顺序表操作有诸多相似故不再赘述。
1.2.1 选用什么形式?数组or链表?
对于栈来说,我们可以通过两种方式来实现:数组或者是链表。
用数组来实现栈的底层,数组的结构决定了他在尾插,尾删操作上的优势,相对简单。
我们在实现之前的单链表的时候,就发现了单链表的尾插,尾删需要首先去找尾,成本比较高,而栈的特点是先入后出,在栈顶进行插入和删除操作,如果使用单链表让单链表的头结点作为栈底,尾结点作为栈顶,在入栈和出栈操作时,需要先去找尾,相对繁琐。
针对单链表的特点,头插和头删操作比较容易,因此我们可以把头看做栈顶,在头节点之前进行插入和删除操作,把尾看做栈底。
在本文章中,选择使用数组来实现栈。
1.2.2 有关操作预览
void STInit(ST* ps); //堆栈初始化
void STDestroy(ST* ps); //销毁栈
void STPush(ST* ps, STDataType x); //入栈
void STPop(ST* ps); //出栈
int STsize(ST* ps); //返回栈中元素个数
bool STEmpty(ST* ps); //判断栈是否为空
STDataType STTop(ST* ps); //返回栈顶元素
1.2.3 栈的定义
我们要实现栈这一结构,需要有一个数组来存储数据,栈是要求在栈顶进行插入和删除操作,所以需要一个top来记录栈顶的位置,我们是动态创建的数组,所以还需要一个变量记录容量。
根据以上特点,使用某一种已有的数据类型无法描述出栈这一结构,所以我们要定义一个结构体来描述栈。
typedef int STDataType; //方便我们存储其他类型的数据
#define N 4
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
1.2.4 初始化操作
对于栈的初始化,我们尤其需要注意top的值,top可以取0或者-1。
如果top初始化为0,表示的是栈顶元素的下一个位置,即要插入数据的位置。
如果top初始化为-1,表示的是栈顶元素的位置。
在这里我们选取top为0。
//初始化函数
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType)*N);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->top = 0;
ps->capacity = N;
}
1.2.5 完整代码
Stack.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
#define N 4
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* ps);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
int STsize(ST* ps);
bool STEmpty(ST* ps);
STDataType STTop(ST* ps);
Stack.c文件
#include "Stack.h"
//初始化函数
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType)*N);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->top = 0;
ps->capacity = N;
}
//销毁
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
//求栈中的元素
int STsize(ST* ps)
{
assert(ps);
return ps->top;
}
//入栈
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (STsize(ps) == ps->capacity)
{
STDataType* p = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
if (p == NULL)
{
perror("realloc fail");
return;
}
ps->a = p;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
//判断栈是否为空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//出栈
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
//取出栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top - 1];
}
Test.c文件
#include "Stack.h"
void Test1()
{
ST ps;
STInit(&ps);
STPush(&ps, 1);
int x = STTop(&ps);
printf("%d\n", x);
STPush(&ps, 4);
x = STTop(&ps);
printf("%d\n", x);
STPush(&ps, 8);
x = STTop(&ps);
printf("%d\n", x);
STPush(&ps, 5);
x = STTop(&ps);
printf("%d\n", x);
STPush(&ps, 7);
x = STTop(&ps);
printf("%d\n", x);
STPop(&ps);
x = STTop(&ps);
printf("%d\n", x);
STDestroy(&ps);
}
int main()
{
Test1();
return 0;
}
1.3 栈相关oj题 - 有效的括号
1.3.1 题目描述
1.3.2 思路
字符串 "()"、"()[]{}" 和 "{[]}" 都是有效的,而 "(]" 和 "([)]" 不是有效的。可以使用栈来解决这个问题,遇到左括号就入栈,遇到右括号就出栈并判断是否匹配。如果栈为空或者左右括号不匹配,则字符串无效。最后,如果栈为空,则字符串有效。
对于括号匹配问题,每个左括号都与相对应的右括号匹配才能返回true,我们可以想到以下步骤:
- 如果是左括号,则入栈。
- 如果是右括号,则出栈顶元素,看是否可以与右括号匹配成功。
注意我们需要对以下两种情况进行单独处理:
- 字符串中的每个字符都是左括号,此时需要在循环结束之后,对栈进行判空操作,如果栈不为空,则返回false。
- 字符串中的每个字符都是右括号,在循环中直接判断,如果栈为空,直接返回false。
1.3.3代码
typedef char STDataType;
#define N 4
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* ps);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
int STsize(ST* ps);
bool STEmpty(ST* ps);
STDataType STTop(ST* ps);
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType)* N);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->top = 0; //栈顶元素的下一个
//ps->tio=-1; //栈顶元素
ps->capacity = N;
}
//销毁函数
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
//求栈中元素的数量
int STsize(ST* ps)
{
assert(ps);
return ps->top;
}
//入栈
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDataType* p = (STDataType*)realloc(ps->a, sizeof(STDataType) * (ps->capacity) * 2);
if (p == NULL)
{
perror("realloc fail");
return;
}
ps->a = p;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
//判空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//出栈
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
//出栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top - 1];
}
bool isValid(char * s){
ST st;
STInit(&st);
while(*s)
{
if(*s=='('||*s == '['||*s=='{')
{
STPush(&st,*s);
}
else if(*s==')'||*s == ']'||*s=='}')
{
if(STEmpty(&st))
{
STDestroy(&st);
return false;
}
else
{
char p = STTop(&st);
STPop(&st);
if((p=='('&&*s!=')')||
(p=='['&&*s!=']')||
(p=='{'&&*s!='}'))
{
STDestroy(&st);
return false;
}
}
}
s++;
}
bool ret = STEmpty(&st);
STDestroy(&st);
return ret;
}
二、队列
2.1 概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据的特殊线性表,队列具有先进先出的特点。
进行插入操作的一端叫做队尾。
进行删除操作的一端叫做队头。
2.2 队列的实现
在本文章中主要对出栈操作进行文字说明,其余操作不再赘述具体实现。
2.2.1 选用什么形式?数组or链表?
队列的特点是在队尾插入数据,在队头删除数据,如果我们采用数组的形式,在队头删除数据时,需要挪动后面的一系列数据,效率较低,所以在本文章中我们采用链表的形式。
若采用链式结构:
2.2.2 队列的结构定义
由于队列在队尾插入,在队头删除的特点,其次我们这里的队列底层使用链表,所以我们在这里定义两个结构体类型,一个结构体来表示队列的整体结构,一个用来描述局部结构即队列中的每个元素的结构。
typedef int QDatatype;
typedef struct QueueNode
{
struct QueueNode* next;
QDatatype data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
2.2.3 队列的操作列表
void QueueInit(Queue* pq); //初始化
void QueueDestroy(Queue* pq); //销毁
void QueuePush(Queue* pq,QDatatype x); //入队列
void QueuePop(Queue* pq); //出队列
int QueueSize(Queue* pq); //返回队列中的元素个数
bool QueueEmpty(Queue* pq); //判空
QDatatype QueueFront(Queue* pq); //返回队头元素
QDatatype QueueBack(Queue* pq); ///返回队尾元素
2.2.4 出队操作
当队列中元素大于一个时,我们只需要改变队头的指针。
对于出队操作,我们需要注意的是当队列中只有一个元素的时候,这时我们还需要更改尾指针的值,需要进行单独处理。
//出队列
void QueuePop(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
if (pq->head == pq->tail)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
2.2.5 完整代码
Queue.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDatatype;
typedef struct QueueNode
{
struct QueueNode* next;
QDatatype data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq,QDatatype x);
void QueuePop(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
Queue.c文件
#include "Queue.h"
//初始化函数
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
//销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
//入队列
void QueuePush(Queue* pq, QDatatype x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
assert(pq->tail == NULL);
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
//判断是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
}
//出队列
void QueuePop(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
if (pq->head == pq->tail)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
//求队列的元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//返回队首元素
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->head->data;
}
//返回队尾元素
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->tail->data;
}
Test.c文件
#include "Queue.h"
void Test1()
{
Queue pq;
QueueInit(&pq);
QueuePush(&pq,1);
QDatatype x = QueueFront(&pq);
printf("%d\n", x);
QueuePush(&pq, 2);
x = QueueFront(&pq);
printf("%d\n", x);
QueuePush(&pq, 3);
x = QueueBack(&pq);
printf("%d\n", x);
QueuePush(&pq, 4);
x = QueueBack(&pq);
printf("%d\n", x);
QueuePush(&pq, 7);
x = QueueBack(&pq);
printf("%d\n", x);
QueuePop(&pq);
x = QueueFront(&pq);
printf("%d\n", x);
QueuePop(&pq);
x = QueueFront(&pq);
printf("%d\n", x);
QueuePop(&pq);
x = QueueFront(&pq);
printf("%d\n", x);
QueueDestroy(&pq);
}
int main()
{
Test1();
return 0;
}
三、循环队列
3.1 概念
循环队列是一种特殊的队列,它可以充分利用数组空间,实现队列的循环利用。其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
3.2 循环队列的实现
3.2.1 数组or链表
对于实现循环队列,我们可以有以下两种方式实现,但不论是哪一种方式,都需要一个front值来表示头(队首)的位置,一个rear值表示要插入数据的位置,即最后一个节点的下一个位置,这样就存在一个问题:当队列为空和队列满时他们的的条件都是front==rear。
对于上述情况有两种解决方式:
- 增加一个size变量来记录队列中元素的个数。
- 多开一个位置,即有一个位置不存储数据,用来区分,如果多开一个位置,当队列空的时候,front==rear,当队列满时,rear的下一个位置是front。
注意上述使用数组来实现循环队列时,画的是他的物理结构,他的逻辑结构如下:
在这里如果使用链表来实现,在进行取尾操作时,还需要再次进行遍历,或者记录尾前面一个节点的位置,相对繁琐,所以我们在下面的文章中,提供了使用数组来实现循环链表的代码。
3.2.2 操作预览
MyCircularQueue(k): 设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
3.2.3 注意
用数组去实现循环队列,我们需要注意当front或者rear在数组最后一个下标时的情况,由于是循环链表,空间重复利用,当走到数组的最后一个元素时,他的下一个取值即是数组的一个元素的下标位置,所以我们这里使用%操作达到想要的结果。
3.3 循环队列的完整代
typedef struct {
int* a;
int rear;
int front;
int k;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
obj->a = (int*)malloc(sizeof(int) * (k + 1));
obj->front = obj->rear = 0;
obj->k=k;
return obj;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
assert(obj);
return (obj->rear + 1)%(obj->k+1) == obj->front;
}
//向循环队列插入一个元素。如果成功插入则返回真。
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
assert(obj);
if(myCircularQueueIsFull(obj))
{
return false;
}
obj->a[obj->rear] = value;
obj->rear= (obj->rear + 1) % (obj->k + 1);
return true;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
assert(obj);
return obj->front == obj->rear;
}
//从循环队列中删除一个元素。如果成功删除则返回真。
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
assert(obj);
if(myCircularQueueIsEmpty(obj))
{
return false;
}
obj->front++;
obj->front %= (obj->k+1);
return true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
if (myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->a[obj->front];
}
int myCircularQueueRear(MyCircularQueue* obj) {
if (myCircularQueueIsEmpty(obj))
{
return -1;
}
return obj->a[(obj->rear+obj->k)%(obj->k+1)];
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a);
obj->a = NULL;
free(obj);
obj = NULL;
}
四、相关oj题 - 用队列实现栈
4.1 问题描述
oj链接:225. 用队列实现栈 - 力扣(LeetCode)
4.2 问题分析
用两个队列来实现栈,首先我们需要了解栈和队列这两种结构各自的特点,栈要求先入后出,队列要求先进先出。
也就是说,用两个队列来模拟实现栈,主要是使用两个队列来完成先入后出的功能,而队列的特点是先入先出,在这里我们主要说明的是入栈和出栈操作:
对于入栈:
对于出栈:
总结起来即以下几点:
- 定义一个结构体Stack,包含两个队列q1和q2。
- 初始化栈时,分别初始化两个队列。
- 入栈操作时,将元素插入非空的队列中。
- 出栈操作时,将非空队列中的元素依次出队并插入另一个空队列中,直到只剩下一个元素,然后将该元素出队即可。
- 取栈顶元素时,将非空队列中的元素依次出队并插入另一个空队列中,直到只剩下一个元素,然后返回该元素即可。
- 判断栈是否为空时,判断两个队列是否都为空即可。
4.3 代码
typedef int QDatatype;
typedef struct QueueNode
{
struct QueueNode* next;
QDatatype data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
//初始化函数
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
//销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
//入队列
void QueuePush(Queue* pq, QDatatype x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->data = x;
newnode->next = NULL;
if (pq->head == NULL)
{
assert(pq->tail == NULL);
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
//判断是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size == 0;
}
//出队列
void QueuePop(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
if (pq->head == pq->tail)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
//求队列的元素个数
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//返回队首元素
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->head->data;
}
//返回队尾元素
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(!(QueueEmpty(pq)));
return pq->tail->data;
}
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq,QDatatype x);
void QueuePop(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
typedef struct {
Queue q1;
Queue q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
if(pst==NULL)
{
perror("malloc fail");
return NULL;
}
QueueInit(&pst->q1);
QueueInit(&pst->q2);
return pst;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))
{
QueuePush(&obj->q1, x);
}
else
{
QueuePush(&obj->q2, x);
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}
int myStackPop(MyStack* obj) {
assert(!myStackEmpty(obj));
Queue* nonemptyque = &obj->q1;
Queue* emptyque = &obj->q2;
if(QueueEmpty(&obj->q1))
{
nonemptyque = &obj->q2;
emptyque = &obj->q1;
}
while(QueueSize(nonemptyque)>1)
{
QueuePush(emptyque,QueueFront(nonemptyque));
QueuePop(nonemptyque);
}
int x = QueueFront(nonemptyque);
QueuePop(nonemptyque);
return x;
}
int myStackTop(MyStack* obj) {
assert(!myStackEmpty(obj));
Queue* nonemptyque = &obj->q1;
Queue* emptyque = &obj->q2;
if(QueueEmpty(&obj->q1))
{
nonemptyque = &obj->q2;
emptyque = &obj->q1;
}
return QueueBack(nonemptyque);
}
void myStackFree(MyStack* obj) {
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}
五、相关oj题 - 用栈实现队列
5.1 问题描述
oj链接:232. 用栈实现队列 - 力扣(LeetCode)
5.2 问题分析
我们要用两个栈来实现一个队列,栈的特点是先入后出,队列的特点是先入先出,我们这里的目的是使用两个栈达到先入先出的目的。
与之前的用两个队列来实现栈,用两个栈来实现队列相对简单,在之前的用两个队列来实现栈,我们在出栈时需要把两个队列中的数据来回翻转,但在本题中,我们只需要定义一个栈来进行插入操作,一个用来删除。
我们固定使用栈q1来进行入队操作,使用栈q2来进行出队操作。
入队时:
直接将数据插入到q1中。
出队时:
当q2为空时,再次将q1中数据依次出栈,然后依次插入到栈q2中。
具体总结如下:
- 定义一个结构体Queue,包含两个栈s1和s2。
- 初始化队列时,分别初始化两个栈。
- 入队操作时,将元素插入非空的栈s1中。
- 出队操作时,如果栈s2为空,则将栈s1中的元素依次出栈并插入栈s2中,然后将栈s2的栈顶元素出栈即可。
- 取队首元素时,如果栈s2为空,则将栈s1中的元素依次出栈并插入栈s2中,然后返回栈s2的栈顶元素即可。
- 判断队列是否为空时,判断两个栈是否都为空即可。
5.3 代码
typedef int STDataType;
#define N 4
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* ps);
void STDestroy(ST* ps);
void STPush(ST* ps, STDataType x);
void STPop(ST* ps);
int STsize(ST* ps);
bool STEmpty(ST* ps);
STDataType STTop(ST* ps);
//初始化函数
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType)*N);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->top = 0;
ps->capacity = N;
}
//销毁
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
//求栈中的元素
int STsize(ST* ps)
{
assert(ps);
return ps->top;
}
//入栈
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (STsize(ps) == ps->capacity)
{
STDataType* p = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
if (p == NULL)
{
perror("realloc fail");
return;
}
ps->a = p;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
//判断栈是否为空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//出栈
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
//取出栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top - 1];
}
typedef struct {
ST q1;
ST q2;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* pst = (MyQueue*)malloc(sizeof(MyQueue));
if(pst==NULL)
{
perror("malloc fail");
return NULL;
}
STInit(&pst->q1);
STInit(&pst->q2);
return pst;
}
void myQueuePush(MyQueue* obj, int x) {
STPush(&obj->q1, x);
}
bool myQueueEmpty(MyQueue* obj) {
return STEmpty(&obj->q1)&&STEmpty(&obj->q2);
}
int myQueuePop(MyQueue* obj) {
assert(!myQueueEmpty(obj));
if(STEmpty(&obj->q2))
{
while(STsize(&obj->q1)>0)
{
STPush(&obj->q2, STTop(&obj->q1));
STPop(&obj->q1);
}
int x= STTop(&obj->q2);
STPop(&obj->q2);
return x;
}
else
{
int x= STTop(&obj->q2);
STPop(&obj->q2);
return x;
}
}
int myQueuePeek(MyQueue* obj) {
assert(!myQueueEmpty(obj));
if(STEmpty(&obj->q2))
{
while(STsize(&obj->q1)>0)
{
STPush(&obj->q2, STTop(&obj->q1));
STPop(&obj->q1);
}
int x= STTop(&obj->q2);
return x;
}
else
{
int x= STTop(&obj->q2);
return x;
}
}
void myQueueFree(MyQueue* obj) {
STDestroy(&obj->q1);
STDestroy(&obj->q2);
free(obj);
}