我需要一些关于逻辑的帮助,我需要从链表中创建一个队列。所以我得到了问题中的所有这些代码:
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),但它仍然崩溃。有什么想法吗?
我认为您的逻辑是正确的,但我会添加更多细节,使代码更容易编写
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
说实话,我什么都不懂。
您不需要将链接列表转换为队列。您只需要使用列表初始化队列的数据成员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) ;
}
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是错误的内存地址。