数据结构---队列

目录

一、队列的概念及结构

二、队列的实现

1.队列的结构体

2.队列的初始化

3.队列的判空

4.队列的插入数据

5.队列的删除数据

6.查看队头的数据

7.查看队尾的数据

8.求出队列的元素个数

9.队列的销毁

三、队列相关的oj题

1.思路

2.完整答案


一、队列的概念及结构

        队列:只允许在一端进行数据的插入,在另一端进行数据的删除操作的特殊线性表,队列的特点是先进先出,进行插入数据的一端称为队尾,删除数据的一端称为队头。

二、队列的实现

        队列同样可以用数组或者链表来实现,但是我们这里就不采取数组的方法,因为队列需要不断的头删,用数组效率较低,而单链表却特别适合在队头出数据。

1.队列的结构体

队列的结构体我们有两个部分:一是每一个的节点,二是用来存储头尾指针以及size的结构体

//队列建议用单链表实现,因为不仅需要头删,还需要尾插,所以我们还要添加一个头尾指针方便操作
typedef int Datatype;
typedef struct QueueNode
{
	Datatype data;
	struct QueueNode* next;
}QueueNode;

typedef struct Queue
{
	QueueNode* head;
	QueueNode* tail;
	int size;
}Queue;

2.队列的初始化

void QueueInit(Queue* queue)
{
	assert(queue);
	queue->head = NULL;
	queue->tail = NULL;
	queue->size = 0;
}

3.队列的判空

bool QueueEmpty(Queue* queue)
{
	assert(queue);
	return queue->size == 0;
}

4.队列的插入数据

void QueuePush(Queue* queue,Datatype x)
{
	assert(queue);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	newnode->data = x;
	newnode->next = NULL;
	if (newnode==NULL)
	{
		perror("malloc");
		return;
	}
	//如果是空链表,头插
	if (queue->head==NULL)
	{
		queue->head = newnode;
		queue->tail = newnode;
	}
	else
	{
		queue->tail->next = newnode;
		queue->tail = newnode;
	}
	queue->size++;
}

5.队列的删除数据

void QueuePop(Queue* queue)
{
	assert(queue);
	//头删
	//如果是空不能Pop
	assert(!QueueEmpty(queue));
	//一个节点
	if (queue->head->next==NULL)
	{
		free(queue->head);
		queue->head = queue->tail=NULL;
	}
	//多个节点(因为有tail的存在,必须要分类讨论)
	else
	{
		QueueNode* second = queue->head->next;
		free(queue->head);
		queue->head = second;
	}
	
	queue->size--;
}

6.查看队头的数据

Datatype QueueFront(Queue* queue)
{
	assert(queue);
	assert(!QueueEmpty(queue));
	return queue->head->data;
}

7.查看队尾的数据

Datatype QueueBack(Queue* queue)
{
	assert(queue);
	assert(!QueueEmpty(queue));
	return queue->tail->data;
}

8.求出队列的元素个数

int Queuesize(Queue* queue)
{
	assert(queue);
	return queue->size;
}

9.队列的销毁

void QueueDestroy(Queue* queue)
{
	assert(queue);
	QueueNode* cur = queue->head;
	while (cur!=NULL)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
	queue->head = queue->tail = NULL;
	queue->size = 0;
}

三、队列相关的oj题

1.思路

        这是一道初学队列时候的经典题目,他能让我们很好的理解队列的相关特点。针对这道题目,我们的思路是:如果Push就让数据先都入一个队列中,如果要出栈就只保留一个数据在当前队列中,先把其余的导入到另外一个队列中,把剩下的那个出栈即可。由于队列的性质,数据的来回倒,并不会影响数据的顺序,从而用两个队列实现一个栈!

2.完整答案

        由于这道题目并没有什么特殊的情况,所以我们这里直接给出结果

//定义MyStack结构体
typedef struct 
{
    Queue q1;
    Queue q2;    
} MyStack;


//创建一个MyStack栈
MyStack* myStackCreate() 
{
    MyStack* obj=(MyStack*)malloc(sizeof(MyStack));    
    if(obj==NULL)
    {
        perror("malloc");
        return NULL;
    }
    //初始化
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);


    return obj;
}

//压栈
void myStackPush(MyStack* obj, int x) 
{
    //在有数据的队列才能进行插入数据
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }   
    else
    {
        QueuePush(&obj->q2,x);
    } 
}

//出栈
int myStackPop(MyStack* obj) 
{
    //找到没有数据和有数据的队列
    Queue* PEmpty=&obj->q1;
    Queue* PNoEmpty=&obj->q2;
    //如果假设错误了,就换过来
    if(QueueEmpty(PNoEmpty))
    {
        PNoEmpty=&obj->q1;
        PEmpty=&obj->q2;
    }
    //把非空的队列移动到另外一个,直到只剩下一个数据
    while(Queuesize(PNoEmpty)>1)
    {
        QueuePush(PEmpty,QueueFront(PNoEmpty));
        QueuePop(PNoEmpty);
    }

    int top=QueueFront(PNoEmpty);
    QueuePop(PNoEmpty);

    return top;
}

//查看栈顶的数据
int myStackTop(MyStack* obj) 
{
    //返回非空的队列的尾
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);
    }
}

//判断栈是否为空
bool myStackEmpty(MyStack* obj) 
{
    return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);    
}

void myStackFree(MyStack* obj) 
{
    QueueDestroy(&obj->q1);
    QueueDestroy(&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);
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值