数据结构——队列
2016-06-04 00:00
627 查看
摘要: 队列
一、队列概念
队列时一种特殊的线性表,只允许在表的前端进行删除操作,而在表的后端进行插入操作,队列具有先进先出的特点。
队列的操作很简单,主要有以下几种常见的操作:
(1)初始化队列:创建一个队列
(2)进队列:将一个元素添加到队尾
(3)出队列:将队头元素取出,同时删除该元素,使下一个元素成为对头
(4)获取队列第一元素:将队头元素取出,不删除该元素
(5)获取队列长度:根据队头和队尾计算出队列中元素的数量
二、顺序队列实现
将队列用顺序存储方式保存时,在内存中申请一片区域用来保存元素,当第一个元素A进入队列时,因是空列队,因此元素A将排在队头,接着B、C、D顺次进入队列,就得到如图所示的队列。其中head指向队头,以指示队头元素出队操作,tail指向队尾,以指示新增元素进入队列。如下图所示:
执行一次出队操作,元素A将出队,这时第2个元素B将成为队头,head指针将指向该元素如果要将元素E入队,则是将其放入tail指针指向元素的后一个位置(如下图为5的单元),并使tail指针指向序号为5的单元。
(1)定义顺序队列的结构
(2)初始化队列
(3)释放队列
(4)获取队列状态
(5)入队操作
(6)出队操作
(7)获取队头元素
三、循环队列
由于每次出队后,队头的指针都向后移动,这时候就会出现一个问题,就是假溢出。如下图所示:
tail已指向队尾,这时进行入队操作时,虽然前面还有空位置,但仍然显示队列已满。为了解决这个问题,就提出了循环队列。
循环队列就是将队列的首尾相连构成一个环形区域,当在第n个位置进行元素的入队操作后,下一个地址就翻转为1
循环队列结构图:
在循环队列中,主要需要计算队尾tail和队头head的序号
以入队操作为例:
1、将队尾序号加1,即tail=tail+1
2、若tail=n+1,则tail=1
其实前2步,可以使用表达式tail=(tail+1)%n
3、若head=tail,即队尾和队头重合了,表示队列已满提示队列溢出
4、若未溢出,将元素入队即可
(1)定义循环队列的结构
(2)初始化队列
(3)释放队列
(4)获取队列状态
(5)入队操作
(6)出队操作
(7)获取队头元素
一、队列概念
队列时一种特殊的线性表,只允许在表的前端进行删除操作,而在表的后端进行插入操作,队列具有先进先出的特点。
队列的操作很简单,主要有以下几种常见的操作:
(1)初始化队列:创建一个队列
(2)进队列:将一个元素添加到队尾
(3)出队列:将队头元素取出,同时删除该元素,使下一个元素成为对头
(4)获取队列第一元素:将队头元素取出,不删除该元素
(5)获取队列长度:根据队头和队尾计算出队列中元素的数量
二、顺序队列实现
将队列用顺序存储方式保存时,在内存中申请一片区域用来保存元素,当第一个元素A进入队列时,因是空列队,因此元素A将排在队头,接着B、C、D顺次进入队列,就得到如图所示的队列。其中head指向队头,以指示队头元素出队操作,tail指向队尾,以指示新增元素进入队列。如下图所示:
执行一次出队操作,元素A将出队,这时第2个元素B将成为队头,head指针将指向该元素如果要将元素E入队,则是将其放入tail指针指向元素的后一个位置(如下图为5的单元),并使tail指针指向序号为5的单元。
(1)定义顺序队列的结构
[code=language-cpp]#define QUEUEMAX 15 typedef struct{ DATA data[QUEUEMAX]; int head; int tail; } SeqQueue;
(2)初始化队列
[code=language-cpp]SeqQueue *SeqQueueInit() { SeqQueue *q; if (q=(SeqQueue *)malloc(sizeof(SeqQueue))) { q->head = 0; q->tail = 0; return q; } return NULL; }
(3)释放队列
[code=language-cpp]void SeqQueueFree(SeqQueue *q) { if (q) free(q); }
(4)获取队列状态
[code=language-cpp]/* *判断队列是否为空 */ int SeqQueueIsEmpty(SeqQueue *q) { return (q->head == q->tail); } /* *判断队列是否已满 */ int SeqQueueIsFull(SeqQueue *q) { return (q->tail == QUEUEMAX); } /* *获取队列的长度 */ int SeqQueueLen(SeqQueue *q) { return (q->tail - q->head); }
(5)入队操作
[code=language-cpp]int SeqQueueIn(SeqQueue *q, DATA data) { if (SeqQueueIsFull(q)) { printf("队列已满!\n"); return 0; } q->data[q->tail++] = data; return 1; }
(6)出队操作
[code=language-cpp]DATA *SeqQueueOut(SeqQueue *q) { if (SeqQueueIsEmpty(q)) { printf("队列已空!\n"); return NULL; } return &(q->data[q->head++]); }
(7)获取队头元素
[code=language-cpp]DATA *SeqQueuePeek(SeqQueue *q) { if (SeqQueueIsEmpty(q)) { printf("队列已空!\n"); return NULL; } return &(q->data[q->head]); }
三、循环队列
由于每次出队后,队头的指针都向后移动,这时候就会出现一个问题,就是假溢出。如下图所示:
tail已指向队尾,这时进行入队操作时,虽然前面还有空位置,但仍然显示队列已满。为了解决这个问题,就提出了循环队列。
循环队列就是将队列的首尾相连构成一个环形区域,当在第n个位置进行元素的入队操作后,下一个地址就翻转为1
循环队列结构图:
在循环队列中,主要需要计算队尾tail和队头head的序号
以入队操作为例:
1、将队尾序号加1,即tail=tail+1
2、若tail=n+1,则tail=1
其实前2步,可以使用表达式tail=(tail+1)%n
3、若head=tail,即队尾和队头重合了,表示队列已满提示队列溢出
4、若未溢出,将元素入队即可
(1)定义循环队列的结构
[code=language-cpp]#define QUEUEMAX 15 typedef struct{ DATA data[QUEUEMAX]; int head; int tail; } CycQueue;
(2)初始化队列
[code=language-cpp]CycQueue *CycQueueInit() { CycQueue *q; if (q=(CycQueue *)malloc(sizeof(CycQueue))) { q->head = 0; q->tail = 0; return q; } return NULL; }
(3)释放队列
[code=language-cpp]void CycQueueFree(CycQueue *q) { if (q) free(q); }
(4)获取队列状态
[code=language-cpp]/* *判断队列是否为空 */ int CycQueueIsEmpty(CycQueue *q) { return (q->head == q->tail); } /* *判断队列是否已满 */ int CycQueueIsFull(CycQueue *q) { return ((q->tail+1)%QUEUEMAX == q->head); } /* *获取队列的长度 */ int CycQueueLen(CycQueue *q) { int n; n = q->tail - q->head; if (n < 0) { n = QUEUEMAX + n; } return n; }
(5)入队操作
[code=language-cpp]int CycQueueIn(CycQueue *q, DATA data) { if (CycQueueIsFull(q)) { printf("队列已满!\n"); return 0; } q->tail = (q->tail+1)%QUEUEMAX; q->data[q->tail] = data; return 1; }
(6)出队操作
[code=language-cpp]DATA *CycQueueOut(CycQueue *q) { int head; if (CycQueueIsEmpty(q)) { printf("队列已空!\n"); return NULL; } head = q->head; q->head = (q->head +1)%QUEUEMAX; return &(q->data[head]); }
(7)获取队头元素
[code=language-cpp]DATA *CycQueuePeek(CycQueue *q) { if (CycQueueIsEmpty(q)) { printf("队列已空!\n"); return NULL; } return &(q->data[q->head]); }
相关文章推荐
- Java数据结构源码分析-前言
- noi2015 d1t2 软件包管理器
- APUE 读书笔记 -----孤儿进程与僵尸进程[总结] +数据结构+C
- java数据结构之链式队列的实现
- 哈希表(HashTable)
- java数据结构之线性队列的实现
- 并查集(UnionSet)
- 基于树状数组的高效轮盘赌算法
- ACM算法分类
- 数据结构与算法分析(7)表、栈和队列(二)
- 数据结构与算法2016-06-02
- 数据结构与算法2016-06-03
- 【数据结构】HashSet原理及实现学习总结
- Linux中存储管理使用的数据结构和函数
- 【数据结构】搜索二叉树的(递归与非递归)实现,包括:增Insert,删Remove,查Find
- 数据结构--堆栈
- 排序算法(2)-快速排序
- codeforces-3A-Shortest path of the king( 棋盘最短路径 + 贪心 )
- 【数据结构】HashMap原理及实现学习总结
- 树和二叉树自测题