繁体   English   中英

值未保存在 C 的队列中

[英]Values aren't being saved in a queue in C

我正在尝试使用链表在 C 中实现一个队列。 我通过 C 可视化器运行我的代码,似乎 AE 值没有被保存。 如,一个节点将包含字母 A,然后当 queue_enqueue 再次被调用时,会创建另一个节点来保存字母 B,然后包含 A 的前一个节点消失了......我的代码包含其他函数,如出队和一个检查队列是否为空,但我将它们取出以保持我的代码简短,并且它们独立于此处提供的功能。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

struct node {
    struct node *next;
    struct node *prev;
    char *value;
};

// The type for a list.
typedef struct list {
    struct node head;
} List;

typedef struct queue {
    List *list;
} Queue;


Queue *queue_create(void) {
    Queue *q = (Queue*)malloc(sizeof(struct queue));
    List *ptr = (List*)malloc(sizeof(struct list));
    q->list = ptr;
    q->list->head.next = NULL;
 
    return q;
}

void queue_destroy(Queue *q) {
    free(q->list->head.value);
    free(q);
}

void queue_enqueue(Queue *q, const char *value) {
    struct node *temp;
    temp = malloc(sizeof(struct node));
    temp->value = strdup(value);
    temp->next = NULL;

    q->list->head.next = temp;
    q->list->head.value = temp;
}

int main(void) {
    // Create an empty queue.
    Queue *q = queue_create();

    // Add the values A, B, ..., Z to the queue.
    char str[] = "A";
    for (char ch = 'A'; ch <= 'E'; ch++) {
        str[0] = ch;
        queue_enqueue(q, str);
    }

    // Clean up.
    queue_destroy(q);

    return 0;
}

为了简化您的问题,您应该从单链表开始,在您的示例中,不需要使用char*作为节点值:

struct node {
    struct node* next;
    char value;
};

您可能还想为您的列表添加一个元素计数器:

typedef struct list {
    struct node *head;
    size_t num;
}

和一个 function 来创建一个具有给定值的新节点:

struct node *node_create(char value) {
    struct node *nd = malloc(sizeof(struct node));

    if (nd)
        nd->value = value;

    return nd;
}

魔法发生在插入 function 中,但它根本不是火箭科学。 您可以在head指向的位置(空列表)或列表末尾创建新节点。

void list_insert(List *list, char value) {
    if (!list)
        return;

    if (!list->head) {
        // first element of list
        list->head = node_create(value);
        if (list->head)
            list->num++;
    }
    else {
        // move to the end of the list
        struct node *nd = list->head;
        
        while (nd->next) {
            nd = nd->next;
        }
        
        nd->next = node_create(value);
        if (nd->next)
             list->num++;
    }
}

还要确保使用一些list_create function 正确初始化您的列表,并且在清理列表时注意释放列表本身的 memory 之前释放所有列表元素

您没有正确链接链指针。

并且,设置q->list->head.value = temp; 甚至不会编译。

对于双向链表,重用节点结构作为前/后指针(例如 prev/next)是可行的,但不清楚。 最好稍微重新定义List以使用前/后 - 它更清晰。

您的销毁代码也是错误的。

追加到列表时,第一次与后续的略有不同。


这是重构的代码。

由于您的代码没有更改列表的任何next/prev指针或 temp 的next/prev指针,因此不清楚您是要排入列表的前面还是后面,所以我添加了这两个函数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

struct node {
    struct node *next;
    struct node *prev;
    char *value;
};

// The type for a list.
typedef struct list {
    struct node *front;
    struct node *back;
    size_t count;
} List;

typedef struct queue {
    List *list;
} Queue;

Queue *
queue_create(void)
{
    Queue *q = malloc(sizeof(*q));
    q->list = calloc(1,sizeof(List));

    return q;
}

void
queue_destroy(Queue *q)
{
    List *list = q->list;
    struct node *cur;
    struct node *next;

    if (list != NULL)
        cur = list->front;
    else
        cur = NULL;

    for (;  cur != NULL;  cur = next) {
        next = cur->next;
        free(cur->value);
    }

    free(list);
    free(q);
}

struct node *
node_create(const char *value)
{
    struct node *temp = calloc(1,sizeof(*temp));

    temp->value = strdup(value);

    return temp;
}

void
queue_enqueue_front(Queue *q,const char *value)
{
    struct node *temp = node_create(value);
    List *list = q->list;

    temp->next = list->front;
    if (list->front != NULL)
        list->front->prev = temp;
    list->front = temp;

    if (list->back == NULL)
        list->back = temp;

    list->count += 1;
}

void
queue_enqueue_back(Queue *q,const char *value)
{
    struct node *temp = node_create(value);
    List *list = q->list;

    temp->prev = list->back;
    if (list->back != NULL)
        list->back->next = temp;
    list->back = temp;

    if (list->front == NULL)
        list->front = temp;

    list->count += 1;
}

void
queue_print_fwd(Queue *q,const char *who)
{
    List *list = q->list;
    struct node *cur;

    if (who != NULL)
        printf("%s:\n",who);

    for (cur = list->front;  cur != NULL;  cur = cur->next)
        printf("  %s\n",cur->value);
}

void
queue_print_rev(Queue *q,const char *who)
{
    List *list = q->list;
    struct node *cur;

    if (who != NULL)
        printf("%s:\n",who);

    for (cur = list->back;  cur != NULL;  cur = cur->prev)
        printf("  %s\n",cur->value);
}

int
main(void)
{
    // Create an empty queue.
    Queue *q = queue_create();

    // Add the values A, B, ..., Z to the queue.
    char str[] = "A";

    for (char ch = 'A'; ch <= 'E'; ch++) {
        str[0] = ch;
        queue_enqueue_back(q, str);
#ifdef DEBUG
        queue_print_fwd(q,"pushback");
#endif
    }

    for (char ch = 'K'; ch >= 'F'; ch--) {
        str[0] = ch;
        queue_enqueue_front(q, str);
#ifdef DEBUG
        queue_print_fwd(q,"pushfront");
#endif
    }

    queue_print_fwd(q,"Forward");
    queue_print_rev(q,"Reverse");

    // Clean up.
    queue_destroy(q);

    return 0;
}

这是程序 output:

Forward:
  F
  G
  H
  I
  J
  K
  A
  B
  C
  D
  E
Reverse:
  E
  D
  C
  B
  A
  K
  J
  I
  H
  G
  F

暂无
暂无

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

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