【问题标题】:Converting linked list into queue (moving the nodes)将链表转换为队列(移动节点)
【发布时间】:2015-10-31 08:32:30
【问题描述】:

我需要一些关于从链表创建队列的逻辑帮助。所以我从问题中得到了所有这些代码:

typedef struct _listnode
{
    int item;
    struct _listnode *next;
} ListNode; // You should not change the definition of ListNode

typedef struct _linkedlist
{
    int size;
    ListNode *head;
} LinkedList;   // You should not change the definition of LinkedList

typedef struct _queue
{
    LinkedList ll;
} Queue;

通过使用 enqueue、dequeue 和 isEmptyQueue,我应该从链表创建一个队列。

所以我得到的逻辑是:

 Loop thru list size
      enqueue linked list head node
      removeNode to update linkedlist head node

这个逻辑正确吗?我需要抢先一步,提前致谢。

所以我想出了这段代码来从链表创建一个队列:

但是,它使我的程序崩溃而没有错误消息。我尝试使用虚拟值 enqueue(q,1) ,但它仍然崩溃。有什么想法吗?

【问题讨论】:

  • "将删除的节点从链表中入队" 错误,什么?
  • @alk 我认为这意味着:将已从链表中删除的节点入队。
  • @alk,它更像是“enqueue [从链表中移除的节点]
  • 对不起,我的意思是我将linkedlist->head排入队列,然后我执行removeNode直到linkedlist size = 0
  • 对不起,但我似乎完全错过了这个问题的重点......:-S

标签: c pointers linked-list queue


【解决方案1】:

我认为您的逻辑是正确的,但我会添加更多细节以使其更易于编码

Loop through the link list, selecting nodes one by one (until NULL)
    select a node;
    enqueue the value to the queue;
    Free the memory of that enqueued node;
    adjust the pointers to point to the next node in the linked list;

编辑

让我们稍微详细地写一下算法

while(head != NULL)
//Loop to traverse the linked list, just as you would while displaying each node

    enqueue( que, head->item);
    //This function will work just like a normal enqueue() function
    //It should take the item, and insert it in the queue and nothing else
    //I would recommend use an array for the queue

    temp = head;          //save the current node address to free later
    head = head -> next;  //go to next node in the linked list
    free(temp);           //free the previous node

【讨论】:

  • while (l->size) { enqueue(q, ll->head->item);移除节点(l,0);我提出了这个,但它使我的程序崩溃。有什么想法吗?
  • @20Cents, wat removeNode 应该做的。
  • 它是作为问题的一部分发布的。基本上它只是从具有指定索引的链表中删除节点。我正在执行 removeNde(l, 0) 所以基本上我从前面一直删除,直到 size = 0
  • Sorry sorry 我在实际编写代码并忘记更新后才意识到问题中的伪代码是错误的。我想做的是从链表创建一个队列。但是您提供的解决方案仍然会使程序崩溃:(
  • @20Cents 你已经从询问算法到询问代码。最好用实际代码发布一个新问题(或至少用实际代码更新当前问题)。
【解决方案2】:

说实话我什么都不懂。

您不需要将链表转换为队列。您只需用列表初始化队列的数据成员ll

这是一个演示程序

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

typedef struct _listnode
{
    int item;
    struct _listnode *next;
} ListNode; // You should not change the definition of ListNode

typedef struct _linkedlist
{
    int size;
    ListNode *head;
} LinkedList;   // You should not change the definition of LinkedList


int insert( LinkedList *ll, int index, int value )
{
    if ( index < 0 || index > ll->size ) return -1;

    ListNode *tmp = malloc( sizeof( ListNode ) );

    tmp->item = value;

    if ( ll->head == NULL )
    {
        tmp->next = ll->head;
        ll->head = tmp;
    }
    else
    {        
        ListNode *current = ll->head; 

        while ( --index ) current = current->next;
        tmp->next = current->next;
        current->next = tmp;
    }

    ++ll->size;

    return 0;
}

void list_output( const LinkedList *ll )
{
    for ( ListNode *current = ll->head; current != NULL; current = current->next )
    {
        printf( "%d ", current->item );
    }

    printf( "\n" );
}

typedef struct _queue
{
    LinkedList ll;
} Queue;

void queue_output( const Queue *q )
{
    list_output( &q->ll );
}    

int main( void )
{
    LinkedList lst = { 0, 0 };
    const int N = 10;

    for ( int i = 0; i < N; i++ ) insert( &lst, i, i );

    list_output( &lst );

    Queue q = { lst };

    lst = ( LinkedList )  { 0, 0 };

    queue_output( &q );

     // call here the method that free allocated memory of the queue

    return 0;
}

它的输出是

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

即队列现在是已分配节点的所有者。该列表又是空的。

这意味着您确实将列表转换为队列。

如果您的意思是将列表的元素复制到队列中(与转换操作相比,这是一个不同的操作),那么逻辑如下

以与遍历列表相同的方式遍历列表以输出其元素并为列表节点的每个数据值调用队列的方法enqueue

for ( ; head != NULL; head = head->next )
{
    enqueue( que, head->x );
}

列表本身将保持不变。

如果复制操作后需要删除链表的节点,可以调用链表中执行该操作的方法。

考虑到不需要动态分配列表或队列。例如,列表的声明可能看起来像

typedef struct _linkedlist
{
    int size;
    ListNode *head;
} LinkedList;   // You should not change the definition of LinkedList

LinkedList lst = { 0, 0 };

动态分配的是链表的节点。

同样适用于队列。

您可以通过以下方式声明队列

typedef struct _queue
{
    LinkedList ll;
} Queue;

Queue q = { { 0, 0 } };

如果你有一个列表,那么将它转换为队列就足够了

q.ll = lst;
lst = ( LinkedList ) { 0, 0 };

也是这个方法

void enqueue(Queue *que, int x)
{
    int counter = 0;
    insert(&(que->l), counter++, x);
}

没有意义。而且队列没有数据成员l。它有数据成员ll

您需要将节点附加到队列中。所以你必须使用队列的数据成员size的值作为必须插入新元素的索引。

所以方法应该是这样的

void enqueue( Queue *que, int x )
{
    insert( &que->ll, que->ll.size, x) ;
}

【讨论】:

  • 实际上问题是通过将存储在链表中的所有整数排队来创建一个队列(基于链表)
  • @20Cents 表示只需将列表的数据值复制到队列中即可。
  • 我明白了。好像我误解了这个问题:(。所以我只需要在我的 enqueue() 中实现 for 循环?
  • @20Cents 我想指出,如果你在复制后不需要链表,那么你也需要释放节点。
  • 等一下,我很困惑。所以从 createQueueFromLinkedList() 开始,我正在执行你的 for 循环。然后在 enqueue() 中,我正在执行 insertNode()。我说的对吗?
【解决方案3】:
void createQFrmLl(LinkedList *ll, Queue * q)
{
    while (ll->size) 
    {
        enqueue(q, ll->head->item); <-- CHANGE done here (passing 'q' instead of &q)
        removeNode(ll, 0);
    }
}

enqueue() 需要 'Queue *' 但你正在传递 'Queue **',因此,在 enqueue() 内部取消引用 q->ll 会崩溃,因为 q 是错误的内存地址。

【讨论】:

  • 所以基本上当我使用 &q 这意味着它是队列**?
  • 你是对的。在 createQFrmLL() 中,第二个输入参数是 'Queue *q',当在函数内部时,您使用 &q -> 这意味着包含 'Queue *'(指向 Queue 的地址)的内存地址,因此它变为 'Queue **'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 2019-12-23
  • 1970-01-01
相关资源
最近更新 更多