user2424370
user2424370

Reputation:

Converting linked list into queue (moving the nodes)

I need some help with the logic whereby I need to create a queue from linked list. So I was given all these code from the question:

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;

And by using enqueue, dequeue and isEmptyQueue, I am supposed to create a queue from linked list.

So the logic that I have gotten is:

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

Is that logic correct? I need a head start and thanks in advance.

So I have came out with this code to create a queue from linked list:

However, it crashes my program with no error message. I tried with dummy value enqueue(q,1) and it still crashes. Any ideas?

Upvotes: 1

Views: 1722

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

Truly speaking I have understood nothing.

You need not to convert a linked list to the queue. All you need is to initialize data member ll of the queue with the list.

Here is a demonstrative program

#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;
}

Its output is

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

That is the queue now is the owner of the allocated nodes. The list in turn is empty.

It means that you indeed converted a list into a queue.

If you mean to copy elements of a list into the queue (it is a different operation compared with the converting operation) then the logic is the following

Traverse the list the same way as you would traverse it to output its element and call method enqueue of the queue for each data value of the node of the list

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

The list itself will be unchanged.

If you need to delete nodes of the list after the copy operation when you can call the method of the list that performs this operation.

Take into account that there is no need to dynamically allocate a list or a queue. For example a declaration of the list could look like

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

LinkedList lst = { 0, 0 };

It is the nodes of the list that are allocated dynamically.

The same is valid for the Queue.

You can declare a queue the following way

typedef struct _queue
{
    LinkedList ll;
} Queue;

Queue q = { { 0, 0 } };

If you have a list then to convert it to the queue it is enough to write

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

Also this method

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

does not make sense. And moreover the Queue does not have data member l. It has data member ll

You need to append nodes to the queue. So you have to use the value of data member size of the queue as an index where the new element must be inserted.

So the method should look like

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

Upvotes: 1

cm161
cm161

Reputation: 510

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() expects 'Queue *' but you are passing 'Queue **', hence, inside enqueue() dereferencing q->ll is crashing since q is wrong memory address.

Upvotes: 0

Haris
Haris

Reputation: 12272

I think your logic is correct, but i would add a little more detail to make it easier to code

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;

Edit

Lets write the algorithm in a little detail

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

Upvotes: 1

Related Questions