简体   繁体   English

值未保存在 C 的队列中

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

I'm trying to implement a queue in C using a linked list.我正在尝试使用链表在 C 中实现一个队列。 I ran my code through a C visualizer and it seems that the values AE aren't being saved.我通过 C 可视化器运行我的代码,似乎 AE 值没有被保存。 As in, one node will contain the letter A then when queue_enqueue is called again, another node is created that holds the letter B and then the previous node that contained A just, disappears... My code contains other functions like dequeue and one to check if the queue is empty, but I took them out to keep my code short and they are independent of the functions provided here.如,一个节点将包含字母 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;
}

To simplify your problem you should begin with a single-linked list and in your example there is no need to use char* as node value:为了简化您的问题,您应该从单链表开始,在您的示例中,不需要使用char*作为节点值:

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

You also might want to add a element counter for your list:您可能还想为您的列表添加一个元素计数器:

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

and a function to create a new node with the given value:和一个 function 来创建一个具有给定值的新节点:

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

    if (nd)
        nd->value = value;

    return nd;
}

The magic happens in the insert function but it is no rocket science at all.魔法发生在插入 function 中,但它根本不是火箭科学。 You either create your new node where head is pointing (empty list) or at the end of the list.您可以在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++;
    }
}

Also make sure to properly initialize your list with some list_create function and when cleaning the list take care to free all list elements before releasing the memory of the list itself还要确保使用一些list_create function 正确初始化您的列表,并且在清理列表时注意释放列表本身的 memory 之前释放所有列表元素

You are not linking the chain pointers correctly.您没有正确链接链指针。

And, setting q->list->head.value = temp;并且,设置q->list->head.value = temp; won't even compile.甚至不会编译。

For a doubly linked list, reusing a node struct as the front/back pointers (eg prev/next) is doable but unclear.对于双向链表,重用节点结构作为前/后指针(例如 prev/next)是可行的,但不清楚。 Better to redefine List slightly to use front/back--it's clearer.最好稍微重新定义List以使用前/后 - 它更清晰。

Your destroy code is also wrong.您的销毁代码也是错误的。

When appending to a list, the first time is slightly different than subsequent ones.追加到列表时,第一次与后续的略有不同。


Here's the refactored code.这是重构的代码。

Since your code didn't change any of the list's next/prev pointers or temp's next/prev pointers, it wasn't clear whether you wanted to enqueue to the front or the back of the list, so I added both functions.由于您的代码没有更改列表的任何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;
}

Here's the program output:这是程序 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