基本数据结构之队列

一、基本数据结构之队列

       队列作为计算机系统一种非常常见的数据结构被大家所熟知。同堆栈一样,队列也是有插入和删除只能在限定段的线性表。

         队列是一种FIFO(First In First Out)的线性表。具体通常用链表或数组来实现。队列只允许在后端(rear)进行插入操作,在前段(front)进行删除操作。

         队列的操作方式和堆栈类似,唯一的区别就是队列只允许在后端进行数据添加。

         队列通常能够解决一下问题:

         1)解决主机与外部设备之间速度不匹配的问题。设置一个缓冲队列。

         2)解决因多用户引起的资源竞争问题。系统按照请求时间设置一个请求队列(还可以给每个任务加一个优先级,就成为了优先级队列)。

         下面介绍队列的几种常见的实现方式:

        

  1. /* 
  2. 单链队列的实现:单链队列使用链表作为基本数据结构,所以不存在溢出问题(除非主存耗完),队列长度也没有限制。 
  3. 但是插入和读取的时间成本较高。 
  4. */  
  5. /* 单链队列--队列的链式存储结构 */  
  6. typedef struct QNode {  
  7.   QElemType data;  
  8.   struct QNode *next;  
  9. }QNode, *QueuePtr;  
  10.   
  11. typedef struc {  
  12.   QueuePtr front, rear; /* 队头队尾指针 */  
  13. }LinkQueue;  
  14.   
  15. /* 链队列的基本操作(9个) */  
  16.   
  17. /* 构造一个空队列 */  
  18. void InitQueue(LinkQueue *Q)  
  19. {  
  20.   Q->font = Q->rear = malloc(sizeof(QNode);  
  21.   if(!Q->font)  
  22.     exit(1);  
  23.   Q->front->next = NULL;  
  24. }  
  25.   
  26. /* 销毁队列Q */  
  27. void DestroyQueue(LinkQueue *Q)  
  28. {  
  29.   while(Q->front) {  
  30.     Q->rear = Q->front->next;  
  31.     free(Q->front);  
  32.     Q->front = Q->rear;  
  33.   }  
  34. }  
  35.   
  36. /* 清空队列Q */  
  37. void ClearQueue(LinkQueue *Q)  
  38. {  
  39.   QueuePtr p,q;  
  40.   Q->rear = Q->front;  
  41.   p = Q->front->next;  
  42.   Q->front->next = NULL;  
  43.   while(p) {  
  44.     q = p;  
  45.     p = q->next;  
  46.     free(q);  
  47.   }  
  48. }  
  49.   
  50. /* 若Q为空队列,则返回TRUE,否则返回FALSE */  
  51. Status QueueEmpty(LinkQueue Q)  
  52. {  
  53.   if(Q->font->next == NULL)  
  54.     return TRUE;  
  55.   else  
  56.     return FALSE;  
  57. }  
  58.   
  59. /* 求队列的长度 */  
  60. int QueueLength(LinkQueue Q)  
  61. {  
  62.   int i = 0;  
  63.   QueuePtr p;  
  64.   p = Q.front;  
  65.   while(Q.rear != p) {  
  66.     i++;  
  67.     p = p->next;  
  68.   }  
  69.   return i;  
  70. }  
  71.   
  72. /* 若队列不为空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */  
  73. Status GetHead_Q(LinkQueue Q, QElemType *e)  
  74. {  
  75.   QueuePtr p;  
  76.   if(Q.front == Q.rear)  
  77.     return ERROR;  
  78.   p = Q.front->next;  
  79.   *e = p->data;  
  80.   return OK;  
  81. }  
  82.   
  83. /* 插入e作为Q新的队尾元素 */  
  84. void EnQueue(LinkQueue *Q, QElemType e)  
  85. {  
  86.   QueuePtr p = (QueuePtr)malloc(sizeof(QNode));  
  87.   if(!p)  
  88.     exit(1);  
  89.   p->data = e;  
  90.   p->next = NULL;  
  91.   Q->rear->next = p;  
  92.   Q->rear = p;  
  93. }  
  94.   
  95. /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */  
  96. Status DeQueue(LinkQueue *Q, QElemType *e)  
  97. {  
  98.   QueuePtr p;  
  99.   if(Q->front == Q->rear)  
  100.     return ERROR;  
  101.   p = Q->front; /* 指向头结点 */  
  102.   *e = p->data;  
  103.   Q->front = p->next;  
  104.   if(Q->rear == p)  
  105.     Q->rear = Q->front;  
  106.   free(p);  
  107.   return OK;  
  108. }  
  109.   
  110. /* 从队头到队尾依次对队列Q中每个元素调用函数vi() */  
  111. void QueueTraverse(LinkQueue Q, (void)(*visit)(QElemType))  
  112. {  
  113.   QueuePtr p;  
  114.   p = Q.front->next;  
  115.   while(p) {  
  116.     visit(p->data);  
  117.     p = p->next;  
  118.   }  
  119.   printf("\n");  
  120. }  
  121. -----------------------------我就是分割线啦---------------------------  
  122. 循环队列  
  123. 循环队列可以更简单防止伪溢出的发生,但队列大小是固定的。  
  124. /* 队列的顺序存储结构(循环队列) */  
  125. #define MAX_QSIZE 5 /* 最大队列长度加1*/   
  126. typedef struct {  
  127.   QElemType *base;/* 初始化的动态分配存储空间 */  
  128.   int front;/* 头指针,若队列不空,指向队列头元素 */  
  129.   int rear;/* 尾指针,若队列不空,指向队列尾元素的下一个位置 */  
  130. }SqQueue;  
  131.   
  132. 循环队列的基本操作(9个)  
  133. /* 构造一个空队列 */  
  134. void InitQueue(SqQueue *Q)  
  135. {  
  136.   Q->base = malloc(MAX_QSIZE * sizeof(QElemType));  
  137.   if(!Q->base)  
  138.     exit(1);  
  139.   Q->front = Q->rear = 0;  
  140. }  
  141.   
  142. /* 销毁队列Q,Q不再存在 */  
  143. void DestroyQueue(SqQueue *Q)  
  144. {  
  145.   if(Q->base)  
  146.     free(Q->base);  
  147.   Q->base = NULL;  
  148.   Q->front = Q->rear = 0;  
  149. }  
  150.   
  151. /* 将Q清为空队列 */  
  152. void ClearQueue(SeQueue *Q)  
  153. {  
  154.   Q->front = Q->rear = 0;  
  155. }  
  156.   
  157. /* 若队列Q为空队列,则返回TRUE;否则返回FALSE */  
  158. Status QueueEmpty(SqQueue Q)  
  159. {  
  160.   if(Q.front == Q.rear)  
  161.     return TRUE:  
  162.   else  
  163.     return FALSE:  
  164. }  
  165.   
  166. /* 返回Q的元素个数,即队列的长度 */  
  167. int QueueLength(SeqQueue Q)  
  168. {  
  169.   return (Q.rear - Q.front + MAX_QSIZE) % MAX_QSIZE;  
  170. }  
  171.   
  172. /* 若队列不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR */  
  173. Status GetHead(SqQueue Q, QElemType *e)  
  174. {  
  175.   if(Q.front == Q.rear)  
  176.     return ERROR; // 队列为空   
  177.   *e = Q.base[Q.front];  
  178.   return OK;  
  179. }  
  180.   
  181. /* 插入元素e为Q的新的队尾元素 */  
  182. Status EnQueue (SeQueue *Q, QElemType *e)  
  183. {  
  184.   if((Q->rear+1)% MAX_QSIZE == Q->front) // 队列满   
  185.     return ERROR;  
  186.   Q->base[Q->rear] = e;  
  187.   Q->rear = (Q->rear + 1) % MAX_QSIZE;  
  188.   return OK;  
  189. }  
  190.   
  191. /* 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;否则返回ERROR */  
  192. Status DeQueue(SqQueue *Q, ElemType *e)  
  193. {  
  194.   if(Q->front == Q->rear) // 队列空   
  195.     return ERROR;  
  196.   *e = Q->base[Q->front];  
  197.   Q->front = (Q->front+1) % MAX_QSIZE;  
  198.   return OK;  
  199. }  
  200.   
  201. /* 从队头到队尾依次对队列Q中每个元素调用函数visit() */  
  202. void QueueTraverse(SqQueue Q, void(*visit)(QElemType))  
  203. {  
  204.   int i ;  
  205.   i = Q.front;  
  206.   while(i!=Q.rear)  
  207.   {  
  208.     visit(Q.base[i];  
  209.     i = (i+1)%MAX_QSIZE;  
  210.   }  
  211.   printf("\n");  
  212. }  
  213. ---------------------------------------------我还是分割线---------------------  
  214. #include<stdio.h>   
  215. #include<stdlib.h>   
  216. /*阵列结构,说白了就是用数组存储元素 */  
  217. struct Queue  
  218. {  
  219.   int Array[10];//阵列空间大小   
  220.   int head;//前端(front)   
  221.   int tail;//后端(rear)   
  222.   int length;//当前队列长度,并且使用此成员判断满和空   
  223. };  
  224.   
  225. /*元素插入队列*/  
  226. void EnQueue(struct Queue *Queue1,int x)  
  227. {  
  228.   Queue1->Array[Queue1->tail]=x;  
  229.   if(Queue1->tail+1==10)//Queue1->length 改空间大小为10   
  230.   {  
  231.     Queue1->tail=0;//1改为0   
  232.   }  
  233.   else  
  234.   {  
  235.     Queue1->tail=Queue1->tail+1;  
  236.   }  
  237.   Queue1->length=Queue1->length+1;//当前个数增1   
  238. }  
  239.   
  240. /*删除队列元素*/  
  241. int DeQueue(struct Queue *Queue1)  
  242. {  
  243.   int x=Queue1->Array[Queue1->head];  
  244.   if(Queue1->head+1==10)//空間大小10   
  245.   {  
  246.     Queue1->head=0;  
  247.   }  
  248.   else  
  249.   {  
  250.     Queue1->head=Queue1->head+1;  
  251.   }  
  252.   Queue1->length=Queue1->length-1;//移出后減少1   
  253.   return x;  
  254. }  
  255. /*基本操作*/  
  256. int main()  
  257. {  
  258.   struct Queue *Queue1=malloc(sizeof(struct Queue));  
  259.   Queue1->length=0;  
  260.   Queue1->head=0;  
  261.   Queue1->tail=0;  
  262.   EnQueue(Queue1,5);//將5放入   
  263.   EnQueue(Queue1,8);//將8放入   
  264.   EnQueue(Queue1,3);//將3放入   
  265.   EnQueue(Queue1,2);//將2放入   
  266.   printf("%d ",DeQueue(Queue1));  
  267.   printf("%d ",DeQueue(Queue1));  
  268.   printf("%d ",DeQueue(Queue1));  
  269.   system("pause");  
  270. }  
  271.   
  272. Note:以上便是队列的基本介绍,包括队列的概念以及应用,最后介绍了,队列的几种常见实现方式。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

minyuanxiani

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值