zoukankan      html  css  js  c++  java
  • 队列的链式存储结构

    队列的链式存储结构

    所谓队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已。

    为了操作方便,我们将队头指针指向链队列的头结点,而队尾指针指向终点元素,注意这个时候不是尾部元素的下一个了。如图:

    空队列时,头指针front和尾指针rear都指向头结点。

    链队列的结构为

    1 typedef struct QNode   //节点结构
    2 {
    3     int data;
    4     QNode* next;
    5 }QNode;
    6 typedef struct QNode* QueuePtr;
    7 typedef struct{               //队列的链表结构
    8     QueuePtr front,rear;
    9 }LinkQueue;

     队列初始化操作

     1 /*链队列初始化操作,初始化头结点*/
     2 int InitLinkQueue(LinkQueue* Q){
     3     if(!Q)
     4         return 0;
     5     QueuePtr s =(QueuePtr)malloc(sizeof(QNode));
     6     s->next=NULL;
     7     Q->front=Q->rear=s; //置空
     8     return 0;
     9 
    10 }

    队列使用前必须初始化,申请头结点内存空间。

    入队操作

     1 /*入队操作*/
     2 int EnQueue(LinkQueue* Q,int e){
     3     QueuePtr s =(QueuePtr)malloc(sizeof(QNode));  //申请新节点空间
     4     if(!s)
     5         return 0;
     6     s->data=e;      //赋值
     7     //s->next=Q->rear->next;   //并初始化,与s->next=NULL相同    
     8     s->next=NULL;
     9     Q->rear->next=s;
    10 
    11     Q->rear=s;
    12     return e;
    13 }

    入队的操作是将新节点指向rear 的next ,然后再将rear 的next指向新节点(类似单链表的插入),最后确记要把rear移动到新节点

    出队操作

     1 /*出队操作*/
     2 int DeQueue(LinkQueue* Q){
     3 
     4     int e;
     5     QueuePtr p;
     6     p=Q->front->next;    //指向第一个节点
     7     if(p){
     8         Q->front->next=p->next;    //头结点下移
     9         free(p);             //释放内存
    10         p=Q->front->next;   //p再移到头结点下
    11     }
    12     else if(p = Q->rear)          //空队列时
    13         Q->front = Q->rear;
    14 
    15     return e;
    16 }

    使用一个指针p指向头结点的下一位,然后移动头结点到p的next,再然后释放p的内存,这就释放的一个节点的空间,此时p再次移动到头结点的下一位,依次进行...

    遍历队元素

    1 /*遍历队列*/
    2 void TraverseQueue(LinkQueue* Q){
    3     QueuePtr p;
    4     p = Q->front->next;
    5     while(p){
    6         printf("%d ",p->data);
    7         p=p->next;
    8     }    
    9 }

    遍历队元素的确记不要去移动front和rear指针的而位置,所以要再新建一个指针来遍历。

     清空队

     1 /*清空链队列*/
     2 int ClearLinkQueue(LinkQueue* Q){
     3 
     4     QueuePtr p;
     5 
     6     p = Q->front->next;  //p指向头结点下一个
     7     while(p){
     8         Q->front->next=p->next;   //队头移动
     9         if(Q->rear==p)   //删到队尾了
    10             Q->front = Q->rear;  //队列置空
    11         else if(Q->front=Q->rear)  //循环退出
    12             return 0;    
    13         free(p);   //释放内存
    14         p=Q->front->next;   //继续移动
    15     }
    16     return 1;
    17 }

    再清空队列的循环中确记要加上循环结束的出口,否则将陷入死循环,即当Q->real==Q->front时,队列为空 。其中指针的移动类似于出队的操作相同。

    主要代码

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 typedef struct QNode   //节点结构
      5 {
      6     int data;
      7     QNode* next;
      8 }QNode;
      9 typedef struct QNode* QueuePtr;
     10 
     11 typedef struct{               //队列的链表结构
     12     QueuePtr front,rear;
     13 }LinkQueue;
     14 
     15 /*链队列初始化操作,初始化头结点*/
     16 int InitLinkQueue(LinkQueue* Q){
     17     if(!Q)
     18         return 0;
     19     QueuePtr s =(QueuePtr)malloc(sizeof(QNode));
     20     s->next=NULL;
     21     Q->front=Q->rear=s; //置空
     22     return 0;
     23 }
     24 
     25 /*入队操作*/
     26 int EnQueue(LinkQueue* Q,int e){
     27     QueuePtr s =(QueuePtr)malloc(sizeof(QNode));
     28     if(!s)
     29         return 0;
     30     s->data=e;      //赋值
     31     //s->next=Q->rear->next;   //并初始化,与s->next=NULL相同    
     32     s->next=NULL;
     33     Q->rear->next=s;
     34 
     35     Q->rear=s;
     36     return e;
     37 }
     38 
     39 /*清空链队列*/
     40 int ClearLinkQueue(LinkQueue* Q){
     41 
     42     QueuePtr p;
     43 
     44     p = Q->front->next;  //p指向头结点下一个
     45     while(p){
     46         Q->front->next=p->next;   //队头移动
     47         if(Q->rear==p)   //删到队尾了
     48             Q->front = Q->rear;  //队列置空
     49         else if(Q->front=Q->rear)  //循环退出
     50             return 0;    
     51         free(p);   //释放内存
     52         p=Q->front->next;   //继续移动
     53     }
     54     return 1;
     55 }
     56 
     57 
     58 /*队列是否为空*/
     59 int ElmptyQueue(LinkQueue* Q){
     60     QueuePtr p;
     61     p=Q->front->next;
     62     if(p)
     63         return 0;
     64     else 
     65         return 1;
     66 }
     67 
     68 /*获取队列长度*/
     69 int QueueLength(LinkQueue* Q){
     70     int count=0;
     71     QueuePtr p;
     72     p=Q->front->next;
     73     while(p){
     74         count++;
     75         p=p->next;
     76     }        
     77     return count;
     78 }
     79 
     80 /*出队操作*/
     81 int DeQueue(LinkQueue* Q){
     82 
     83     int e;
     84     QueuePtr p;
     85     p=Q->front->next;    //指向第一个节点
     86     if(p){
     87         Q->front->next=p->next;    //头结点后移
     88         free(p);             //释放内存
     89         p=Q->front->next;   //p再移到头结点下
     90     }
     91     else if(p = Q->rear)          //空队列时
     92         Q->front = Q->rear;
     93 
     94     return e;
     95 }
     96 
     97 /*遍历队列*/
     98 void TraverseQueue(LinkQueue* Q){
     99     QueuePtr p;
    100     p = Q->front->next;
    101     while(p){
    102         printf("%d ",p->data);
    103         p=p->next;
    104     }    
    105 }
    106 
    107 int main(){
    108 
    109     LinkQueue s;
    110     InitLinkQueue(&s);
    111     printf("入队10个元素 :
    ");
    112     for(int i=0;i<10;i++)
    113     printf("%d ",EnQueue(&s,i));
    114     printf("
    ");
    115 
    116     printf("遍历队列
    ");
    117     TraverseQueue(&s);
    118     printf("
    ");
    119 
    120     printf("队元素个数");
    121     printf("个数:%d
    ",QueueLength(&s));
    122     printf("出队一个元素
    ");
    123     DeQueue(&s);
    124     printf("队元素个数");
    125     printf("个数:%d
    ",QueueLength(&s));
    126     
    127     printf("是否队列为空(1:0):%d
     ",ElmptyQueue(&s));
    128 
    129     printf("清空队列...");
    130     ClearLinkQueue(&s);
    131     printf("个数:%d
    ",QueueLength(&s));
    132     return 0;
    133 }

     

     链式存储结构比顺序结构难操作,特别要注意指针的指向和指向内存的有效性。

    比较循环队列和链队列的差异性:

    从时间上:两者操作都是O(1),即常数时间,不过循环队列是事先申请好空间,使用期间不能释放,而对于链队列,每次申请和释放节点也会产生一些时间上的开销

    如果入队和出队频繁的话,还是存在细微差异性的,

    从空间:循环队列必须有一个固定的长度,所以就有了存储元素个数和空间浪费的问题了,而链队列不存在此问题,所以在空间上,链队列更加灵活。

     附上Java代码 

     1 package linkqueue;
     2 
     3 public class LinkQueue {
     4 
     5     QNode front, rear;
     6 
     7     /**
     8      * 初始化队列
     9      */
    10     public void initLinkQueue(LinkQueue Q) {
    11         QNode node = new QNode();
    12         node.next = null;
    13         Q.front = Q.rear = node;
    14     }
    15 
    16     /**
    17      * 入队
    18      */
    19     public void enLinkQueue(LinkQueue Q, int e) {
    20         QNode node = new QNode();
    21         node.data = e;
    22         node.next = Q.rear.next;
    23         Q.rear.next = node;
    24         Q.rear = node;
    25     }
    26 
    27     /**
    28      * 出队
    29      */
    30     public int deLinkQueue(LinkQueue Q) {
    31         int e;
    32         QNode node;
    33         node = Q.front.next;
    34 
    35         if (node != null) {
    36             e = node.data;
    37             Q.front.next = node.next;
    38             node = Q.front.next;
    39             return e;
    40         } else if (node == Q.rear) {
    41             Q.rear = Q.front;
    42         }
    43         return 0;
    44     }
    45 
    46     /**
    47      * 清空队
    48      */
    49     public void clearLinkQueue(LinkQueue Q) {
    50         QNode node;
    51         node = Q.front.next;
    52         if (node == Q.rear)
    53             Q.rear = Q.front = null;
    54         while (node != null) {
    55             Q.front.next = node.next;
    56             node = Q.front.next;
    57         }
    58 
    59     }
    60 
    61     /**
    62      * 返回队列长度
    63      */
    64     public int gtLinkQueue(LinkQueue Q) {
    65         int count = 0;
    66         QNode node;
    67         node = Q.front.next;
    68         while (node != null) {
    69             count++;
    70             node = node.next;
    71         }
    72         return count;
    73     }
    74 
    75     /**
    76      * 遍历队元素
    77      */
    78     public void traverseList(LinkQueue Q) {
    79         QNode node;
    80         node = Q.front.next;
    81         while (node != null) {
    82             System.out.print(node.data + " ");
    83             node = node.next;
    84         }
    85     }
    86 
    87 }
    View Code
    1 package linkqueue;
    2 
    3 public class QNode {
    4     int data;
    5     QNode next;
    6 }
    View Code
     1 package linkqueue;
     2 
     3 public class Test {
     4 
     5     public static void main(String[] args) {
     6         LinkQueue queue = new LinkQueue();
     7         System.out.println("初始化队列...");
     8         queue.initLinkQueue(queue);
     9         System.out.println("入队10个元素...");
    10         for (int i = 0; i < 10; i++)
    11             queue.enLinkQueue(queue, i);
    12         System.out.println("遍历队列元素...");
    13         queue.traverseList(queue);
    14         System.out.println("");
    15 
    16         System.out.println("出队一个元素..." + queue.deLinkQueue(queue));
    17         System.out.println("再出队一个元素..." + queue.deLinkQueue(queue));
    18 
    19         System.out.println("元素个数..." + queue.gtLinkQueue(queue));
    20 
    21         System.out.println("清空队列");
    22         queue.clearLinkQueue(queue);
    23         System.out.println("元素个数..." + queue.gtLinkQueue(queue));
    24 
    25     }
    26 
    27 }
    View Code

     完毕 -  。- 

  • 相关阅读:
    201521123036 《Java程序设计》第4周学习总结
    201521123036 《Java程序设计》第3周学习总结
    201521123075 《Java程序设计》第12周学习总结
    201521123075 《Java程序设计》第11周学习总结
    201521123075 《Java程序设计》第10周学习总结
    201521123075 《Java程序设计》第9周学习总结
    201521123075 《Java程序设计》第8周学习总结
    201521123075 《Java程序设计》第7周学习总结
    201521123075 《Java程序设计》第6周学习总结
    201521123075 《Java程序设计》第5周学习总结
  • 原文地址:https://www.cnblogs.com/liuzeyu12a/p/10312115.html
Copyright © 2011-2022 走看看