zoukankan      html  css  js  c++  java
  • 浅谈数据结构之链队列(六)

      前面我们讲了队列的顺序存储结构,现在我们来看看队列的链式存储结构。队列的链式存储其实就是线性表的单链表结构,只不过它是尾进头出而已,通常我们把它简称为链队列。为了操作上的方便,我们将队头指针front指向链队列的头结点,而队尾指针rear则指向终端结点。注意:当队列为空时,指针front和rear都指向头结点。

      在这里,我们再介绍一下循环队列。循环队列是为了避免数组插入与删除数据时需要移动数据而引入的,我们一般把队列的这种头尾相接的顺序存储结构称为循环队列。对于循环队列和链队列相比较来说,循环队列使得队头和队尾在数组中循环变化,解决了移动数据时所需要的时间损耗,因此它的时间复杂度为0(1);而链队列事先并不需要预估队列的长度,也没有存储元素个数和空间浪费的问题,所以在空间上,链队列更加灵活,方便。

      链队列的入队操作其实就是在链表尾插入结点,而出队操作则是将头结点的后继结点出队,同时将头结点的后继改为它后面的结点;若链表除头结点外只剩下一个元素,则需将指针rear指向头结点,具体操作源程序代码如下所示:

      1 #include <stdio.h>
      2 #include <stdlib.h> 
      3 #include <math.h>
      4 
      5 #define OK 1
      6 #define ERROR 0
      7 #define TRUE 1
      8 #define FALSE 0
      9 
     10 #define MAXSIZE 20            /* 存储空间初始分配量 */
     11 
     12 typedef int Status; 
     13 typedef int QElemType;        /* QElemType类型根据实际情况而定,这里假设为int */
     14 
     15 typedef struct QNode          /* 结点结构 */
     16 {
     17    QElemType data;
     18    struct QNode *next;
     19 }QNode,*QueuePtr;
     20 
     21 typedef struct                /* 队列的链表结构 */
     22 {
     23    QueuePtr front,rear;       /* 队头、队尾指针 */
     24 }LinkQueue;
     25 
     26 Status visit(QElemType c)
     27 {
     28     printf("%d ",c);
     29     return OK;
     30 }
     31 
     32 /* 构造一个空队列Q */
     33 Status InitQueue(LinkQueue *Q)
     34 { 
     35     Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
     36     if(!Q->front)
     37         exit(OVERFLOW);
     38     Q->front->next=NULL;
     39     return OK;
     40 }
     41 
     42 /* 将Q清为空队列 */
     43 Status ClearQueue(LinkQueue *Q)
     44 {
     45     QueuePtr p,q;
     46     Q->rear=Q->front;
     47     p=Q->front->next;
     48     Q->front->next=NULL;
     49     while(p)
     50     {
     51         q=p;
     52         p=p->next;
     53         free(q);
     54     }
     55     return OK;
     56 }
     57 
     58 /* 求队列的长度 */
     59 int QueueLength(LinkQueue Q)
     60 { 
     61     int i=0;
     62     QueuePtr p;
     63     p=Q.front;
     64     while(Q.rear!=p)
     65     {
     66         i++;
     67         p=p->next;
     68     }
     69     return i;
     70 }
     71 
     72 /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */
     73 Status GetHead(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 
     84 /* 插入元素e为Q的新的队尾元素 */
     85 Status EnQueue(LinkQueue *Q,QElemType e)
     86 { 
     87     QueuePtr s=(QueuePtr)malloc(sizeof(QNode));
     88     if(!s)                        /* 存储分配失败 */
     89         exit(OVERFLOW);
     90     s->data=e;
     91     s->next=NULL;
     92     Q->rear->next=s;              /* 把拥有元素e的新结点s赋值给原队尾结点的后继 */
     93     Q->rear=s;                    /* 把当前的s设置为队尾结点,rear指向s */
     94     return OK;
     95 }
     96 
     97 /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
     98 Status DeQueue(LinkQueue *Q,QElemType *e)
     99 {
    100     QueuePtr p;
    101     if(Q->front==Q->rear)
    102         return ERROR;
    103     p=Q->front->next;             /* 将欲删除的队头结点暂存给p */
    104     *e=p->data;                   /* 将欲删除的队头结点的值赋值给e */
    105     Q->front->next=p->next;       /* 将原队头结点的后继p->next赋值给头结点后继 */
    106     if(Q->rear==p)                /* 若队头就是队尾,则删除后将rear指向头结点 */
    107         Q->rear=Q->front;
    108     free(p);
    109     return OK;
    110 }
    111 
    112 /* 从队头到队尾依次对队列Q中每个元素输出 */
    113 Status QueueTraverse(LinkQueue Q)
    114 {
    115     QueuePtr p;
    116     p=Q.front->next;
    117     while(p)
    118     {
    119         visit(p->data);
    120         p=p->next;
    121     }
    122     printf("
    ");
    123     return OK;
    124 }
    125 
    126 int main()
    127 {
    128     int i;
    129     QElemType e;
    130     LinkQueue q;
    131     
    132     i=InitQueue(&q);
    133     printf("1.初始化后队列后,队列的长度:Q.length=%d
    ",QueueLength(q));
    134     
    135     EnQueue(&q,-5);
    136     EnQueue(&q,3);
    137     EnQueue(&q,8);
    138     EnQueue(&q,10);
    139     EnQueue(&q,16);
    140     EnQueue(&q,36);
    141     printf("2.插入6个元素后,队列的长度:Q.length=%d
    ",QueueLength(q));
    142     printf("3.队列的元素输出依次为:");
    143     QueueTraverse(q);
    144     
    145     i=GetHead(q,&e);
    146     if(i==OK)
    147          printf("4.此时队列的队头元素是:%d
    ",e);
    148          
    149     DeQueue(&q,&e);
    150     i=GetHead(q,&e);
    151     if(i==OK)
    152         printf("5.删除队列的队头元素后,新的队头元素是:%d
    ",e);
    153         
    154     DeQueue(&q,&e);
    155     printf("6.继续删除队头元素后,队列的长度:Q.length=%d
    ",QueueLength(q));
    156     printf("7.队列的元素输出依次为:");
    157     QueueTraverse(q);
    158         
    159     ClearQueue(&q);
    160     printf("8.清空队列后,q.front=%u q.rear=%u q.front->next=%u
    ",q.front,q.rear,q.front->next);
    161     
    162     return 0;
    163 }
  • 相关阅读:
    深入理解Java虚拟机之.class文件的数据结构一
    计算机操作系统之文件管理二
    计算机操作系统之文件管理一
    深入理解Java虚拟机之垃圾收集二
    深入理解Java虚拟机之垃圾收集一
    深入理解Java虚拟机之内存管理
    iscsi remote boot
    Autoconfigure enviroment via Python script
    How to set up a PXE server with REHL 7 OS
    jQuery如何获取动态添加的元素
  • 原文地址:https://www.cnblogs.com/mix88/p/6180622.html
Copyright © 2011-2022 走看看