队列的实现—超详细
文章目录
- 队列的实现---超详细
- 一、队列的模型
- 二、代码实现以及测试用例
- ①队列初始化
- ②入队
- ③出队
- ④输出队头
- ⑤输出队尾
- ⑥判断队列是否为空
- ⑦队列的长度
- ⑧队列的销毁
- ⑨测试用例
一、队列的模型
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。
所以我们可以思考一下,这种结构如果用顺序表来实现一定是十分麻烦的,因为顺序表的头删的时间复杂度是O(N)。所以我们应该要采取链表来实现队列结构。
至于是单链表还是带头双向循环链表,其实都是无伤大雅的,在这里我们选择单链表。
结构:
typedef int SDataType;typedef struct Queue
{struct Queue* next;SDataType val;
}QU;
其实这样我们已经把单链表构建出来了,但是请大家思考两个问题:
如果是入队时,难道我每次入队都需要去找一次尾吗?
如果是计算队列长度时,这是一个不在连续空间存储的数据结构,我们如果简单的计算出长度呢?
所以我们可以再次引入一个结构体,将这个链表的头、尾和长度都计算出来。
typedef struct queue
{QU* phead;QU* tail;int size;
}q;
二、代码实现以及测试用例
①队列初始化
void QIni(q* p)
{assert(p);p->phead = p->tail = NULL;p->size = 0;
}
②入队
void QPush(q* p, QDataType x)
{assert(p);QU* newnode = (QU*)malloc(sizeof(QU));if (newnode == NULL){perror("malloc");exit(-1);}newnode->next = NULL;newnode->val = x;if (p->tail == NULL){p->phead = p->tail = newnode;}else{p->tail->next = newnode;p->tail = newnode;}p->size++;
}
③出队
void QPop(q* p)
{assert(p);assert(p->phead);QU* tmp = p->phead->next;free(p->phead);p->phead = tmp;if (p->phead == NULL){p->tail = NULL;//很关键}p->size--;
}
④输出队头
QDataType QFront(q* p)
{assert(p);assert(p->phead);return p->phead->val;
}
⑤输出队尾
QDataType QBack(q* p)
{assert(p);assert(p->tail);return p->tail->val;
}
⑥判断队列是否为空
bool QEmpty(q* p)
{assert(p);return p->phead == NULL;
}
⑦队列的长度
int QSize(q* p)
{assert(p);return p->size;
}
⑧队列的销毁
void QDestroy(q* p)
{assert(p);//assert(p->phead);QU* tmp = p->phead;while (tmp){QU* tmp2 = tmp->next;free(tmp);tmp = tmp2;}p->phead = p->tail = NULL;p->size = 0;
}
⑨测试用例
void test2()
{q p;QIni(&p);QPush(&p, 1);QPush(&p, 2);QPush(&p, 3);QPush(&p, 4);QPush(&p, 5);while (!QEmpty(&p)){printf("%d ", QFront(&p));QPop(&p);}printf("\n");QDestroy(&p);
}int main()
{test2();return 0;
}