数据结构之——《队列》

本文介绍了数据结构中的队列,详细阐述了队列的基本概念、接口实现,包括入队、出队等操作。接着,通过一个案例展示了如何使用队列来模拟栈的功能,实现了入栈、出栈、获取栈顶元素和判断栈空的方法。通过这种方式,读者可以更深入地理解队列和栈的交互运用。
摘要由CSDN通过智能技术生成


1.队列

队列:是一种先进先出(FIFO)的线性表,允许在表的一端进行插入(即入队),在表的另一端进行删除(即出队)。
入队:队尾(rear)插入;
出队:队头(front)删除;

2.队列接口实现

(1)定义队列结构体
代码如下(示例):

typedef int QDataType;

typedef struct QNode
{
	struct QNode* _next;
	QDataType _data;
}QNode;

typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
	int _size;
}Queue;

(2)队列初始化
代码如下(示例):

void queueInit(Queue* q)
{
	q->_front = q->_rear = NULL;
	q->_size = 0;
}

(3)创建结点
代码如下(示例):

QNode* creatNode(QDataType data)
{
	QNode* node = (QNode*)malloc(sizeof(QNode));
	node->_data = data;
	node->_next = NULL;
	return node;
}

(4)入队(尾插)
代码如下(示例):

void queuePush(Queue* q, QDataType data)
{
	QNode* node = creatNode(data);
	if (q->_front == NULL)
		q->_front = q->_rear = node;
	else
	{
		q->_rear->_next = node;
		q->_rear = node;
	}
	++q->_size;
}

(5)出队(头删)
代码如下(示例):

void queuePop(Queue* q)
{
	if (q->_front)
	{
		QNode* next = q->_front->_next;
		free(q->_front);
		q->_front = next;
		//删除之后是否为空队列
		if (q->_front == NULL)
			q->_rear = NULL;
		--q->_size;
	}
}

(6)获取队尾元素
代码如下(示例):

QDataType queueBack(Queue* q)
{
	return q->_rear->_data;
}

(7)获取队头元素
代码如下(示例):

QDataType queueFront(Queue* q)
{
	return q->_front->_data;

}

(8)队列的大小
代码如下(示例):

int queueSize(Queue* q)
{
	return q->_size;
}

(9)判断队列是否为空
代码如下(示例):

int queueEmpty(Queue* q)
{
	if (q->_front == NULL)
		return 1;
	return 0;
}

(10)销毁队列
代码如下(示例):

void queueDestroy(Queue* q)
{
	QNode* cur = q->_front;
	while (cur)
	{
		QNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	q->_front = q->_rear = NULL;
	q->_size = 0;
}

3.应用案例:用一个队列实现栈

根据第二部的定义实现的队列接口函数,则用队列实现栈的功能就容易多了。 入栈:队列的入队操作。 出栈:除过最后一个元素,队列中其他元素循环进行出队入队操作,最后一个元素只出队。 获取栈顶元素:队尾元素的获取。 栈是否为空:队列是否为空。
typedef struct {
	Queue q;
} MyStack;

MyStack* myStackCreate(){
	MyStack* ms = (MyStack*)malloc(sizeof(MyStack));
	queueInit(&ms->q);
	return ms;
}

(1)入栈

void myStackPush(MyStack* obj, int x) 
{
	queuePush(&obj->q, x);
}

(2)出栈

int myStackPop(MyStack* obj)
{
	int ret;
	int size = queueSize(&obj->q);
	while (size > 1)
	{
		int front = queueFront(&obj->q);
		queuePop(&obj->q);
		queuePush(&obj->q,front);
		--size;
	}
	ret = queueFront(&obj->q);
	queuePop(&obj->q);
	return ret;
}

(3)获取栈顶元素

int myStackTop(MyStack* obj)
{
	return queueBack(&obj->q);
}

(4)栈是否为空

int myStackEmpty(MyStack* obj)
{
	return queueEmpty(&obj->q);
}

(5)栈释放

void myStackFree(MyStack* obj)
{
	queueDestroy(&obj->q);
	free(obj);
}

4.小结

通过学习队列线性表,对基本接口函数较为熟练掌握,而用队列实现栈,只是调用了队列的接口函数完成对应栈的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include #include #include //队列最大长度 #define MAX_QUEUE 1024 //偷懒,就用静态队列了 static int mQueue[MAX_QUEUE]; //队列插入 void InsertData(int **Front, int **Rear) { if (*Rear + 1 == *Front && (*Rear + 1 - MAX_QUEUE != *Front)) { //当队列数据已满,返回 puts("Queue Size Overflow!\n"); return; } else if (*Rear - mQueue > MAX_QUEUE) { //实现的是类似循环队列,但由于是静态线性队列(数组) //而不是用链表来实现的,所以到静态队列(数组)尾部,尾指针自动指向(数组)头部 *Rear = mQueue; } puts("Input Data:"); scanf("%d", *Rear); //输入数据后,尾指针后移 *Rear += 1; } //从头指针删除一个队列的数据 void DeleteData(int **Front, int **Rear) { if (*Front == *Rear) { //头指针尾指针重合,队列空,不能删除,返回 puts("Queue Empty!\n"); return; } else if (*Front - mQueue > MAX_QUEUE) { //参考 Rear *Front = mQueue; } //从头指针删除一个数据 *Front += 1; } //显示队列数据 void ShowData(int **Front, int **Rear) { int *temp; for (temp=*Front; temp!=*Rear; temp++) { printf("%d --> ", *temp); } puts("\n"); } void usage(void) { puts("1. Insert Data"); puts("2. Delete Data"); puts("3. Show Data"); } int main(int argc, char **argv) { //头指针,尾指针 //队列一个特性 First in first out FIFO int *pFront, *pRear; int op_code; //初始化队列,头指针和尾指针此时指向的地址相同 pFront = pRear = mQueue; while (1) { usage(); scanf("%d", &op_code); switch (op_code) { case 1: printf("%p\n", pFront); printf("%d\n", *pFront); InsertData(&pFront, &pRear); break; case 2: DeleteData(&pFront, &pRear); break; case 3: ShowData(&pFront, &pRear); break; default: break; } } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值