Chinaunix首页 | 论坛 | 博客
  • 博客访问: 256749
  • 博文数量: 52
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1538
  • 用 户 组: 普通用户
  • 注册时间: 2013-04-24 07:45
个人简介

生活就像海洋,只有意志坚强的人,才能到达彼岸。

文章存档

2013年(52)

分类: C/C++

2013-08-18 19:12:45

一、队列的定义
    
1>队列是一种特殊的线性表

2>队列仅在线性表的两端进行操作

    *对头(Front):取出数据元素的一端

    *队尾(Rear):插入数据元素的一端

3>性质:先进先出(FIFO)

4>队列的操作
    
    *创建队列

    *销毁队列

    *清空队列

    *进队列

    *出队列

    *获取对头元素

    *获取队列的长度

队里是一种特殊的线性表,所以通常有两种实现方式,顺序结构实现。链式结构实现。从而我们可以

复用之前实现的链表会很简单的实现队列,在此就不做详细介绍了。下面来讨论队列的优化实现,其

中也包括顺序结构实现和链式结构实现。

二、顺序队列的优化实现

顺序队列的瓶颈  如何将出队操作的时间复杂度降低到O(1)?

定义front使其始终代表队头的下标
    出队时将队头元素返回,且front++

定义rear使其始终代表队尾下一个元素的小标
    入队时将新元素插入,且rear++

没有必要只将下标为0的位置定义为对头!!!

顺序状态的关键状态

    初始状态:length == 0, front == 0, rear == 0;

    空队列时:length == 0, front == rear;

    满队列状态:length == capacity, front == rear;

循环使用队列中的空间

    入队:rear = (rear + 1)% capacity;

    出队:front = (front + 1)% capacity;

点击(此处)折叠或打开

  1. /********************************SeqQueue.h**********************/

  2. #ifndef _SEQQUEUE_H_
  3. #define _SEQQUEUE_H_

  4. typedef void SeqQueue;

  5. SeqQueue* SeqQueue_Create(int capacity);

  6. void SeqQueue_Destroy(SeqQueue* queue);

  7. void SeqQueue_Clear(SeqQueue* queue);

  8. int SeqQueue_Append(SeqQueue* queue, void* item);

  9. void* SeqQueue_Retrieve(SeqQueue* queue);

  10. void* SeqQueue_Header(SeqQueue* queue);

  11. int SeqQueue_Length(SeqQueue* queue);

  12. int SeqQueue_Capacity(SeqQueue* queue);

  13. #endif

  14. /*************************SeqQueue.c****************************/
  15. #include <stdio.h>
  16. #include <malloc.h>
  17. #include "SeqQueue.h"

  18. typedef unsigned int TSeqQueueNode;

  19. typedef struct _tag_SeqQueue
  20. {
  21.     int capacity;
  22.     int length;
  23.     int front;
  24.     int rear;
  25.     TSeqQueueNode* node;
  26. }TSeqQueue;

  27. SeqQueue* SeqQueue_Create(int capacity)
  28. {
  29.     TSeqQueue* ret = NULL;
  30.     if( capacity >= 0)
  31.     {
  32.         ret = (TSeqQueue*)malloc(sizeof(TSeqQueue) + sizeof(TSeqQueueNode) * capacity);    
  33.     }
  34.     
  35.     if( ret != NULL )
  36.     {
  37.         ret->capacity = capacity;
  38.         ret->length = 0;
  39.         ret->front = 0;
  40.         ret->rear = 0;
  41.         ret->node = (TSeqQueueNode*)(ret + 1);    
  42.     }
  43.     
  44.     return ret;
  45. }

  46. void SeqQueue_Destroy(SeqQueue* queue)
  47. {
  48.     free(queue);
  49. }

  50. void SeqQueue_Clear(SeqQueue* queue)
  51. {
  52.     TSeqQueue* sQueue = (TSeqQueue*)queue;
  53.     
  54.     if( sQueue != NULL )
  55.     {
  56.         sQueue->length = 0;
  57.         sQueue->front = 0;
  58.         sQueue->rear = 0;    
  59.     }
  60. }

  61. int SeqQueue_Append(SeqQueue* queue, void* item)
  62. {
  63.     TSeqQueue* sQueue = (TSeqQueue*)queue;
  64.     int ret = (sQueue != NULL);
  65.     
  66.     ret = ret && (item != NULL) && (sQueue->length + 1 < sQueue->capacity );
  67.     
  68.     if( ret )
  69.     {
  70.         sQueue->node[sQueue->rear] = (TSeqQueueNode)item;
  71.         
  72.         sQueue->rear = (sQueue->rear + 1) % sQueue->capacity;
  73.         
  74.         sQueue->length++;    
  75.     }
  76.     
  77.     return ret;
  78. }

  79. void* SeqQueue_Retrieve(SeqQueue* queue)
  80. {
  81.     TSeqQueue* sQueue = (TSeqQueue*)queue;
  82.     void* ret = SeqQueue_Header(queue);
  83.     
  84.     if( ret != NULL)
  85.     {    
  86.         sQueue->front = (sQueue->front + 1) % sQueue->capacity ;
  87.         
  88.         sQueue->length--;
  89.             
  90.     }
  91.     
  92.     return ret;
  93. }

  94. void* SeqQueue_Header(SeqQueue* queue)
  95. {
  96.     TSeqQueue* sQueue = (TSeqQueue*)queue;
  97.     void*ret = NULL;
  98.     
  99.     if( (sQueue != NULL) && (sQueue->length > 0))
  100.     {
  101.         ret = (void*)(sQueue->node[sQueue->front]);            
  102.     }
  103.     
  104.     return ret;
  105. }

  106. int SeqQueue_Length(SeqQueue* queue)
  107. {
  108.     TSeqQueue* sQueue = (TSeqQueue*)queue;
  109.     int ret = -1;
  110.     
  111.     if( sQueue != NULL)
  112.     {
  113.         ret = sQueue->length;            
  114.     }
  115.     
  116.     return ret;
  117. }

  118. int SeqQueue_Capacity(SeqQueue* queue)
  119. {
  120.     TSeqQueue* sQueue = (TSeqQueue*)queue;
  121.     int ret = -1;
  122.     
  123.     if( sQueue != NULL)
  124.     {
  125.         ret = sQueue->capacity;            
  126.     }
  127.     
  128.     return ret;
  129.     
  130. }
  131. /*************************************main.c****************/
  132. #include <stdio.h>
  133. #include <stdlib.h>
  134. #include "SeqQueue.h"

  135. /* run this program using the console pauser or add your own getch, system("pause") or input loop */

  136. int main(int argc, char *argv[])
  137. {
  138.     SeqQueue* queue = SeqQueue_Create(6);
  139.     int a[10] = {0};
  140.     int i = 0;
  141.     
  142.     for(i=0; i<10; i++)
  143.     {
  144.         a[i] = i + 1;
  145.         
  146.         SeqQueue_Append(queue, a + i);
  147.     }
  148.     
  149.     printf("Header: %d\n", *(int*)SeqQueue_Header(queue));
  150.     printf("Length: %d\n", SeqQueue_Length(queue));
  151.     printf("Capacity: %d\n", SeqQueue_Capacity(queue));
  152.     
  153.     while( SeqQueue_Length(queue) > 0 )
  154.     {
  155.         printf("Retrieve: %d\n", *(int*)SeqQueue_Retrieve(queue));
  156.     }
  157.     
  158.     printf("\n");
  159.     
  160.     for(i=0; i<10; i++)
  161.     {
  162.         a[i] = i + 1;
  163.         
  164.         SeqQueue_Append(queue, a + i);

  165.         printf("Retrieve: %d\n", *(int*)SeqQueue_Retrieve(queue));
  166.     }
  167.     
  168.     SeqQueue_Destroy(queue);
  169.     
  170.     return 0;
  171. }
三、链式队列的优化实现

1>定义rear指针始终指向链表中的最后一个元素
    *入队时将新元素通过rear插入队尾,且将rear指向新元素

2>链式队列的关键状态
    *空队列状态:front == NULL,rear == NULL;

3>关键操作
    *入队:
        rear->next = node;
        rear = node;
        node->next = NULL;
    *出队:
    front = front->next;

点击(此处)折叠或打开

  1. /**********************LinkQueue.h********************/
  2. #ifndef _LINKQUEUE_H_
  3. #define _LINKQUEUE_H_

  4. typedef void LinkQueue;

  5. LinkQueue* LinkQueue_Create();

  6. void LinkQueue_Destroy(LinkQueue* queue);

  7. void LinkQueue_Clear(LinkQueue* queue);

  8. int LinkQueue_Append(LinkQueue* queue, void* item);

  9. void* LinkQueue_Retrieve(LinkQueue* queue);

  10. void* LinkQueue_Header(LinkQueue* queue);

  11. int LinkQueue_Length(LinkQueue* queue);

  12. #endif

  13. /**********************LinkQueue.c********************/
  14. #include <malloc.h>
  15. #include <stdio.h>
  16. #include "LinkQueue.h"

  17. typedef struct _tag_LinkQueueNode TLinkQueueNode;
  18. struct _tag_LinkQueueNode
  19. {
  20.     TLinkQueueNode* next;
  21.     void* item;
  22. };

  23. typedef struct _tag_LinkQueue
  24. {
  25.     TLinkQueueNode* front;
  26.     TLinkQueueNode* rear;
  27.     int length;
  28. }TLinkQueue;


  29. LinkQueue* LinkQueue_Create() // O(1)
  30. {
  31.     TLinkQueue* ret = (TLinkQueue*)malloc(sizeof(TLinkQueue));
  32.     
  33.     if( ret != NULL )
  34.     {
  35.         ret->front = NULL;
  36.         ret->rear = NULL;
  37.         ret->length = 0;    
  38.     }
  39.     
  40.     return ret;
  41. }

  42. void LinkQueue_Destroy(LinkQueue* queue) // O(n)
  43. {
  44.     LinkQueue_Clear(queue);
  45.    free(queue);
  46. }

  47. void LinkQueue_Clear(LinkQueue* queue) // O(n)
  48. {
  49.     while( LinkQueue_Length(queue) > 0 )
  50.     {
  51.         LinkQueue_Retrieve(queue);    
  52.     }
  53. }

  54. int LinkQueue_Append(LinkQueue* queue, void* item) // O(1)
  55. {
  56.     TLinkQueue* sQueue = (TLinkQueue*)queue;
  57.     TLinkQueueNode* node = (TLinkQueueNode*)malloc(sizeof(TLinkQueueNode));
  58.     int ret = (sQueue != NULL) && (item != NULL) && (node != NULL);
  59.     
  60.     if( ret )
  61.     {
  62.         node->item = item;
  63.         
  64.         if(sQueue->length > 0)
  65.         {
  66.             sQueue->rear->next = node;
  67.             sQueue->rear = node;
  68.             node->next = NULL;
  69.         }
  70.         else
  71.         {
  72.             sQueue->front = node;
  73.             sQueue->rear = node;
  74.             node->next = NULL;
  75.         }    
  76.         
  77.         sQueue->length++;
  78.     }
  79.     
  80.     if( !ret )
  81.     {    
  82.         free(node);
  83.     }
  84.     
  85.     return ret;
  86.     
  87. }

  88. void* LinkQueue_Retrieve(LinkQueue* queue) // O(1)
  89. {
  90.     TLinkQueue* sQueue = (TLinkQueue*)queue;
  91.     TLinkQueueNode* node = NULL;
  92.     void* ret = NULL;
  93.     
  94.     if( (sQueue != NULL) && (sQueue->length > 0))
  95.     {
  96.         node = sQueue->front ;    
  97.         sQueue->front = node->next ;
  98.         
  99.         ret = node->item ;
  100.         
  101.         free(node);
  102.         
  103.         sQueue->length--;
  104.         
  105.         if( sQueue->length == 0)
  106.         {
  107.             sQueue->front = NULL;
  108.             sQueue->rear = NULL;
  109.         }
  110.     }
  111.     
  112.     return ret;
  113. }

  114. void* LinkQueue_Header(LinkQueue* queue) // O(1)
  115. {
  116.    TLinkQueue* sQueue = (TLinkQueue*)queue;
  117.    
  118.    void* ret = NULL;
  119.    
  120.    if( (sQueue != NULL) && (sQueue->length > 0))
  121.     {
  122.         ret = sQueue->front->item ;    
  123.     }
  124.     
  125.     return ret;
  126. }

  127. int LinkQueue_Length(LinkQueue* queue) // O(1)
  128. {
  129.     TLinkQueue* sQueue = (TLinkQueue*)queue;
  130.     int ret = -1;
  131.     
  132.     if(sQueue != NULL)
  133.     {
  134.         ret = sQueue->length;    
  135.     }
  136.     
  137.    return ret;
  138. }

  139. /**********************main.c*************************/
  140. #include <stdio.h>
  141. #include <stdlib.h>
  142. #include "LinkQueue.h"

  143. /* run this program using the console pauser or add your own getch, system("pause") or input loop */

  144. int main(int argc, char *argv[])
  145. {
  146.     LinkQueue* queue = LinkQueue_Create();
  147.     int a[10] = {0};
  148.     int i = 0;
  149.     
  150.     for(i=0; i<10; i++)
  151.     {
  152.         a[i] = i + 1;
  153.         
  154.         LinkQueue_Append(queue, a + i);
  155.     }
  156.     
  157.     printf("Header: %d\n", *(int*)LinkQueue_Header(queue));
  158.     printf("Length: %d\n", LinkQueue_Length(queue));
  159.     
  160.     LinkQueue_Clear(queue);
  161.     
  162.     while( LinkQueue_Length(queue) > 0 )
  163.     {
  164.         printf("Retrieve: %d\n", *(int*)LinkQueue_Retrieve(queue));
  165.     }
  166.     
  167.     LinkQueue_Destroy(queue);
  168.     
  169.     return 0;
  170. }
优化的顺序队列循环利用空间提高出队操作的效率,优化的链式队列定义rear指针指向队尾元素提高

出队操作的效率。

四、用栈实现队列的特别实现

实现思路:

    准备两个栈用于实现队列:inStack和outStack

    当有新元素入队时:将其压入inStack中

    当需要出队时:

    当outStack为空时:

    1、将inStack中的元素逐一弹出并压入outStack中

    2、将outStack的栈顶元素弹出

    当outStack不为空时:

    -直接将outStack的栈顶元素弹出



阅读(1618) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~