使用 2 个队列的出队函数遇到段错误?

Posted

技术标签:

【中文标题】使用 2 个队列的出队函数遇到段错误?【英文标题】:dequeueing function working with 2 queues encounters segfault? 【发布时间】:2022-01-04 15:08:00 【问题描述】:

下面的函数应该使一个由 2 个队列组成的结构出队。每次我们将第一个队列出队时,它的后部都需要成为第二个队列的前部。本质上将第二个队列中的第一个元素移动到第一个队列中作为其后部。我想出了下面的算法:

int dequeue(queue* Q1,queue* Q2)

    node* temp;

    if(Q1->rear=NULL)
        return 0;
    

    if(count<3)
        temp=Q1->front;
        Q1->front=Q1->front->next;
        free(temp);
        count--;
        return 1;
    

    if(count>=3)

        temp=Q1->front;
        Q1->front=Q1->front->next;
        free(temp);

        Q1->rear->next=Q2->front;
        Q1->rear=Q1->rear->next;
        Q2->front=Q2->front->next;
        Q1->rear->next=NULL;

        if(Q2->front=NULL)
            Q2->rear=NULL;
        

        count--;
        return 1;

    

它在Q1-&gt;rear-&gt;next=Q2-&gt;front; 处给出一个段错误

有没有其他方法可以实现这一点?

【问题讨论】:

对我来说这个条件 if(count 还有一个错字 if(Q2->front=NULL) Q2->rear=NULL; 你使用的是赋值而不是比较 不清楚变量count是否表示两个队列中的节点总数。 @VladfromMoscow 这是一个全局变量,表示两个队列中的节点总数 当函数依赖于全局变量时,这是一种不好的方法。 【参考方案1】:

对于初学者来说,if 语句的条件有一个错字

    if(Q2->front=NULL)
        Q2->rear=NULL;
    

您使用的是赋值而不是比较。

这个if语句还有一个bug

if(count<3)
    temp=Q1->front;
    Q1->front=Q1->front->next;
    free(temp);
    count--;
    return 1;

q1-front在此声明之后

    Q1->front=Q1->front->next;

可以等于NULL。在这种情况下,您还需要将Q1-&gt;rare 设置为NULL

但无论如何你使用 if 语句的方法

if(count<3)
    temp=Q1->front;
    Q1->front=Q1->front->next;
    free(temp);
    count--;
    return 1;


if(count>=3)

    temp=Q1->front;
    Q1->front=Q1->front->next;
    free(temp);
    //...

使代码不那么清晰,并且容易出错。

我会这样写函数

int dequeue( queue *q1, queue *q2 )

    int success = q1->front != NULL;

    if ( success )
    
        if ( q2->front != NULL )
        
            q1->rear->next = q2->front;
            q1->rear = q1->rear->next;  

            q2->front = q2->front->next;

            if ( q2->front == NULL ) q2->rear = NULL;

            q1->rear->next = NULL;
        

        node *tmp = q1->front;

        q1->front = q1->front->next;
        if ( q1->front == NULL ) q1->rear = NULL;

        free( tmp );

        --count;
    

    return success;

请注意,当函数依赖于全局变量(我的意思是变量count)时,这是一种不好的编程习惯。您可以避免在结构中包装队列和变量count 的这种情况。

这是一个演示程序,展示了该功能的实际作用。

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

typedef struct node

    int data;
    struct node *next;
 node;

typedef struct queue

    node *front;
    node *rear;
 queue;

size_t count;

int dequeue( queue *q1, queue *q2 )

    int success = q1->front != NULL;

    if ( success )
    
        if ( q2->front != NULL )
        
            q1->rear->next = q2->front;
            q1->rear = q1->rear->next;  

            q2->front = q2->front->next;

            if ( q2->front == NULL ) q2->rear = NULL;

            q1->rear->next = NULL;
        

        node *tmp = q1->front;

        q1->front = q1->front->next;
        if ( q1->front == NULL ) q1->rear = NULL;

        free( tmp );

        --count;
    

    return success;


int push( queue *q, int data )

    node *new_node = malloc( sizeof( node ) );
    int success = new_node != NULL;
    
    if ( success )
    
        new_node->data = data;
        new_node->next = NULL;
        
        if ( q->rear == NULL )
        
            q->front = new_node;
        
        else
        
            q->rear->next = new_node;
        
        
        q->rear = new_node;
        
        ++count;
    
    
    return success;


int empty( const queue *q )

    return q->front == NULL;


int front( queue *q )

    return q->front->data;


int main( void )

    queue q1 =  .front = NULL, .rear = NULL ;  
    queue q2 =  .front = NULL, .rear = NULL ;  
    
    const int N = 10;
    
    for ( int i = 0; i < N; i++ )
    
        if ( i < N / 2 ) push( &q1, i );
        else push( &q2, i );
    
    
    while ( !empty( &q1 ) )
    
        printf( "%d ", front( &q1 ) );
        dequeue( &q1, &q2 );
    
    
    putchar( '\n' );

    for ( int i = 0; i < N; i++ )
    
        if ( i < N / 2 ) push( &q1, i );
        else push( &q2, i );
    
    
    while ( !empty( &q1 ) )
    
        printf( "%d ", front( &q1 ) );
        dequeue( &q1, &q2 );
    
    
    putchar( '\n' );

程序输出是

0 1 2 3 4 5 6 7 8 9 
0 1 2 3 4 5 6 7 8 9

同样的代码被执行了两次,说明函数dequeue工作正常。

【讨论】:

以上是关于使用 2 个队列的出队函数遇到段错误?的主要内容,如果未能解决你的问题,请参考以下文章

队列练习之Example001-用两个栈 s1 和 s2 来模拟一个队列,实现队列的出队入队队是否为空的运算

在 Linux 中控制信号量队列中的出队顺序

堆和优先队列

为啥我在 c 中遇到 atoi 的段错误?

64位平台上,函数返回指针时遇到的段错误问题

使用 CUDA 流时的段错误