Home > database >  How to sort a doubly linked list with the nodes instead of the node's values
How to sort a doubly linked list with the nodes instead of the node's values

Time:10-31

I am trying to sort a doubly linked list with the nodes for an assignment because thats what the spec wants me to do. I thought to basically make a new list with the sorted and then assign the head and tail

The two .h files of my program:

#ifndef SN_H
#define SN_H

#include <string>
#include <sstream>

//SortNode class implementation here
template <class T>
class SortNode
{
    protected:
        T value;
    public:
        SortNode<T> * next;
        SortNode<T> * prev;
        SortNode(T);
        std :: string print();
        T getValue();
};

#include "SortNode.cpp"

#endif

#ifndef DLL_H
#define DLL_H

#include "SortNode.h"

template <class T>
class SortList 
{
    private:
        bool ascending;
        SortNode<T> * head;
        SortNode<T> * tail;

    public:
        SortList(bool);
        void add(SortNode<T>* a) ;
        SortNode<T>* remove(T val);  
        void setAsc(bool a);
        void sort() ;
        string print() ;
        SortNode<T>*getHead() ;
        string debug() ;

};


#include "SortList.cpp"

#endif

I have tried to sort it like i described but then it gets stuck in a loop and don't have an idea how to do this.

This is the sort function that gives me problems.

template <class T>
void SortList<T> :: sort()
{

cout<<"above if "<<endl;
    if (ascending == true)
    {
        SortNode<T> * node = head, *ptr = NULL ,*sortedh = NULL, *sortedt = NULL, *newnode = NULL;
        
        while (node != NULL)
        {
            newnode = node;
           
            if (!sortedh)
            {
                sortedh = node;
                sortedt = node;
            }
            else
            {
               
                ptr = head;

                while (ptr!= NULL && ptr -> getValue() < newnode -> getValue())
                {
                    ptr = ptr -> next;
                }

                if (!ptr)
                {
                    sortedt -> next = newnode;
                    newnode ->prev = sortedt;
                    sortedt = newnode;

                }
                else
                {
                    if (ptr ->prev == NULL)
                    {
                        newnode -> next = ptr;
                        ptr -> prev =newnode;
                        sortedh = newnode;
                    }
                    else
                    {
                        ptr -> prev -> next = newnode;
                        newnode -> prev =ptr -> prev;
                        newnode -> next =ptr;
                        ptr -> prev = newnode;
                    }
                    
                }


            }
            
            
            node = node -> next;
        }

      
    }
  
    

}

Any help will be appreciated.

CodePudding user response:

The code has bugs.

For example in this code snippet there are even two bugs.

        if (!sortedh)
        {
            sortedh = node;
            sortedt = node;
        }
        else
        {
           
            ptr = head;
            //...

Instead you need to write

        if (!sortedh)
        {
            sortedh = node;
            sortedt = node;
            node->next = nullptr;
        }
        else
        {
           
            ptr = sortedh;
            //...

Or in this if statement

if (!ptr)
{
    sortedt -> next = newnode;
    newnode ->prev = sortedt;
    sortedt = newnode;
}

you forgot to set the data member next of the node pointed to by the pointer newnode like

if (!ptr)
{
    sortedt -> next = newnode;
    newnode ->prev = sortedt;
    newnode->next = nullptr; 
    sortedt = newnode;
}

Or in this if statement

if (ptr ->prev == NULL)
{
    newnode -> next = ptr;
    ptr -> prev =newnode;
    sortedh = newnode;
}

you forgot to set the data member prev of the node pointed to by the pointer newnode as for example

newnode -> next = ptr;
newnode->prev = ptr->prev; or newnode->prev = nullptr;

And there is one more problem. The data member next of the node pointed to by the pointer node can be changed. So this statement

node = node -> next;

can result in that the pointer node can point to an already processed node.

Also the function does not set the pointers head and tail.

Here is a demonstration program that shows how the function that implements the insertion sort method can be defined. To simplify writing the program I have made some minor changes in the class definitions.

#include <iostream>
#include <cstdlib>
#include <ctime>

//SortNode class implementation here
template <class T>
class SortNode
{
protected:
    T value;
public:
    SortNode *prev;
    SortNode *next;

    SortNode( const T &value, SortNode *prev = nullptr, SortNode *next = nullptr )
    {
        this->value = value;
        this->prev  = prev;
        this->next  = next;
    }

    const T & getValue() const
    {
        return value;
    }

    T & getValue()
    {
        return value;
    }
};

template <class T>
class SortList
{
private:
    bool ascending = true;
    SortNode<T> *head = nullptr;
    SortNode<T> *tail = nullptr;

public:
    SortList() = default;
    void add( const T &value )
    {
        SortNode<T> *new_node = new SortNode<T>{ value, tail, nullptr };

        if (!head)
        {
            head = new_node;
        }
        else
        {
            tail->next = new_node;
        }

        tail = new_node;
    }

    SortNode<T> *remove( T val );
    void setAsc( bool a );
    void sort();
    std::ostream &print( std::ostream &os = std::cout ) const
    {
        for (SortNode<T> *current = head; current != nullptr; current = current->next)
        {
            os << current->getValue() << " -> ";
        }

        return os << "null";
    }
    SortNode<T> *getHead();
};

template <class T>
void SortList<T> ::sort()
{
    if (ascending)
    {
        SortNode<T> *node = head, *sortedh = nullptr, *sortedt = nullptr;

        while (node != NULL)
        {
            SortNode<T> *newnode = node;
            SortNode<T> *next = node->next;

            if (!sortedh)
            {
                sortedh = node;
                sortedt = node;
                node->next = nullptr;
            }
            else
            {
                SortNode<T> *ptr = sortedh;

                while (ptr != NULL && !( newnode->getValue() < ptr->getValue() ) )
                {
                    ptr = ptr->next;
                }

                if (!ptr)
                {
                    sortedt->next = newnode;
                    newnode->prev = sortedt;
                    newnode->next = nullptr;
                    sortedt = newnode;
                }
                else
                {
                    if (ptr->prev == NULL)
                    {
                        newnode->next = ptr;
                        newnode->prev = nullptr;
                        ptr->prev = newnode;
                        sortedh = newnode;
                    }
                    else
                    {
                        ptr->prev->next = newnode;
                        newnode->prev = ptr->prev;
                        newnode->next = ptr;
                        ptr->prev = newnode;
                    }

                }
            }

            node = next;
        }

        head = sortedh;
        tail = sortedt;
    }
}

int main()
{
    SortList<int> list;

    const int N = 20;

    srand( ( unsigned int )time( nullptr ) );
    for (int i = 0; i < N; i  )
    {
        list.add( rand() % N );
    }

    list.print() << '\n';

    list.sort();

    list.print() << '\n';
}

The program output might look like

17 -> 12 -> 0 -> 12 -> 8 -> 8 -> 8 -> 13 -> 4 -> 7 -> 8 -> 11 -> 7 -> 8 -> 18 -> 4 -> 16 -> 18 -> 18 -> 3 -> null
0 -> 3 -> 4 -> 4 -> 7 -> 7 -> 8 -> 8 -> 8 -> 8 -> 8 -> 11 -> 12 -> 12 -> 13 -> 16 -> 17 -> 18 -> 18 -> 18 -> null
  • Related