Romi-知行合一

轻轻的风轻轻的梦,轻轻的晨晨昏昏, 淡淡的云淡淡的泪,淡淡的年年岁岁。
  博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

数据结构学习5——队列

Posted on 2012-08-28 22:23  romi  阅读(5546)  评论(0编辑  收藏  举报

队列:先进先出的线性表,它只允许在一端(队尾)进行插入操作,在另一端(队首)进行删除操作。与栈的插入和删除都在栈顶进行不同。

这里只说队列的链式存储。国际惯例,先上源码

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<malloc.h>
  4 
  5 //定义队列
  6 typedef struct node{
  7     int data;
  8     struct node *next;
  9 }Queue;
 10 //定义对手指针和队尾指针
 11 typedef struct pointer{
 12     Queue *front;//队首指针,对手指针不存放队列元素
 13     Queue *rear;//队尾指针,存放队尾的数据元素
 14 }Qpointer;
 15 
 16 //队列初始化
 17 void QueueInit(Qpointer *qp)
 18 {
 19     Queue *que;
 20     que=(Queue*)malloc(sizeof(Queue));
 21     que->next=NULL;
 22     //队首和队尾指向同一个内存空间,指针域为NULL
 23     qp->front=que;
 24     qp->rear=que;
 25 }
 26 
 27 //判断队列是否为空:为空返回1,不为空返回0
 28 int IsEmpty(Qpointer *qp)
 29 {
 30     //判断方法:对手指针和队尾指针是否相同
 31     if(qp->front==qp->rear)
 32     {
 33         return 1;
 34     }
 35     return 0;
 36 }
 37 
 38 //插入数据元素:插入成功返回1,失败返回0
 39 int QueuePush(Qpointer *qp,int element)
 40 {
 41     Queue *que;
 42     que=(Queue*)malloc(sizeof(Queue));
 43     if(que==NULL)
 44     {
 45         return 0;
 46     }
 47     que->data=element;
 48     que->next=NULL;
 49     qp->rear->next=que;//将节点插入队列尾
 50     qp->rear=que;//调整队尾指针
 51     return 0;
 52 }
 53 
 54 //删除数据元素:删除成功返回1,失败返回0
 55 int QueuePop(Qpointer *qp,int *element)
 56 {
 57     Queue *que;
 58     if(IsEmpty(qp))
 59     {
 60         return 0;
 61     }
 62     que=qp->front->next;//que指向队列头结点的下一个节点,即真正的队首
 63     *element=que->data;//将要出队列的元素
 64     qp->front->next=que->next;
 65     //判断队列是否就只剩下一个元素
 66     if(qp->rear==que)
 67     {
 68         qp->rear=qp->front;
 69     }
 70     free(que);
 71     return 1;
 72 }
 73 
 74 int main()
 75 {
 76     Qpointer *qp;
 77     int x;
 78     //初始化队列
 79     qp=(Qpointer*)malloc(sizeof(Qpointer));
 80     QueueInit(qp);
 81     printf("input positive integers:\n");
 82     scanf("%d",&x);
 83     while(x>0)
 84     {
 85         QueuePush(qp,x);
 86         scanf("%d",&x);
 87     }
 88     //输出队列:队首->队尾
 89     Queue *p=qp->front->next;
 90     if(p==NULL)
 91         return 0;
 92     printf("queue element:\n");
 93     while(p)
 94     {
 95         printf("%d ",p->data);
 96         p=p->next;
 97     }
 98     printf("\n");
 99     //删除队列
100     printf("delete queue:\n");
101     while(QueuePop(qp,&x))
102     {
103         printf("%d ",x);
104     }
105     printf("\n");
106     //释放内存空间
107     p=qp->front;
108     free(p);
109     free(qp);
110 
111     return 0;
112 }

1.队列定义:这里除了定义队列中节点的数据结构,还专门定义了队首和队尾,方便对队列操作,这样一来,队列的操作就只需要对pointer结构体中的对手指真和队尾指针进行。

2.判断是否为空
当队首指针和队尾指针只想同一块地址时,队列为空,队列为空就是说队列中没有数据元素。注意队首front只是队列的头结点,并不代表队列的实际队首,在队列不为空时,队列的实际队首应该是头结点的下一个节点。

3.插入数据元素

插入在队尾进行,插入后,新插入的节点就成为了队尾。

4.删除数据元素

删除在队首进行,需要注意的是,当实际的队首也是队尾时,删除队列中的一个数据后队列就成为了空队列(rear=front)。最后不要忘了将删除的数据的内存空间释放掉。

5.注意点

最后释放内存时,一定要先释放掉pointer中的队首指针和队尾指针指向的内存空间,再释放掉pointer结构体指向的内存空间。

使用GDB调试,可知pointer结构体的内存模型如下:

这时初始化队列后的情况,并未插入任何数据。pointer结构体指针变量qp指向0x804b008,因为qp中有两个指针变量,所以占8个字节的内存空间,分别存放front(指向0x804b018)指针变量和rear(指向0x804b018)指针变量