0

Hi I am making a custom linked list (for fun!) and want to implement a sort method that sorts the stored data using the stored types > and < operators (will require the type to have these operators overloaded)

What is the best way to do this? I guess the first thing one might jump to would be to compare the current node with the the node to its "right" see if one is greater than the other. Then keep iterating through the list until you don't swap any more nodes. However I am thinking there is probably a more efficient way to do this. Here is my code so far:

#ifndef LIST_HPP
#define LIST_HPP

#include <string>

template <typename T>
class Node;

template <typename T>
class List
{   
    public:
        List();
        ~List();

        bool isEmpty() const;
        T& front();
        T& back();
        inline unsigned int size() const;
        void pushFront(const T& s);
        void removeElement(const T& s);
        void insert(const T& s);
        T popFront();
        const T* each();

    private:
        unsigned int size_;
        Node<T>* head_;
        Node<T>* current_;      
};

template <typename T> List<T>::List() : size_(0), head_(0), current_(0)
{
}

template <typename T> List<T>::~List()
{
    while (isEmpty())
    {
        popFront();
    }
    head_ = 0;
}

template <typename T> bool List<T>::isEmpty() const
{
    return (!size_ || !head_);
}


template <typename T> T& List<T>::front()
{
    if (isEmpty())
        throw std::string("List Empty");

    return head_->data();
}

template <typename T> T& List<T>::back()
{
    Node<T>* cur = head_;

    while (true)
    {
        if (cur->next() == 0)
            return cur->data();

        cur = cur->next();
    }
}

template <typename T> void List<T>::pushFront(const T& s)
{
    current_ = head_ = new Node<T>(s, head_);

    size_++;
}

template <typename T> T List<T>::popFront()
{
    if (isEmpty())
    {
        throw std::string("List Empty");
    }

    Node<T>* current_head = head_;
    current_ = head_ = head_->next();

    T temp = current_head->data();

    delete current_head;

    size_--;

    return temp;
}
template <typename T> const T* List<T>::each()
{
    if (isEmpty())
        return 0;

    if (current_ == 0)
    {
        current_ = head_;
        return 0;
    }

    const T* ret_str = &current_->data();

    current_ = current_->next();

    return ret_str;
}
template <typename T> void List<T>::removeElement(const T& s)
{
    if (isEmpty())
    {
        throw std::string("List Empty");
        return;
    }

    Node<T>* prev = 0, *rnode;

    rnode = head_;

    while (rnode != 0)
    {
        if (rnode->data() == s)
            break;

        prev = rnode;
        rnode = rnode->next();
    }

    if (prev == 0)
    {
        Node<T>* temp = head_;
        current_ =  head_ = head_->next();

        delete temp;        
    }
    else
    {
        prev->next(rnode->next());
        delete rnode;
    }

    size_--;
}
template <typename T> void List<T>::insert(const T& s)
{
    if (isEmpty())
    {
        pushFront(s);
    }
    else if (size_ == 1)
    {
        if (s <= head_->data())
            pushFront(s);
        else
            head_->next(new Node<T>(s, 0));

        size_++;
    }
    else
    {
        Node<T>* current, *prev = 0, *new_node = 0;

        while (current != 0)
        {
            if (s <= current->data())
                break;

            prev = current;
            current = current->next();
        }

        if (prev == 0)
            pushFront(s);
        else
            prev->next(new Node<T>(s, current));

        size_++;

    }

}

template <typename T> unsigned int List<T>::size() const {return size_;}

template <typename T>
class Node
{
    public:
        Node(const T& data, Node<T>* next = 0);
        T& data();
        Node* next();
        void next(Node<T>* n);

    private:
        T data_;
        Node* next_;
};

template <typename T> Node<T>::Node(const T& data, Node* next): data_(data), next_(next)
{
}

template <typename T> void Node<T>::next(Node<T>* n)
{
    next_ = n;
}
template <typename T> Node<T>* Node<T>::next()
{
    return next_;
}
template <typename T> T& Node<T>::data()
{
    return data_;
}
#endif //LIST_HPP 

Surely there is a way to sort with only one iteration through the list? Or maybe not.

Thanks for any help in advance!

4
  • 1
    Well, there isn't. You can only swap with the next node in a single linked list, thereby you need O(n^2) comparisons in worst case. For mergesort/quicksort you must be able to randomly access any item of your container. By the way, the lower-bound for sorting algorithms based on comparison is O(n log n). You can't get better than that, except if you're using equality based algorithms. Commented Apr 3, 2013 at 7:37
  • 1
    Surely not. Suggest you get virtually any algorithms book on the planet, but R.Sedgewick's come highly recommended (by me anyway). Commented Apr 3, 2013 at 7:38
  • @Zeta One small note. Mergsesort can be done on linked lists in O(n log n) (and as a bonus, requires no additional memory requirements.) On such example algorithm can be seen here Commented Apr 3, 2013 at 7:47
  • @WhozCraig: Oops. Yes. Mergesort is a possible candidate for a list sort. Commented Apr 3, 2013 at 7:59

1 Answer 1

1

Could use a Radix Sort and there is a very nice article on linked list sorting more efficient than performing a node to every other node comparison in O(n * n) time here.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.