重提循环队列

来源:互联网 发布:js 调用touchstart 编辑:程序博客网 时间:2024/05/16 19:14

之前写过一篇博客介绍队列:http://blog.csdn.net/thefutureisour/article/details/7835273

后来发现这个这个队列是有问题的:

bool enQueue(Queue *q,ElemType e){//如果队列已满,重新分配内存if(q->rear == q->Qsize-1){q->data = (ElemType*)realloc(q->data,2*q->Qsize*sizeof(ElemType));if(q->data == NULL)return false;elseq->Qsize *= 2;}//先赋值,然后队尾循环加1q->data[q->rear] = e;q->rear = (q->rear+1)%q->Qsize;return true;}


这个判断队列满的办法明显是错误的,因为有可能在多次出队、入队操作以后,data[1]代表rear,data[0]代表front,此时队列已经满了应该重新分配内存,而这个程序并没有做出正确的判断。然后我对作了修改,改成了

if(Qlength(q) == q->Qsize-1)


这个代码看似正确,但是如果进行下面的测试,就会发现问题了:

int a = 100;Queue myQueue;initQueue(&myQueue,4);//先把队列充满for(int i = 0 ; i < 3 ;++i)enQueue(&myQueue,i);printQueue(&myQueue);deQueue(&myQueue,&a);enQueue(&myQueue,3);printQueue(&myQueue);deQueue(&myQueue,&a);enQueue(&myQueue,4);printQueue(&myQueue);enQueue(&myQueue,5);printQueue(&myQueue);destroyQueue(&myQueue);


 

最后一次入队5以后,打印为空,通过单步调试,我发现问题因为此时Qlength的返回值为0.我才恍然大悟,问题的严重性:

当data[0]为rear而data[1]为front时,虽然这时候队列实际已经满了,我也重新分配了内存,但是rear和front下标却没有修改,进而导致重新分配的后的数组是类似于下面的结构:

data      0         1         2         3         4         5         6         7

             rear     front    数据   数据    {      新分配的空间      }

首先:enqueue以后rear会++,所以此时会出现Qlength为0,其次这已经完全不是循环队列的结构了,rear的前一个数据是没有初始化的内存。

怎么解决这个问题呢?

我也没有特别高明的办法,只能重新分配的时候新建一个数组,数组中的元素按照队列从头至尾的顺序保存,然后重新分配内存之后,把新内存的前Qsize-1个元素用新建的数组初始化,然后把rear置为Qsize,新来的元素放到rear的位置,然后rear再自增。这样就搞定了:

bool enQueue(Queue *q,ElemType e){//如果队列已满,重新分配内存if(q->Qsize-1 == Qlength(q)){//先把原来的按顺序记录在tmp中ElemType* tmp = (ElemType*)malloc(sizeof(ElemType) * q->Qsize);for(int i = 0; i< q->Qsize-1;++i){tmp[i] = q->data[(q->front+i+q->Qsize)%q->Qsize];}//重新分配内存q->data = (ElemType*)realloc(q->data,2*q->Qsize*sizeof(ElemType));if(q->data == NULL)return false;//用tmp初始化q->datafor(int i = 0; i< q->Qsize-1;++i){q->data[i] = tmp[i];}//重新设定front、rear标记q->front= 0;q->rear = q->Qsize;//新来的元素放入队尾q->data[q->Qsize] = e;//队尾指针自增q->rear++;//容量翻倍q->Qsize *= 2;free(tmp);}else{//先赋值,然后队尾循环加1q->data[q->rear] = e;q->rear = (q->rear+1)%q->Qsize;}return true;}


 

由于时间匆忙,可能会有小的纰漏,但是大方向上应该是没有问题的。

 

原创粉丝点击