数据结构之队列的实现(附源码)

03-08 1471阅读 0评论

目录

一、队列的概念及结构

二、队列的实现

 拓展:循环队列

三、初学的队列以及栈和队列结合的练习题


一、队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

数据结构之队列的实现(附源码) 第1张

二、队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

数据结构之队列的实现(附源码) 第2张

 具体代码如下(C语言实现):

#pragma once
//Queue.h
// 链式结构:表示队列
#include 
#include 
#include 
typedef int QDateType;
typedef struct QListNode
{
	struct QListNode* _next;
	QDateType _data;
}QNode;
// 队列的结构 
typedef struct Queue
{
	QNode* _front;//队头
	QNode* _rear;//队尾
	int size;
}Queue;
// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDateType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDateType QueueFront(Queue* q);
// 获取队列队尾元素 
QDateType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);
//Queue.c
#include "Queue.h"
void QueueInit(Queue* q)
{
	assert(q);
	q->_front = NULL;
	q->_rear = NULL;
	q->size = 0;
}
void QueuePush(Queue* q, QDateType data)
{
	assert(q);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("tmp malloc");
		exit(-1);
	}
	tmp->_data = data;
	tmp->_next = NULL;
	if (q->_rear == NULL)
	{
		q->_front = q->_rear = tmp;
	}
	else
	{
		q->_rear->_next = tmp;
		q->_rear = tmp;
	}
	q->size++;
}
void QueuePop(Queue* q)
{
	assert(q);
	assert(QueueEmpty(q));
	if (q->_front->_next == NULL)
	{
		free(q->_front);
		q->_front = q->_rear = NULL;
	}
	else
	{
		QNode* next = q->_front->_next;
		free(q->_front);
		q->_front = next;
	}
	q->size--;
}
QDateType QueueFront(Queue* q)
{
	assert(q);
	assert(QueueEmpty(q));
	return q->_front->_data;
}
QDateType QueueBack(Queue* q)
{
	assert(q);
	assert(QueueEmpty(q));
	return q->_rear->_data;
}
int QueueSize(Queue* q)
{
	assert(q);
	return q->size;
}
int QueueEmpty(Queue* q)
{
	assert(q);
	return q->size;
}
void QueueDestroy(Queue* q)
{
	assert(q);
	QNode* cur = q->_front;
	while (cur)
	{
		Queue* next = cur->_next;
		free(cur);
		cur = next;
	}
	q->_front = q->_rear = NULL;
	q->size = 0;
}
//test.c
#include "Queue.h"
void test02()
{
	Queue q1;
	QueueInit(&q1);
	QueuePush(&q1, 1);
	QueuePush(&q1, 2);
	QueuePush(&q1, 3);
	QueuePush(&q1, 4);
	QueuePush(&q1, 5);
	QueuePop(&q1);
	while (QueueEmpty(&q1))
	{
		printf("%d ", QueueFront(&q1));
		QueuePop(&q1);
	}
	printf("\n");
	QueueDestroy(&q1);
}
int main()
{
	test02();
	return 0;
}

 拓展:循环队列

数据结构之队列的实现(附源码) 第3张

如上图所示:循环队列的节点数一般会比要求的节点数多一个,以便区分空的循环队列和满的循环队列。空的循环队列front和rear指向同一个节点,满的循环队列可以理解为rear = front + 1。

三、初学的队列以及栈和队列结合的练习题

题目一:设计循环队列

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。
    typedef struct 
    {
        int* a;
        int front;
        int rear;
        int k;
    } MyCircularQueue;
    MyCircularQueue* myCircularQueueCreate(int k) 
    {
        MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
        obj->a = (int*)malloc(sizeof(int)*(k+1));
        obj->front = obj->rear = 0;
        obj->k = k;
        return obj;
    }
    bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
    {
        //front和rear相等即为空
        return obj->front == obj->rear;    
    }
    bool myCircularQueueIsFull(MyCircularQueue* obj) 
    {
        //数学方法判满
        return (obj->rear + 1) % (obj->k + 1) == obj->front;
    }
    bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) 
    {
        if(myCircularQueueIsFull(obj))
        return false;
        obj->a[obj->rear] = value;
        ++obj->rear;
        //不然rear可能越界
        obj->rear %= (obj->k+1);
        return true;
    }
    bool myCircularQueueDeQueue(MyCircularQueue* obj) 
    {
        if(myCircularQueueIsEmpty(obj))
        return false;
        obj->front++;
        obj->front %= (obj->k+1);
        return true; 
    }
    int myCircularQueueFront(MyCircularQueue* obj) 
    {
        if(myCircularQueueIsEmpty(obj))
        return -1;
        else
        return obj->a[obj->front];
    }
    int myCircularQueueRear(MyCircularQueue* obj) 
    {
        if(myCircularQueueIsEmpty(obj))
        return -1;
        else
        //数学方法
        return obj->a[(obj->rear + obj->k) % (obj->k + 1)];
    }
    void myCircularQueueFree(MyCircularQueue* obj) 
    {
        free(obj->a);
        free(obj);
    }

    题目二:用队列实现栈

    思路:用两个队列,保持一个队列为空一个不为空,当要出栈的时候就将不为空的队列中除了队尾的元素全都入到为空的队列中,然后将唯一的那个元素出栈。

    typedef int QDateType;
    typedef struct QListNode
    {
    	struct QListNode* _next;
    	QDateType _data;
    }QNode;
    // 队列的结构 
    typedef struct Queue
    {
    	QNode* _front;
    	QNode* _rear;
    	int size;
    }Queue;
    void QueueInit(Queue* q)
    {
    	assert(q);
    	q->_front = NULL;
    	q->_rear = NULL;
    	q->size = 0;
    }
    void QueuePush(Queue* q, QDateType data)
    {
    	assert(q);
    	QNode* tmp = (QNode*)malloc(sizeof(QNode));
    	if (tmp == NULL)
    	{
    		perror("tmp malloc");
    		exit(-1);
    	}
    	tmp->_data = data;
    	tmp->_next = NULL;
    	if (q->_rear == NULL)
    	{
    		q->_front = q->_rear = tmp;
    	}
    	else
    	{
    		q->_rear->_next = tmp;
    		q->_rear = tmp;
    	}
    	q->size++;
    }
    void QueuePop(Queue* q)
    {
    	assert(q);
    	assert(QueueEmpty(q));
    	if (q->_front->_next == NULL)
    	{
    		free(q->_front);
    		q->_front = q->_rear = NULL;
    	}
    	else
    	{
    		QNode* next = q->_front->_next;
    		free(q->_front);
    		q->_front = next;
    	}
    	q->size--;
    }
    QDateType QueueFront(Queue* q)
    {
    	assert(q);
    	assert(QueueEmpty(q));
    	return q->_front->_data;
    }
    QDateType QueueBack(Queue* q)
    {
    	assert(q);
    	assert(QueueEmpty(q));
    	return q->_rear->_data;
    }
    int QueueSize(Queue* q)
    {
    	assert(q);
    	return q->size;
    }
    int QueueEmpty(Queue* q)
    {
    	assert(q);
    	return q->size;
    }
    void QueueDestroy(Queue* q)
    {
    	assert(q);
    	QNode* cur = q->_front;
    	while (cur)
    	{
    		Queue* next = cur->_next;
    		free(cur);
    		cur = next;
    	}
    	q->_front = q->_rear = NULL;
    	q->size = 0;
    }
    typedef struct 
    {
        Queue q1;
        Queue q2;
    } MyStack;
    MyStack* myStackCreate() 
    {
        MyStack* tmp = (MyStack*)malloc(sizeof(MyStack));
        QueueInit(&tmp->q1);
        QueueInit(&tmp->q2);
        return tmp;
    }
    void myStackPush(MyStack* obj, int x) 
    {
        if(QueueEmpty(&obj->q1))
        {
            QueuePush(&obj->q1, x);
        }
        else
        {
            QueuePush(&obj->q2, x);
        }
    }
    int myStackPop(MyStack* obj) 
    {
        Queue* empty = &obj->q1;
        Queue* noempty = &obj->q2;
        if(QueueEmpty(&obj->q1))
        {
            empty = &obj->q2;
            noempty = &obj->q1;
        }
        while(QueueSize(noempty) > 1)
        {
            QueuePush(empty, QueueFront(noempty));
            QueuePop(noempty);
        }
        int top = QueueFront(noempty);
        QueuePop(noempty);
        return top;
    }
    int myStackTop(MyStack* obj) 
    {
        if(QueueEmpty(&obj->q1))
        return QueueBack(&obj->q1);
        else
        return QueueBack(&obj->q2);
    }
    bool myStackEmpty(MyStack* obj) 
    {
        int ret1, ret2;
        if(QueueEmpty(&obj->q1) == 0)
        ret1 = 0;
        else
        ret1 = 1;
        if(QueueEmpty(&obj->q2) == 0)
        ret2 = 0;
        else
        ret2 = 1;
        if(ret1 == 0 && ret2 == 0)
        return true;
        else
        return false;
    }
    void myStackFree(MyStack* obj) 
    {
        QueueDestroy(&obj->q1);
        QueueDestroy(&obj->q2);
        free(obj);
    }

    题目三:用栈实现队列

    思路:使用两个栈,一个push栈一个pop栈,先往push栈中堆入元素,出队时,先将push栈中的元素先pop到pop栈中,再从pop栈中pop元素,其间再有元素堆入入到push栈中。

    typedef int STDataType;
    typedef struct Stack
    {
    	STDataType* _a;
    	int _top;		// 栈顶
    	int _capacity;  // 容量 
    }Stack;
    void StackInit(Stack* ps)
    {
    	assert(ps);
    	ps->_a = NULL;
    	ps->_top = 0;
    	ps->_capacity = 0;
    }
    void StackPush(Stack* ps, STDataType data)
    {
    	assert(ps);
    	if (ps->_capacity == ps->_top)
    	{
    		int newCapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
    		STDataType* tmp = (STDataType*)realloc(ps->_a,sizeof(STDataType) * newCapacity);
    		if (tmp == NULL)
    		{
    			perror("realloc fail");
    			exit(-1);
    		}
    		ps->_a = tmp;
    		ps->_capacity = newCapacity;
    	}
    	ps->_a[ps->_top] = data;
    	ps->_top++;
    }
    void StackPop(Stack* ps)
    {
    	assert(ps);
    	assert(ps->_top > 0);
    	ps->_top--;
    }
    STDataType StackTop(Stack* ps)
    {
    	assert(ps);
    	assert(ps->_top > 0);
    	return ps->_a[ps->_top - 1];
    }
    int StackSize(Stack* ps)
    {
    	assert(ps);
    	return ps->_top;
    }
    int StackEmpty(Stack* ps)
    {
    	return ps->_top;
    }
    void StackDestroy(Stack* ps)
    {
    	assert(ps);
    	free(ps->_a);
    	ps->_a = NULL;
    	ps->_capacity = 0;
    	ps->_top = 0;
    }
    typedef struct 
    {
        Stack pushst;
        Stack 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) 
    {
        //pop栈为空就往其中堆入元素
        if(StackEmpty(&obj->popst) == 0)
        {
            while(StackEmpty(&obj->pushst) > 0)
            {
                StackPush(&obj->popst, StackTop(&obj->pushst));
                StackPop(&obj->pushst);
            }
        }
        return StackTop(&obj->popst);
    }
    int myQueuePop(MyQueue* obj) 
    {
        int front = myQueuePeek(obj);
        StackPop(&obj->popst);
        return front;
    }
    bool myQueueEmpty(MyQueue* obj) 
    {
        int ret1, ret2;
        if(StackEmpty(&obj->pushst) == 0)
        ret1 = 0;
        else
        ret1 = 1;
        if(StackEmpty(&obj->popst) == 0)
        ret2 = 0;
        else
        ret2 = 1;
        if(ret1 == 0 && ret2 == 0)
        return true;
        else
        return false; 
    }
    void myQueueFree(MyQueue* obj) 
    {
        StackDestroy(&obj->pushst);
        StackDestroy(&obj->popst);
        free(obj);
    }

免责声明
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明。
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所
提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何
损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在
转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并白负版权等法律责任。

手机扫描二维码访问

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1471人围观)

还没有评论,来说两句吧...

目录[+]