网站设计总结wordpress开启xml-rpc
目录
1.什么是队列
2.如何实现队列
3.队列的实现
Queue.h中接口总览
具体实现
结构的定义
初始化
销毁
入队列
出队列
取队头元素
取队尾元素
判断是否为空
获取队列的大小
4.完整代码附录
Queue.h
Queue.c
1.什么是队列
队列是一种特殊的线性表,只允许在一端进行数据的插入操作,在另一端进行数据的删除操作。队列中的数据元素必须满足先进先出的性质。
- 插入数据的操作叫做入队列,插入数据的一端叫做队尾。
 - 删除数据的操作叫做出队列,删除数据的一端叫做队头。
 
队列逻辑结构如下图所示:

2.如何实现队列
要想实现队列,必须满足队列的要求,也就是以下两点:
- a、在一端插入数据,在另一端删除数据。
 - b、满足先进先出的性质。
 
所以,我们使用数组(顺序表)或者 链表实现,那么使用哪种结构来实现更好呢?
我们可以对比一下:
| 数组(顺序表) | 链表(单链表) | |
| 头插效率 | O(N) | O(1) | 
| 头删效率 | O(N) | O(1) | 
| 尾插效率 | O(1) | O(N) | 
| 尾删效率 | O(1) | O(N) | 
貌似使用数组和链表实现都是一样的,在一端进行插入or删除的效率是O(1),在另一端进行删除or插入的效率就是O(N) 。
但是我们可以优化一下链表,链表在尾部进行插入or删除的效率之所以是O(N),是因为需要遍历链表找尾结点,但是,如果我们能够直接找到尾结点,那么链表在尾部进行插入和删除的效率不就都是O(1)了吗?
所以,我们可以使用两个指针head和tail分别指向链表的头结点和尾结点。这样一来,进行尾插时,直接就能找到尾结点,所以尾插的效率也是O(1)。

所以我们实现的队列的最终形态如下:

3.队列的实现
队列的实现,我们主要实现Queue.h和Queue.c文件即可,Queue.h文件中存放声明,Queue.c文件中存放定义。
Queue.h中接口总览

具体实现
结构的定义
实现队列结构的时候,由于我们采用的是链表来实现队列,所以我们需要定义一个个的结点;前面我们分析可知,head指向头结点,tail指向尾结点,可以使得入队列和出队列的时间复杂度都为O(1),所以我们需要管理好head指针和tail指针,这里我们也采用结构体来管理。


初始化
初始化队列只需要初始化 struct Queue 结构体对象中的成员即可。
- head和tail指针都初始化为空。
 - size初始化为0。
 
 
销毁
销毁队列的时候,首先需要将节点全部释放,然后将head和tail指针置空,并将size置为0。

入队列
入队列的时候要区分两种情况:
- 入队列的结点是第一个结点,此时让head和tail同时指向该结点即可。
 - 入队列的结点不是第一个结点,此时让新结点连接到尾结点的后面即可。
 - 最后记得将size++。
 


出队列
出队列的时候要区分三种情况:
- 队列不能为空。
 - 只有一个结点的情况。此时,释放结点之后,将head和tail指针置空。
 - 不止一个结点的情况。此时,记录head指向的结点,将head后移,然后释放记录的节点。
 
注意:最后记得将size--。

  
取队头元素
直接返回head指向的结点的数据即可。

取队尾元素
直接返回tail指向的结点的数据即可。

判断是否为空
当队列为空时,head和tail都指向空,所以直接判断head或者tail是否为空都可以。

获取队列的大小
直接返回struct Queue结构体类型对象中的size即可。

4.完整代码附录
Queue.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int QDataType;
typedef struct QueueNode    // 定义结点 
{struct QueueNode* next; // 存储下一个结点的地址 QDataType data;         // 存储数据 
}QNode;typedef struct Queue        // 定义队列 
{QNode* head;            // 指向头结点 QNode* tail;            // 指向尾结点 int size;               // 记录队列的大小 
}Que;// 初始化 
void QueueInit(Que* pq);
// 销毁 
void QueueDestroy(Que* pq);
// 入队列 
void QueuePush(Que* pq, QDataType x);
// 出队列 
void QueuePop(Que* pq);
// 取队头元素 
QDataType QueueFront(Que* pq);
// 取队尾元素 
QDataType QueueBack(Que* pq);
// 判断是否为空 
bool QueueEmpty(Que* pq);
// 获取队列的大小 
int QueueSize(Que* pq); 
Queue.c
// 初始化队列 
void QueueInit(Que* pq)
{assert(pq);pq->head = pq->tail = NULL;pq->size = 0;
}// 销毁队列 
void QueueDestroy(Que* pq)
{assert(pq);QNode* cur = pq->head;while (cur)             // 遍历释放结点 {QNode* next = cur->next;free(cur);cur = next;}pq->head = pq->tail = NULL;pq->size = 0;
}// 入队列 
void QueuePush(Que* pq, QDataType x)
{assert(pq); // pq指针不能为空 QNode* newnode = (QNode*)malloc(sizeof(QNode)); // 申请新结点 if (newnode == NULL){perror("malloc fail");exit(-1);}// 初始化新结点中的成员 newnode->data = x;newnode->next = NULL;if (pq->tail == NULL)  // 入队列的结点是第一个结点 {pq->head = pq->tail = newnode;}else                   // 入队列的结点不是第一个结点 {pq->tail->next = newnode;pq->tail = newnode;}pq->size++;
}// 出队列
void QueuePop(Que* pq)
{assert(pq);assert(!QueueEmpty(pq));      // 出队列的时候,队列不能为空 if (pq->head->next == NULL)   // 只有一个结点的情况 {free(pq->head);pq->head = pq->tail = NULL;}else                          // 不止一个结点的情况 {QNode* next = pq->head->next;free(pq->head);pq->head = next;}pq->size--;
}// 取队头元素 
QDataType QueueFront(Que* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}// 取队尾元素 
QDataType QueueBack(Que* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail->data;
}// 判空 
bool QueueEmpty(Que* pq)
{assert(pq);return pq->head == NULL;
}// 获取队列的大小 
int QueueSize(Que* pq)
{assert(pq);return pq->size;
}
 
 
 
