在 C 中使用两个队列创建堆栈,dequeue 不起作用

creating a stack using two queues in c, dequeue is not working

提问人:shinny.dogma 提问时间:10/31/2023 更新时间:10/31/2023 访问量:37

问:

因此,我正在使用 CLang 中的两个队列创建一个堆栈 我得到了 enqueue dequeue 和 printQueue。 不幸的是,我的一个队列的出列无法正常工作,以下是我到目前为止所写的内容:

int isQueueEmpty(Queue * queue)
{
    if(queue == NULL) return 1;
    else if(queue->head == NULL) return 1;
    else return 0;
}

//// Do not modify this ////
void enqueue(Queue ** queue, void * item)
{
    if(*queue == NULL)
        *queue = malloc(sizeof(Queue));
    if((*queue)->head == NULL)
    {
        (*queue)->head = malloc(sizeof(Node));
        (*queue)->head->data = item;
        (*queue)->head->next = NULL;
        (*queue)->tail = (*queue)->head;
    }
    else
    {
        Node * temp = malloc(sizeof(Node));
        (*queue)->tail->next = temp;
        temp->data = item;
        temp->next = NULL;
        (*queue)->tail = temp;
    }
}

//// Do not modify this ////
void * dequeue(Queue * queue)
{
    if(queue == NULL || queue->head == NULL) return NULL;
    else
    {
        void * temp = queue->head->data;
        Node * tempNode = queue->head;
        queue->head = queue->head->next;
        free(tempNode);
        return temp;
    }
}

void printQueue(Queue * queue)
{
    if(queue!=NULL)
    {
        printf("Queue content: {");
        Node * temp = queue->head;
        for(;temp!=NULL;temp = temp->next)
        {
            printf("%d ", *(int*)(temp->data));
        }
        printf("}\n");
    }
    else
        printf("Uninitailized Queue\n");
}

Queue *q=NULL;
Queue* qu=NULL;

void push(void * item) {
    printf("reeter here\n");
    while(!isQueueEmpty(q)){
        enqueue(&qu, q->head);
        printf("eleq: %d\n", *((int*)dequeue(q)));
    }
    enqueue(&q, item);
    while(!isQueueEmpty(qu)){
        enqueue(&q, qu->head);
        dequeue(qu);
        //printf("elequ: %d\n", *((int*)dequeue(qu)));
    }
    printf("q:\n");
    printQueue(q);
    printf("qu:\n");
    printf("reached end\n");
    printQueue(qu);
}

不幸的是,我的第二个队列的出列没有正确删除元素,导致 pop() 中的第二个循环执行和无限循环。 其次,在对队列进行排队和取消引用后,存储在队列中的数据以地址的形式返回,而不是我输入的内容:

reeter here
q:
Queue content: {1}
qu:
reached end
Uninitailized Queue
reeter here
eleq: 1
q:
Queue content: {21519347601}
qu:
reached end
Queue content: {}
reeter here
eleq: 2
eleq: -159836464
q:
Queue content: {3-1598364641519347601}
qu:
reached end
Queue content: {}
Queue content: {3-1598364641519347601}
3
-159836464
1519347601
reeter here

这是我从我的外壳中收到的结果。因此,我如何首先修复 push() 函数,以便它实际推送和存储所需的数据,以及如何在不使用修改取消队列的情况下正确地取消第二个队列的队列。 谢谢

C 分段-故障 队列 堆栈

评论

2赞 Ted Lyngmo 10/31/2023
当你这样做时,你似乎期望有意义。事实并非如此。你编辑的内存是未初始化的,所以可以指向任何地方。*queue = malloc(sizeof(Queue);if ((*queue)->head == NULL)mallochead
1赞 ikegami 10/31/2023
运行编译的构建非常适合查找和调试这些问题。-fsanitize=address

答:

0赞 storsan 11/27/2023 #1

代码一开始就没有正确地对项目进行排队。在函数中的两个调用中,您传递了一个参数,而它应该作为参数正确地传递给您实际排队的项目。enqueue()push()Node *void *

以下代码更改应该有效:

   void push(void * item) {
    while(!isQueueEmpty(q)){
        enqueue(&qu, q->head->data);
        printf("eleq: %d\n", *((int*)dequeue(q)));
    }
    enqueue(&q, item);
    while(!isQueueEmpty(qu)){
        enqueue(&q, qu->head->data);
        printf("elequ: %d\n", *((int*)dequeue(qu)));
    }
    printf("q:\n");
    printQueue(q);
    printf("qu:\n");
    printf("reached end\n");
    printQueue(qu);
}

由于您没有分享声明的样子,因此我使用声明为 from 进行了测试,现在调用可以正常工作。对于将项目 1 推送到 4 的测试,在程序结束时从队列的前面删除项目将模拟堆栈排序:itemitemint *main()push()main()q

$./stackqtest.exe
q:
Queue content: {1 }
qu:
reached end
Uninitailized Queue
eleq: 1
elequ: 1
q:
Queue content: {2 1 }
qu:
reached end
Queue content: {}
eleq: 2
eleq: 1
elequ: 2
elequ: 1
q:
Queue content: {3 2 1 }
qu:
reached end
Queue content: {}
eleq: 3
eleq: 2
eleq: 1
elequ: 3
elequ: 2
elequ: 1
q:
Queue content: {4 3 2 1 }
qu:
reached end
Queue content: {}
0赞 chqrlie 11/28/2023 #2

该函数存在一个问题:当从队列中弹出最后一个元素时,它不会更新指针。由于首先实现测试,这不会导致问题,但在这种情况下,创建悬空指针是有风险的。dequeuetailenqueueheadtail

我知道您不应该修改这些功能,但这是出于教育目的的修改版本:

void *dequeue(Queue *queue)
{
    if (queue == NULL || queue->head == NULL) {
        return NULL;
    } else {
        Node *tempNode = queue->head;
        queue->head = queue->head->next;
        if (!queue->head)
            queue->tail = NULL;
        void *temp = tempNode->data;
        free(tempNode);
        return temp;
    }
}

还要注意以下问题:enqueue

  • 多次取消引用函数参数既麻烦又容易出错。
  • 初始化代码应进行因式分解
  • 应测试并报告分配错误:

以下是修改后的版本供您研究:

int enqueue(Queue **queue_p, void *item)
{
    Queue *queue = *queue_p;

    if (*queue == NULL) {
        *queue_p = queue = malloc(sizeof(*queue));
        if (queue == NULL) {
            // allocation error, report failure
            return -1;
        }
    }
    Node *node = malloc(sizeof(*node));
    if (node == NULL) {
        // allocation error, report failure
        return -1;
    }
    node->data = item;
    node->next = NULL;
    if (queue->head == NULL) {
        queue->tail = queue->head = node;
    } else {
        queue->tail = queue->tail->next = node;
    }
    return 0;
}

关于您的代码,该函数存在几个问题:push()

  • 您排队而不是 .实际上,您应该使用 的返回值,而不是破坏封装。当前代码将指针排入队列,该指针将由 释放,从而导致未定义的行为。q->headq->head->datadequeue()dequeue

这是修改后的版本:push()

void push(void *item)
{
    printf("reenter here\n");
    while (!isQueueEmpty(q)) {
        int *data = dequeue(q);
        enqueue(&qu, data);
        //printf("eleq: %d\n", *data);
    }
    enqueue(&q, item);
    while (!isQueueEmpty(qu)) {
        int *data = dequeue(qu);
        enqueue(&q, data);
        //printf("elequ: %d\n", *data);
    }
    printf("q:\n");
    printQueue(q);
    printf("qu:\n");
    printQueue(qu);
    printf("reached end\n");
}