1.用队列实现栈(来源力扣)
2.用栈实现队列(来源力扣)
3.设计循环队列(来源力扣)
1.用队列实现栈:实现栈的初始化,插入,删除,返回栈顶元素,判断栈是否为空,销毁释放栈
解题思路: 初始化:利用之前写好的队列初始化接口直接初始化这两个队列;
插入:有两个队列,向不为空的队列插入(不为空的叫队列一,为空的叫队列二),
删除:先将队列一元素倒到队列二中去,只留队列一中最后一个元素;然后删除;
返回栈顶元素:利用之前写好的 队列返回队尾接口 返回的值就是栈顶元素;
判断栈是否为空:调用 判断队列是否为空接口 判断队列一 队列二是否全部为空;
销毁释放栈:先销毁两个队列中的结点,再销毁这两个队列;
//自己写的队列:
typedef int typedata;
typedef struct QlistNode
{
typedata data;
struct QlistNode* next;
}Qnode;
typedef struct Queue
{
Qnode* head;
Qnode* tali;
int size;
}Queue;
//初始化接口:
void Queueinit(Queue* ps);
//销毁队列接口:
void Queuedestroy(Queue* ps);
//元素进队列接口:
void Queuepush(Queue* ps, typedata x);
//元素出队列接口:
void Queuepop(Queue* ps);
//获取队列头接口:
typedata QueueFront(Queue* ps);
//获取队列尾接口:
typedata QueueBack(Queue* ps);
//获取队列元素个数接口:
int Queuesize(Queue* ps);
//判空接口:
bool QueueEmpty(Queue* ps);
//队列打印接口:
void Queueprint(Queue* ps);
//初始化接口:
void Queueinit(Queue* ps)
{
assert(ps);
ps->head = NULL;
ps->tali = NULL;
ps->size = 0;
}
//销毁队列接口:
void Queuedestroy(Queue* ps)
{
assert(ps);
Qnode* cur = ps->head;
while (cur!= NULL)
{
Qnode* del =cur;
cur = cur->next;;
free(del);
del = NULL;
}
ps->head = ps->tali = NULL;
}
//元素进队列接口:
void Queuepush(Queue* ps, typedata x)
{
assert(ps);
Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
if (newnode == NULL)
{
perror("malloc fali");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (ps->tali==NULL)
{
ps->head =ps->tali = newnode;
}
else
{
ps->tali->next = newnode;
ps->tali=newnode;
}
ps->size++;
}
//元素出队列接口:
void Queuepop(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
if (ps->head->next==NULL)
{
free(ps->head);
ps->head =ps->tali = NULL;
}
else
{
Qnode* cur = ps->head->next;
free(ps->head);
ps->head = cur;
}
ps->size--;
}
//获取队列头接口:
typedata QueueFront(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
//if (ps->head == NULL)
//{
// exit(-1);
//}
return ps->head->data;
}
//获取队列尾接口:
typedata QueueBack(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
return ps->tali->data;
}
//获取队列元素个数接口:
int Queuesize(Queue* ps)
{
assert(ps);
assert(!QueueEmpty(ps));
return ps->size;
}
bool QueueEmpty(Queue* ps)
{
assert(ps);
return ps->head == NULL && ps->tali == NULL;
}
//队列打印接口:
void Queueprint(Queue* ps)
{
assert(ps);
int i = 0;
Qnode* cur = ps->head;
for (i = 0; i < ps->size; i++)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
/
/
//用自己写的队列来实现栈:
typedef struct {
Queue q1;
Queue q2;
} MyStack;//创建两个队列;,
MyStack* myStackCreate() {
MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
Queueinit(&obj->q1);//初始化队列;
Queueinit(&obj->q1);
return obj;
}
void myStackPush(MyStack* obj, int x) {
if(!QueueEmpty(&obj->q1))//如果q1队列不为空;
{
Queuepush(&obj->q1,x);//向q1队列插入;
}
else
{
Queuepush(&obj->q2,x);//否则向q2队列插入;
}
}
int myStackPop(MyStack* obj) {
Queue*emptyQ=&obj->q1;//定义一个结构体指针,假设q1为空;
Queue*noemptyQ=&obj->q2;//定义一个结构体指针,假设q2不为空;
if(!QueueEmpty(&obj->q1))//假如当q1不为空;
{
noemptyQ=&obj->q1;//把q1给不为空的指针;
emptyQ=&obj->q2;//把q2给为空的指针;
}
while(Queuesize(noemptyQ)>1)//调用不为空队列的元素个数接口使其为循环条件大于1;
{
Queuepush(emptyQ,QueueFront(noemptyQ));//调用入队接口,把不为空的队头 入到为空的队列中去;
Queuepop(noemptyQ);//调用出队列接口;删除不为空队列中的元素;
}
int ret=QueueFront(noemptyQ);//此时,不为空的队列中只有一个元素,将其用临时变量存贮起来;
Queuepop(noemptyQ);//调用出队列接口;删除不为空队列中的最后一个元素;
return ret;//将临时变量也就是栈顶元素返回;
}
int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))//如果q1不为空
{
return QueueBack(&obj->q1);//调用获取队尾接口拿到q1的尾元素也就是栈顶元素;
}
else
{
return QueueBack(&obj->q2);//如果q2不为空,调用获取队尾接口拿到q2的尾元素,也就是栈顶元素;
}
}
bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);//调用判空接口判断两个队列是否为空;
}
void myStackFree(MyStack* obj) {
Queuedestroy(&obj->q1);//释放q1;
Queuedestroy(&obj->q2);//释放q2;
free(obj);//最后释放创建的栈;
}
//////
2.用栈实现队列:实现队列初始化,入队列,出队列,返回队头元素,判断队列是否为空,销毁队列;
解题思路:队列初始化:调用之前写好的 栈初始化接口 来初始化这两个栈;
入队列:定义一个输入栈(元素都入到这个栈,叫做栈一),一个输出栈(叫做栈二);
返回队头元素:将栈一中的元素全部倒到栈二中,在栈二中调用获得栈顶元素接口,返回的就是队头元素;
出队列:调用返回队头元素接口,保存队头元素后,再把队头删除,返回保存的队头元素;
判断队列是否为空:调用 判断栈是否为空接口 判断栈一 栈二是否全部为空;
销毁队列:调用销毁栈接口 ,销毁栈一,栈二,再释放队列;
//自己写好的栈:
typedef char stacktype;
typedef struct stack
{
stacktype*arr;
int capacity;
int top;
}sk;
//初始化栈函数:
void stackinit(sk* ps);
//销毁栈函数:
void stackdestroy(sk* ps);
//入栈函数:
void stackpush(sk* ps,stacktype x);
//打印栈中的元素函数:
void stackprint(sk* ps);
//出栈函数:
void stackpop(sk* ps);
//获取栈顶元素函数:
stacktype stacktop(sk* ps);
//获取栈中元素个数函数:
stacktype stacksize(sk* ps);
//判空函数:
bool stackempty(sk* ps);
//初始化栈函数:
void stackinit(sk* ps)
{
assert(ps);
ps->arr= (stacktype*)malloc(sizeof(stacktype) * 4);
if (ps->arr == NULL)
{
perror("malloc");
exit(-1);
}
ps->capacity = 4;
ps->top = 0;
}
//像栈中插入元素函数:
void stackpush(sk* ps, stacktype x)
{
if (ps->top == ps->capacity)
{
stacktype*ptr = (stacktype*)realloc(ps->arr,sizeof(stacktype)*(ps->capacity) *2);
if (ptr == NULL)
{
perror("realloc fail");
}
ps->arr = ptr;
ps->capacity *= 2;
}
ps->arr[ps->top] = x;
ps->top++;
}
//打印栈中的元素函数:
void stackprint(sk* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->top; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
//出栈函数:
void stackpop(sk* ps)
{
assert(ps);
assert(!stackempty(ps));
ps->top--;
}
//获取栈顶元素函数:
stacktype stacktop(sk* ps)
{
assert(ps);
assert(!stackempty(ps));
return ps->arr[ps->top - 1];
}
//判空函数:
bool stackempty(sk* ps)
{
assert(ps);
//return ps->top == 0 ? true : false;
return ps->top == 0;
}
//获取栈中元素个数函数:
stacktype stacksize(sk* ps)
{
assert(ps);
return ps->top;
}
//销毁栈函数:
void stackdestroy(sk* ps)
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->capacity = 0;
ps->top = 0;
}
/
/
//利用两个栈来实现一个队列:
typedef struct {
sk pushst;
sk popst;
} MyQueue;//创建两个栈利用结构体,模拟实现队列;
MyQueue* myQueueCreate() {
MyQueue*obj=(MyQueue*)malloc(sizeof(MyQueue));//开辟结构体空间;
stackinit(&obj->pushst);//调用初始化接口初始化输入栈,不为空;
stackinit(&obj->popst);//调用初始化接口初始化输出栈,为空;
return obj;//返回结构体;
}
void myQueuePush(MyQueue* obj, int x) {
stackpush(&obj->pushst,x);//把数据全部只放进输入栈;,
}
int myQueuePeek(MyQueue* obj);//在这声明一下,方便myQueuePop调用;
int myQueuePop(MyQueue* obj) {
int ret=myQueuePeek(obj);//将模拟实现队列的队头用临时变量存储起来;
stackpop(&obj->popst);//删除掉队头;
return ret;//返回队头;
}
int myQueuePeek(MyQueue* obj) {
if(stackempty(&obj->popst))//如果输出栈为空;则需要 倒数据;
{
while(!stackempty(&obj->pushst))//如果输入栈不为空,一直将输入栈的元素倒到输出栈;
{
stackpush(&obj->popst,stacktop(&obj->pushst));//调用入栈接口,将输入栈的栈顶元素入到输出栈中
stackpop(&obj->pushst);//将输入栈元素删除,直至为空;
}
}
return stacktop(&obj->popst);//数据倒完到输出栈,返回输出栈栈顶元素;
}
bool myQueueEmpty(MyQueue* obj) {
return stackempty(&obj->pushst)&&stackempty(&obj->popst);//调用判空接口判断两个栈是否为空;
}
void myQueueFree(MyQueue* obj) {
stackdestroy(&obj->pushst);//调用销毁栈接口,销毁输入栈;
stackdestroy(&obj->popst);//调用销毁栈接口,销毁输出栈;
free(obj);//最后释放掉开辟的结构体指针空间;
}
//////
3.设计循环队列:
3.1 实现检查循环队列是否为空为满的图解:
3.2 实现循环队列的插入的图解:
3.3 实现循环队列的删除的图解:
3.4 循环队列中获取队头队尾数据:只需要判断队列是否为空,如果为空返回-1,不为空直接返回队头,队尾的元素;
3.5 销毁循环队列:先释放结构体中的数组,再释放结构体;
实现循环队列的具体代码如下所示:
typedef struct {
int*arr;//用数组来实现循环队列;
int front;//队头;
int rear;//队尾;
int k;//队列长度;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//开辟循环队列结构体的空间;
obj->arr=(int*)malloc(sizeof(int)*(k+1));//开辟循环队列中元素空间的大小,要多开辟一个空间,即k+1个空间;
obj->front=obj->rear=0;//先让队头队尾都指向数组开头;
obj->k=k;//长度为k;
return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
assert(obj);//判空;
return obj->rear==obj->front;//如果队头和队尾相等,则是说明循环队列为空;
}
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->arr[obj->rear++]=value;
obj->rear%=(obj->k+1);//如果此时rear在k+1的位置时,我们需要将队尾转到数组前面,实现循环队列;
return true;//成功插入返回true;
}
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
assert(obj);//判空
if(myCircularQueueIsEmpty(obj))//判断循环队列是否为空,如果为空,则不能成功删除;
{
return false;
}
//如果不为空,那么队头向后加一;
obj->front++;
obj->front%=(obj->k+1);如果此时front在k+1的位置时,我们需要将队头转到数组前面,实现循环队列;
return true;//成功删除返回true;
}
int myCircularQueueFront(MyCircularQueue* obj) {
assert(obj);//判空
if(myCircularQueueIsEmpty(obj))//判断循环队列是否为空,
{
return -1;//如果为空,返回-1;
}
else
{
return obj->arr[obj->front];//如果不为空,返回队头元素;
}
}
int myCircularQueueRear(MyCircularQueue* obj) {
assert(obj);//判空
if(myCircularQueueIsEmpty(obj))//判断循环队列是否为空,
{
return -1;//如果为空,返回-1;
}
else
{
//int ret=obj->rear==0?k:obj->rear-1;
//return obj->arr[ret];
return obj->arr[(obj->rear+obj->k)%(obj->k+1)];//如果不为空,返回队头元素;
}
}
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->arr);//先释放结构体中数组;
free(obj);//再释放结构体;
}
/////////