简体   繁体   English

链表队列,无限循环

[英]linked-list queue, endless loop

I use nested structure to define the linked-list queue: 我使用嵌套结构定义链表队列:

queue.h: 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: 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;
  }

but when I use it in the main program, then it jumps into a endless loop, after backtracing, and I knew the problem is at: 但是当我在主程序中使用它时,在回溯之后它跳入一个无限循环,我知道问题出在:

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

but it seems correct, but I may make some mistake on my initialization of the two nested struct! 但是这似乎是正确的,但是我在初始化两个嵌套结构时可能会犯一些错误!

PS the I did not list the "free()". PS我没有列出“ free()”。

This loop modifies the list while it traverses it. 该循环在遍历列表时会对其进行修改。 Specifically, it replaces q->q_node with q->q_node->next , which if nothing else will discard your entire loop. 具体来说,它将q->q_node替换为q->q_node->next ,如果没有其他选择,则会丢弃整个循环。

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

If you want to correctly traverse the list, you need to declare a separate pointer that you use for traversal. 如果要正确遍历该列表,则需要声明用于遍历的单独指针。 Something like this: 像这样:

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;
}

The pointer p will step along the list without modifying the q_node pointers along the way. 指针p将沿列表移动,而不会一路修改q_node指针。

You have a similar error in C_enqueue . 您在C_enqueue有类似的错误。 You really want to use a separate pointer to walk the list, and not assign q->q_node during traversal. 您确实想使用一个单独的指针来遍历列表,而不在遍历期间分配q->q_node You can fix your C_enqueue similarly: 您可以类似地修复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 */

One problem with your code is that your iterations through the queue are destructive: rather than using a temporary variable to iterate your linked list, you perform the iteration using the q_node itself. 代码的一个问题是,通过队列的迭代具有破坏性:您使用q_node本身执行迭代,而不是使用临时变量来迭代链接列表。 This leads to C_get_queue_length calls effectively destroying the queue, without freeing its nodes (a memory leak). 这导致C_get_queue_length调用有效地破坏了队列,而没有释放其节点(内存泄漏)。

Here is an example of how to iterate a list non-destructively, using your "get length" method: 这是一个使用“ get 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;
}

Your decision to pre-allocate one node when creating a queue is also questionable: it appears that the head node is unused, and also excluded from the count. 您在创建队列时预分配一个节点的决定也令人怀疑:看来头节点未使用,也被排除在计数之外。 This makes it easier to write the code to insert and delete nodes, but the same could be done with an extra level of indirection (ie a pointer to a pointer). 这使得编写代码来插入和删除节点更加容易,但是同样可以通过额外级别的间接操作(即指向指针的指针)来完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM