将Queue数据结构作为数组实现的问题

时间:2013-08-17 10:47:34

标签: c arrays pointers data-structures queue

此代码将简单队列数据结构作为数组实现

#include <stdio.h>
#define Q_MAX_SIZE 255
#include <stdbool.h>
struct queue
{
    int* pointer;
    int* currentValue;
    int max, count, theQueue[Q_MAX_SIZE];
};

void initQueue(struct queue*);
bool pushQueue(struct queue*, int);
int* popQueue(struct queue*);

int main(void)
{
    int i, j, num = 0;
    struct queue obj[5];

    for(i=0; i<5; i++)
    {
        initQueue(&obj[i]);

        for(j = 0; j<3; j++)
        {
            num++;
            pushQueue(&obj[i], num);
        }
        num = 0;
    }

    for(i=0; i<5; i++)
    {
        printf("Queue[%d]:\n", i);
        int* inputobj;
        inputobj = popQueue(&obj[i]);

        while(inputobj != NULL)
        {
            printf("Queue[No.%d] = %d\n", i, *inputobj);
            inputobj = popQueue(&obj[i]);
        }
        putchar('\n');
    }

    puts("done..!");

    return 0;
}

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

void initQueue(struct queue *Q)
{
    Q->pointer = Q->theQueue;
    Q->max = Q_MAX_SIZE;
    Q->count = 0;
}

bool pushQueue(struct queue *Q, int input)
{
    if(Q->count < Q->max)
    {
        *Q->pointer = input;
        Q->pointer++;
        Q->count++;
        return 1;
    }
    else
        return 0;
}

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

int* popQueue(struct queue *Q)
{
    int i;
    if(Q->count > 0)
    {
        Q->currentValue = Q->theQueue;
        Q->pointer--;
        Q->count--;

        for(i=0; i < Q->count; i++)
        {
            int* currentPtr = Q->theQueue + i;
            int* nextPtr = currentPtr + 1;
            *currentPtr = *nextPtr;
        }
        return Q->currentValue;
    }

    else
        NULL;
}

此行中函数popQueue()中的代码存在问题:

Q->currentValue = Q->theQueue;

是工作把输出不正确

output:
Queue[0]:
Queue[No.0] = 2
Queue[No.0] = 3
Queue[No.0] = 3

Queue[1]:
Queue[No.1] = 2
Queue[No.1] = 3
Queue[No.1] = 3

Queue[2]:
Queue[No.2] = 2
Queue[No.2] = 3
Queue[No.2] = 3

Queue[3]:
Queue[No.3] = 2
Queue[No.3] = 3
Queue[No.3] = 3

Queue[4]:
Queue[No.4] = 2
Queue[No.4] = 3
Queue[No.4] = 3

done..!

但在我更改currentValue结构中的指针(queue)以使其为整数类型并编辑函数popQueue()中的某些行之后,每件事都可以正常工作。

- 这是编辑后的功能:

int* popQueue(struct queue *Q)
{
  int i;
  if(Q->count > 0)
  {
    Q->currentValue = Q->theQueue[0];
    Q->pointer--;
    Q->count--;

    for(i=0; i < Q->count; i++)
    {
      int* currentPtr = Q->theQueue + i;
      int* nextPtr = currentPtr + 1;
      *currentPtr = *nextPtr;
    }
    return &Q->currentValue;
  }

- 这是正确的输出:

Queue[0]:
Queue[No.0] = 1
Queue[No.0] = 2
Queue[No.0] = 3

Queue[1]:
Queue[No.1] = 1
Queue[No.1] = 2
Queue[No.1] = 3

Queue[2]:
Queue[No.2] = 1
Queue[No.2] = 2
Queue[No.2] = 3

Queue[3]:
Queue[No.3] = 1
Queue[No.3] = 2
Queue[No.3] = 3

Queue[4]:
Queue[No.4] = 1
Queue[No.4] = 2
Queue[No.4] = 3

问题是:是什么让第一个代码提供了错误的输出?

1 个答案:

答案 0 :(得分:1)

在第一种情况下,错误输出的原因是指针Q->currentValue从未改变其值(它所持有的地址)。它始终指向队列中的第一个元素。

说队列包含{1, 2, 3 |,<garbage>}

这意味着,在第一次弹出后,队列变为:

{2, 3 |, 3, <garbage>}

currentValue仍保留数组中第一个元素的地址,即2

第二次弹出后:

{3 |, 3, 3, <garbage>}

currentValue指向第一个元素,其值为3

最后一次,数组没有变化(因为Q->count--Q->count的值更改为0),所以conent是

{| 3, 3, 3, <garbage>} 并且currentValue仍然指向3

我假设您更改了第二个示例,以使Queue->currentValue成为int

这样,它会保留原始的第一个元素(弹出)。

这使您的打印在您的测试用例中正常工作。

<强>然而,

  • 如果队列中有0,您的实施将失败。
  • 您的实现会为pop操作(O(n))增加不必要的复杂性。使用headtail来实现循环队列要好得多。
  • 保留弹出元素的副本以便返回它不会是我的第一选择。我建议实现一个isEmpty()方法,在while循环中检查其结果,当队列不为空时,只需让pop()返回队列前进head并返回前一个元素。