隊列:只允許在一端進行插入數據操作,在另一端進行刪除數據操作的特殊線性表
進行插入操作的一端稱爲隊尾(入隊列)
進行刪除操作的一端稱爲隊頭(出隊列)
隊列具有先進先出(FIFO)的特性
隊列分類:
1.順序隊列
元素刪除:
方式1:隊頭不動,出隊列時隊頭後的所有元素向前移動
缺陷:操作時如果出隊列比較多,要搬移大量元素
方式2:隊頭移動,出隊列時隊頭向後移動一個位置
缺陷:容易造成隊列假溢出假溢出:順序隊列因多次入隊列和出隊列操作後出現的尚有存儲空間但不能再進行入隊列操作的溢出
真溢出:順序隊列最大存儲空間已經存滿而又要求進行入隊列操作所引起的溢出
2.循環隊列(解決了假溢出問題)
常考面試題:循環隊列如何判斷隊列空和滿呢?
a.少用一個存儲單元
b.設置一個標記位
c.設置一個計數器
3.鏈式隊列(類似於鏈表)
4.優先級隊列(帶有優先級的隊列稱爲優先級隊列 )
隊列具有先進先出的特性,即最先進入隊列的元素將被最先出隊列,有時也需要把進入隊列中的元素分優先級(比如線程調度),出隊列時首先選擇優先級最高的元素出隊列(優先級高先被服務VIP),對於優先級相同的元素則按照先進先出的原則出隊列,即優先級隊列的出隊列操作不是直接將對頭元素出隊列,而是把隊列中優先級最高的元素出隊列。
隊列的應用:
生產者消費者模型
消息隊列
排隊現象
網絡數據傳輸
大家熟知的linux管道
/****************順序隊列******************/
#include <stdio.h>
#include <assert.h>
#include <sydlib.h>
#define MAX_SIZE 10
typedef int DataType;
typedef struct Queue
{
DataType _array[MAX_SIZE];
int _front;
int _back;
int _count;
}Queue;
void QueueInit(Queue* q);
void QueuePush(Queue* q,DataType data);
void QueuePop(Queue* q);
int QueueEmpty(Queue* q);
int QueueSize(Queue* q);
DataType QueueFront(Queue* q);
DataType QueueBack(Queue* q);
void QueueInit(Queue* q)
{
assert(q);
q->_front = q->_back = 0;
q->_count = 0;
}
void QueuePush(Queue* q, DataType data)
{
assert(q);
if (q->_count == MAX_SIZE)
return;
q->_array[q->_back++] = data;
if (q->_back == MAX_SIZE)
q->_back = 0;
q->_count++;
}
void QueuePop(Queue* q)
{
assert(q);
if (QueueEmpty(q))
return;
++(q->_front);
if (q->_front == MAX_SIZE)
q->_front = 0;
q->_count--;
}
int QueueEmpty(Queue* q)
{
assert(q);
return 0 == q->_count;
}
int QueueSize(Queue* q)
{
return q->_count;
}
DataType QueueFront(Queue* q)
{
return q->_array[q->_front];
}
DataType QueueBack(Queue* q)
{
if (0 != q->_back)
return q->_array[q->_back - 1];
else
{
return q->_array[MAX_SIZE - 1];
}
}
void TestQueue()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
QueuePush(&q, 6);
QueuePush(&q, 7);
QueuePush(&q, 8);
QueuePush(&q, 9);
QueuePush(&q, 10);
printf("size = %d\n", QueueSize(&q));
printf("front = %d\n", QueueFront(&q));
printf("back = %d\n", QueueBack(&q));
QueuePop(&q);
QueuePop(&q);
QueuePop(&q);
printf("size = %d\n", QueueSize(&q));
printf("front = %d\n", QueueFront(&q));
printf("back = %d\n", QueueBack(&q));
}
int main()
{
TestQueue();
return 0;
}
/******************鏈式隊列*******************/
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <stdlib.h>
typedef int DataType;
typedef struct Node
{
struct Node* _pNext;
DataType _data;
}Node ,*PNode;
typedef struct Queue
{
PNode _pHead;
PNode _pTail;
}Queue;
void QueueInit(Queue* q);
void QueuePush(Queue* q, DataType data);
void QueuePop(Queue* q);
int QueueEmpty(Queue* q);
int QueueSize(Queue* q);
PNode QueueFront(Queue* q);
PNode QueueBack(Queue* q);
PNode BuyNode(DataType data);
void QueueDestroy(Queue* q);
void QueueInit(Queue* q)
{
assert(q);
q->_pHead = NULL;
q->_pTail = NULL;
}
void QueuePush(Queue* q, DataType data)
{
assert(q);
if(NULL == q->_pHead)
{
q->_pHead = q->_pTail = BuyNode(data);
}
else
{
q->_pTail->_pNext = BuyNode(data);
q->_pTail = q->_pTail->_pNext;
}
}
PNode BuyNode(DataType data)
{
PNode pNewNode = (PNode)malloc(sizeof(Node));
assert(pNewNode);
pNewNode->_data = data;
pNewNode->_pNext = NULL;
return pNewNode;
}
void QueuePop(Queue* q)
{
assert(q);
if (NULL == q->_pHead)
{
return;
}
else if (q->_pHead == q->_pTail)
{
free(q->_pHead);
q->_pHead = q->_pTail = NULL;
}
else
{
//PNode pPreTail = q->_pHead;
//while (pPreTail->_pNext != q->_pTail)
//{
// pPreTail = pPreTail->_pNext;
//}
//free(q->_pTail);
//q->_pTail = pPreTail;
PNode pDel = q->_pHead;
q->_pHead = pDel->_pNext;;
free(pDel);
}
}
int QueueEmpty(Queue* q)
{
assert(q);
if (NULL == q->_pHead)
return 1;
return 0;
}
int QueueSize(Queue* q)
{
assert(q);
int count = 0;
PNode pCur;
pCur = q->_pHead;
while (pCur)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
PNode QueueFront(Queue* q)
{
assert(q && q->_pHead);
return q->_pHead;
}
PNode QueueBack(Queue* q)
{
assert(q && q->_pHead);
return q->_pTail;
}
void QueueDestroy(Queue* q)
{
PNode pCur = q->_pHead;
while (pCur)
{
q->_pHead = pCur->_pNext;
free(pCur);
pCur = q->_pHead;
}
q->_pTail == NULL;
}
void TestQueue()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
printf("size = %d\n", QueueSize(&q));
printf("front = %d\n", QueueFront(&q));
printf("back = %d\n", QueueBack(&q));
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
printf("size = %d\n", QueueSize(&q));
printf("front = %d\n", QueueFront(&q));
printf("back = %d\n", QueueBack(&q));
QueuePop(&q);
QueuePop(&q);
QueuePop(&q);
printf("size = %d\n", QueueSize(&q));
printf("front = %d\n", QueueFront(&q));
printf("back = %d\n", QueueBack(&q));
QueueDestroy(&q);
}
int main()
{
TestQueue();
return 0;
}
帶頭節點的雙向鏈表:
https://blog.csdn.net/Romantic_C/article/details/79991268
帶頭節點的單鏈表:
https://blog.csdn.net/Romantic_C/article/details/79919836
鏈表面試題:
https://blog.csdn.net/Romantic_C/article/details/81395660
棧的基本操作:
https://blog.csdn.net/Romantic_C/article/details/81395874