链表队列,无限循环

时间:2013-11-09 09:18:46

标签: c queue

我使用嵌套结构来定义链表列表:

queue.h:

#define QUEUE_MAX_SIZE 4096

struct QUEUE_NODE {
  char *string;
  struct QUEUE_NODE *next;
}queue_node;

struct COMMON_QUEUE {
  struct QUEUE_NODE *q_node;
}common_queue;

=================================

queue.c:

/* here I define the operations */
struct COMMON_QUEUE *C_init_queue() {
  struct QUEUE_NODE *head;
  head = malloc(sizeof(struct QUEUE_NODE));
  if (head==NULL) {
    fprintf(stderr, "Insufficient memory!!!");
    return NULL;
  }
  struct COMMON_QUEUE *new_queue;
  new_queue = malloc(sizeof(struct COMMON_QUEUE));
  if (new_queue==NULL) {
    fprintf(stderr, "Insufficient memory!!!");
    return NULL;
  }
  head->next = NULL;
  head->string = NULL;

  new_queue->q_node = head;

  return new_queue;
}

int C_get_queue_length(struct COMMON_QUEUE *q) {
  int count;
  count = 0;

  while (q->q_node->next!=NULL) {
    count += 1;
    q->q_node = q->q_node->next;
  }

  return count;
}

int C_enqueue(struct COMMON_QUEUE *q, char *in) {
  if (C_get_queue_length(q)>=QUEUE_MAX_SIZE) {
    fprintf(stderr, "Linked queue is full!!!");
    return ERROR;
  }
  struct QUEUE_NODE *new_node;
  new_node = malloc(sizeof(struct QUEUE_NODE));
  if (new_node==NULL) {
    return ERROR;
  }
  new_node->next = NULL;
  new_node->string = NULL;

  while (q->q_node->next!=NULL) {
    q->q_node = q->q_node->next;
  }
  new_node->next = q->q_node->next;
  q->q_node->next = q->q_node;
  new_node->string = in;

  return OK;
  }

但是当我在主程序中使用它时,它会在回溯后跳转到无限循环,我知道问题出在:

while (q->q_node->next!=NULL) {
    count += 1;
    q->q_node = q->q_node->next;
}

但似乎是正确的,但我可能会在初始化两个嵌套结构时犯一些错误!

P.S。我没有列出“免费()”。

2 个答案:

答案 0 :(得分:2)

此循环在遍历列表时修改列表。具体来说,它会将q->q_node替换为q->q_node->next,如果没有其他内容会丢弃您的整个循环。

while (q->q_node->next!=NULL) {
    count += 1;
    q->q_node = q->q_node->next;
}

如果要正确遍历列表,则需要声明用于遍历的单独指针。像这样:

int C_get_queue_length(struct COMMON_QUEUE *q) {
    int count;
    struct COMMON_QUEUE *p = q->q_node;
    count = 0;

    while (p->next != NULL) {
        count += 1;
        p = p->next;
    }

    return count;
}

指针p将沿着列表步进,而不会修改沿途的q_node指针。

C_enqueue中有类似的错误。您确实希望使用单独的指针来遍历列表,而不是在遍历期间分配q->q_node。您可以同样修复C_enqueue

p = q->q_node;
while (p->next != NULL) {
    p = p->next;
}
p->next = new_node;     /* append the new node after where the list traversal stopped */
new_node->next = NULL;  /* always NULL, because you always insert at the end */

答案 1 :(得分:1)

您的代码的一个问题是您在队列中的迭代是破坏性的:而不是使用临时变量来迭代链表,您可以使用q_node本身执行迭代。这导致C_get_queue_length调用有效地破坏队列,而不释放其节点(内存泄漏)。

以下是如何使用“获取长度”方法非破坏性地迭代列表的示例:

int C_get_queue_length(struct COMMON_QUEUE *q) {
    int count;
    count = 0;
    struct QUEUE_NODE node = q->q_node;
    while (node->next != NULL) {
        count++;
        node = node->next;
    }

    return count;
}

您在创建队列时预先分配一个节点的决定也值得怀疑:看起来头节点未使用,并且也从计数中排除。这使得编写插入和删除节点的代码变得更容易,但是可以通过额外的间接级别(即指向指针的指针)来完成相同的操作。