栈和队列----(2

队列是一种种常见的数据结构,它用来解决一些数据类型的问题,那么好,我来带着大家来学习一下队列

这里写目录标题

  • 队列
    • 队列的认识
    • 队列的模拟实现
    • 队列的练习

队列

队列的认识

我们学完了栈之后,紧接着再来了解一下队列的,和栈一样,是一种操作受限制的线性表

队列(queue):具有先进先出的特点,与栈是相反的。
特点:只允许在表的前端进行插入删除操作,在表的后端进行插入操作

队列的模拟实现

实现一个队列的功能,需要有插入,删除,返回队头和队尾元素,队列大小,是否为空这些功能。
仔细想一下这些功能,使用单链表的方法是比较合适的

首先创建一个结构体来存放下一个节点和队列中该节点的值

typedef int qudatetype;

typedef struct queuenode {
	qudatetype val;
	struct queuende* next;
}qunode;

但是,我们需要返回队列的尾部元素,如果每次都遍历这个队列,会使时间复杂度较大,那么,我们需要一个指针来指向队列链表的尾部,这样可使效率提高

这里我们在创建一个结构体用来放队列的头节点和尾节点,在加上队列的大小

typedef struct queue {
	qunode* phead;
	qunode* ptail;
	int size;
}qu;

这样我们一个队列的准备工作就完成了

下面我们开始队列的模拟实现,我们采用分模块的方式进行实现,这里,我在代码中会进行注释,可直接阅读代码来学习队列的实现。

queue.h用来声明函数
queue,c用来实现队列的各个功能
test.c用来测试队列

queue.h

#include
#include
#include
#include

typedef int qudatetype;

typedef struct queuenode {
	qudatetype val;
	struct queuende* next;
}qunode;

typedef struct queue {
	qunode* phead;
	qunode* ptail;
	int size;
}qu;

//队列的初始化
void initqu(qu* pq);

void qudestroy(qu* pq);

//队列的插入和弹出
void queuepush(qu* pq,qudatetype x);

void queuepop(qu* pq);

//返回队列的头尾

qudatetype queuehead(qu* pq);

qudatetype queuetail(qu* pq);


//返回队列是否为空
bool queueempty(qu* pq);


//返回队列长度
int queuesize(qu* pq);

queue.c

#include"queue.h"

//队列的初始化
void initqu(qu* pq)
{
	assert(pq);

	pq->size = 0;
	pq->phead = pq->ptail = NULL;
}

//队列的销毁

void qudestroy(qu* pq)
{
	assert(pq);//断言

	qunode* cur = pq->phead;

	while (cur)//遍历一下队列,依次进行内存释放
	{
		qunode* next = cur->next;

		free(cur);
		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;//收尾
}

//队列的插入和弹出
void queuepush(qu* pq, qudatetype x)
{
	assert(pq);

	qunode* newnode = (qunode*)malloc(sizeof(qunode));//创建新节点
	assert(newnode);//断言,如果开辟内存失败,程序终止
	//对节点进行初始化
	newnode->val = x;
	newnode->next = NULL;
	//如果是第一次插入,执行if中的操作
	if (pq->phead == NULL)
		pq->phead = pq->ptail = newnode;
	//否则,执行else中的操作
	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;//更新ptail指向队列尾部
	}
	pq->size++;//大小自增
}

void queuepop(qu* pq)
{
	assert(pq);
	assert(pq->phead);//队列为空,无法删除,程序终止

	qunode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	如果队列中只有一个元素,执行以下操作
	if (pq->phead == NULL)
		pq->ptail = NULL;

	pq->size--;
}

//返回队列的头尾

qudatetype queuehead(qu* pq)
{
	assert(pq);

	assert(pq->phead);

	return pq->phead->val;
}

qudatetype queuetail(qu* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->val;
}


//返回队列是否为空
bool queueempty(qu* pq)
{
	assert(pq);

	return pq->size == 0;//size为0,为真返回1,反之,返回0
}


//返回队列长度
int queuesize(qu* pq)
{
	assert(pq);

	return pq->size;
}

test.c

#include"queue.h"

int main()
{
	qu q;
	initqu(&q);
	queuepush(&q, 1);
	queuepush(&q, 2);
	queuepush(&q, 3);
	queuepush(&q, 4);
	queuepop(&q);
	queuepop(&q);
	queuepop(&q);

	while (!queueempty(&q))
	{
		printf("%d---", queuehead(&q));
		queuepop(&q); 
	}
	qudestroy(&q);
	return 0;
}

队列的练习

趁热打铁,做一道题,练习一下队列
先来看一下这道题
https://leetcode.cn/problems/implement-stack-using-queues/

栈和队列----(2_第1张图片
使用队列来实现栈的功能
思路
我们浅浅思考一下,栈和队列的特点,栈是先进后出,队列是先进先出,这样,我们可以利用两个队列来实现一个栈的功能,
假设一个队列1,2,3,4,5;我们可以把它们的前4个元素,导入到另一个空队列中,变成1,2,3,4;然后把剩下的5删除,这样我们就达到了栈的先进后出的特点了。其他的功能也是比较容易实现的

代码实现

typedef int qudatetype;

typedef struct queuenode {
	qudatetype val;
	struct queuende* next;
}qunode;

typedef struct queue {
	qunode* phead;
	qunode* ptail;
	int size;
}qu;

void initqu(qu* pq)
{
	assert(pq);

	pq->size = 0;
	pq->phead = pq->ptail = NULL;
}

//队列的销毁

void qudestroy(qu* pq)
{
	assert(pq);

	qunode* cur = pq->phead;

	while (cur)
	{
		qunode* next = cur->next;

		free(cur);
		cur = next;
	}

	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

//队列的插入和弹出
void queuepush(qu* pq, qudatetype x)
{
	assert(pq);

	qunode* newnode = (qunode*)malloc(sizeof(qunode));
	assert(newnode);

	newnode->val = x;
	newnode->next = NULL;

	if (pq->phead == NULL)
		pq->phead = pq->ptail = newnode;

	else
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

void queuepop(qu* pq)
{
	assert(pq);
	assert(pq->phead);

	qunode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	if (pq->phead == NULL)
		pq->ptail = NULL;

	pq->size--;
}

//返回队列的头尾

qudatetype queuehead(qu* pq)
{
	assert(pq);

	assert(pq->phead);

	return pq->phead->val;
}

qudatetype queuetail(qu* pq)
{
	assert(pq);
	assert(pq->ptail);

	return pq->ptail->val;
}


//返回队列是否为空
bool queueempty(qu* pq)
{
	assert(pq);

	return pq->size == 0;
}


//返回队列长度
int queuesize(qu* pq)
{
	assert(pq);

	return pq->size;
}


typedef struct {
    qu q1;
    qu q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack*pst=(MyStack*)malloc(sizeof(MyStack));
    initqu(&pst->q1);
    initqu(&pst->q2);

    return pst;
}

void myStackPush(MyStack* obj, int x) {
    if(!queueempty(&obj->q1))
    {
        queuepush(&obj->q1,x);
    }
    else
    {
        queuepush(&obj->q2,x);
    }
}

int myStackPop(MyStack* obj) {
    qu *empty=&obj->q1;
    qu *nonempty=&obj->q2;
    if(!queueempty(empty))
    {
        empty=&obj->q2;
        nonempty=&obj->q1;
    }

    while(queuesize(nonempty)>1)
    {
        queuepush(empty,queuehead(nonempty));
        queuepop(nonempty);
    }

    int top=queuehead(nonempty);
    queuepop(nonempty);
    return top;
}

int myStackTop(MyStack* obj) {
    if(queueempty(&obj->q1))
        return queuetail(&obj->q2);
    return queuetail(&obj->q1);
}

bool myStackEmpty(MyStack* obj) {
    
    return queueempty(&obj->q1)&&queueempty(&obj->q2);
}

void myStackFree(MyStack* obj) {
    qudestroy(&obj->q1);
    qudestroy(&obj->q2);
    free(obj);
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

这道题有了思路代码还是很好理解的,大家可以参考一下通过的代码,自己去oj一下

栈和队列的讲解就到这里了。大家有不同的见解可以一起交流一下

感谢观看,有错误或不足请指出

你可能感兴趣的:(c语言,数据结构)