C、如何从队列中移除元素?

问题描述

更新:我们相信在这两种解决方案中都发现了一些错误,也邀请您分享您的想法:)

我试图实现我自己的数据结构,它结合了 C 中的列表和队列。

我的数据结构有 2 个指针,front 指向队列中最老的成员,rear 指向新添加的成员,每个成员都指向 在它之后插入的成员

例如,如果我插入 1 然后 2 然后 3,我将有:

NULL <-3 <- 2 <- 1 // 1 is front and 3 is rear.

现在我想支持从这个 DS 中删除元素,所以我开始实现它并解析了数十种边缘情况,例如:

  1. 如果成员是前部,则更改 DS 的前部并释放成员,但如果前部现在为空,则将后部也更改为空,否则其他代码将无法按预期工作。

  2. 如果该成员处于中间发布,则返回上一个成员并更新其下一个但这似乎很难

  3. 后部成员几乎相同,除了我们现在需要更新后部并且只更改指向其右侧元素的指针(NULL 位于其左侧)

我该怎么做这样的事情?

几天来我已经有了数十个想法和实现,但都失败了,或者我做了一些非常糟糕的事情,使运行时复杂度更高,或者我写了 170 行,其中存在矛盾并留下未完成的条件(通过使用 2 个指针)。

有什么帮助吗?

struct queue_node
{
    int key;
    struct queue_node *next;
};

struct queue
{
    int queue_size;
    struct queue_node *front,*rear;
};

int requeue(struct queue *q,int val)
{
    struct queue_node *tmp = q->front;
    while (tmp!=NULL)
    {
        if (tmp->key==val)
        {
            if (tmp==q->front)
            {
                q->front=tmp->next;
                if (q->front == NULL)
                {
                    q->rear = NULL;
                }
                free(tmp);
            }else if (tmp == q->rear)
            {

            }
            return 0; // found
        }
        tmp=tmp->next;
    }
    return -1; // not found
}

解决方法

val attributes = window.attributes
attributes.screenBrightness = 1f
window.attributes = attributes

结果:

typedef struct queue_node
{
    int key;
    struct queue_node *next;
}node;

typedef struct 
{
    size_t size;
    node *head;
    node *tail;
}queue;

node *append(queue *q,int key)
{
    node *n = malloc(sizeof(*n));
    node *c = q -> head;
    if(n)
    {
        if(!q -> head) q -> head = n;
        else
        {
            while(c -> next) c = c -> next;
            c -> next = n;
        }
        n -> key = key;
        n -> next = NULL;
        q -> size++;
        q -> tail = n;
    }
    return n;
}

int removenode(queue *q,int key)
{
    node *n = q -> head,*p = q -> head;
    int result = 0;
    while(n)
    {
        if(n -> key == key)
        {
            if(n == p)
            {
                q -> head = n -> next;
                if(!n -> next) q -> tail = n;
            }
            else
            {
                p -> next = n -> next;                
                if(!p -> next) q -> tail = p;
            } 
            free(n);
            q -> size--;
            result = 1;
            break;
        }
        if(p != n) p = p -> next;
        n = n -> next;
    }
    return result;
}

void printqueue(queue *q)
{
    node *n = q -> head;
    printf("The queue:\n");
    while(n)
    {
        printf("Node key = %d\n",n -> key);
        n = n -> next;
    }
    printf("--------------\n");
    if(q -> head) printf("Head key: %d,Tail key: %d,Queue size: %zu\n -------------\n\n",q -> head -> key,q -> tail -> key,q -> size);
    else printf("Queue empty\n------------\n\n");
}

int main(void)
{
    queue q = {0,};
    append(&q,1);
    append(&q,2);
    append(&q,3);
    append(&q,4);
    printqueue(&q);
    removenode(&q,3);
    printqueue(&q);
    removenode(&q,1);
    printqueue(&q);
    removenode(&q,2);
    printqueue(&q);

}

Program demo

,

可以通过以下方式定义函数

int requeue( struct queue *q,int val )
{
    struct queue_node **current = &q->front;
    struct queue_node *prev = NULL;

    while ( *current && ( *current )->key != val )
    { 
        prev = *current;
        current = &( *current )->next;
    }

    int success = *current == NULL ? -1 : 0;

    if ( success == 0 )
    {
        struct queue_node *tmp = *current;
        *current = ( *current )->next;
        free( tmp );
        --q->queue_size;            

        if ( *current == NULL ) q->rear = prev;
    }

    return success;
}

这是一个演示程序。

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

struct queue_node
{
    int key;
    struct queue_node *next;
};

struct queue
{
    int queue_size;
    struct queue_node *front,*rear;
};

int requeue( struct queue *q,int val )
{
    struct queue_node **current = &q->front;
    struct queue_node *prev = NULL;

    while ( *current && ( *current )->key != val )
    { 
        prev = *current;
        current = &( *current )->next;
    }

    int success = *current == NULL ? -1 : 0;

    if ( success == 0 )
    {
        struct queue_node *tmp = *current;
        *current = ( *current )->next;
        free( tmp );
        --q->queue_size;            

        if ( *current == NULL ) q->rear = prev;
    }

    return success;
}


int push( struct queue *q,int key )
{
    struct queue_node *node = malloc( sizeof( struct queue_node ) );
    int success = node != NULL;
    
    if ( success )
    {
        node->key = key;
        node->next = NULL;
        
        if ( q->rear == NULL )
        {
            q->front = q->rear = node;
        }
        else
        {
            q->rear = q->rear->next = node;
        }

        ++q->queue_size;            
    }
    
    return success;
}

void display( const struct queue *q )
{
    for ( struct queue_node *current = q->front; current; current = current->next )
    {
        printf( "%d -> ",current->key );
    }
    
    puts( "null" );
}

int main(void) 
{
    struct queue q = { .front = NULL,.rear = NULL };
    
    push( &q,1 );
    push( &q,2 );
    push( &q,3 );
    push( &q,4 );
    
    display( &q );
    
    requeue( &q,4 );

    display( &q );

    push( &q,4 );

    display( &q );

    requeue( &q,1 );

    display( &q );

    requeue( &q,3 );

    display( &q );

    requeue( &q,2 );

    display( &q );

    push( &q,4 );
    
    display( &q );
    
    return 0;
}

程序输出为

1 -> 2 -> 3 -> 4 -> null
1 -> 2 -> 3 -> null
1 -> 2 -> 3 -> 4 -> null
2 -> 3 -> 4 -> null
2 -> 4 -> null
2 -> null
null
1 -> 2 -> 3 -> 4 -> null

如果为了测试将函数 printf 的调用添加到函数 requeue 中的此代码段

if ( success == 0 )
{
    struct queue_node *tmp = *current;
    *current = ( *current )->next;
    printf( "tmp->key == %d,tmp == %p\n",tmp->key,( void * )tmp );
    free( tmp );
    --q->queue_size;            

    if ( *current == NULL ) q->rear = prev;
}

那么演示程序的输出可以是这样的

1 -> 2 -> 3 -> 4 -> null
tmp->key == 4,tmp == 0x55b55f9e02c0
1 -> 2 -> 3 -> null
1 -> 2 -> 3 -> 4 -> null
tmp->key == 1,tmp == 0x55b55f9e0260
2 -> 3 -> 4 -> null
tmp->key == 3,tmp == 0x55b55f9e02a0
2 -> 4 -> null
tmp->key == 4,tmp == 0x55b55f9e02c0
2 -> null
tmp->key == 2,tmp == 0x55b55f9e0280
null
1 -> 2 -> 3 -> 4 -> null