用队列实现栈,用栈实现队列以及实现循环队列的练习

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);//再释放结构体;
}

/////////

至此,这是我对用队列实现栈,用栈实现队列以及实现循环队列的全部理解与认识,如有不足之处,请各位大佬不吝赐教!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值