Revision: 304 Author: coenbijlsma Date: Sun Aug 9 02:14:08 2009 Log: Created a SortedList data structure which can Comparable<T>'s that are automatically sorted on insertion. Also added Comparable::compareTo(Comparable<T>) and adjusted the Integer and String class accordingly. TODO: Optimize SortedList::insert(SortedListNode<T>*, SortedListNode<T>*). http://code.google.com/p/freenos/source/detail?r=304 Added: /trunk/include/SortedList.h Modified: /trunk/bin/parse/Main.cpp /trunk/include/Comparable.h /trunk/include/Integer.h /trunk/include/String.h ======================================= --- /dev/null +++ /trunk/include/SortedList.h Sun Aug 9 02:14:08 2009 @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2009 Coen Bijlsma + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __SORTEDLIST_H +#define __SORTEDLIST_H + +#include "Assert.h" +#include "Comparable.h" + +/** + * Represents an item in the SortedList. The data in a SortedListNode + * cannot be (U*)0. + */ +template <class U = class Comparable<class U> > class SortedListNode +{ + public: + + /** + * Class constructor. + * @param t Data value. + * @param p Previous SortedListNode. + * @param n Next SortedListNode. + */ + SortedListNode(U* t + , SortedListNode<U>* p + , SortedListNode<U>* n) + : data(t), prev(p), next(n) + { + assertRead(t); + assert(t); + } + + /** User data. */ + U* data; + + /** Previous and next node. */ + SortedListNode<U>* prev; + SortedListNode<U>* next; +}; + +/** + * Represents a sorted list. Every item in a SortedList must implement + * the functions of the Comparable class as to sort the items in the list. + */ +template <class T = class Comparable<class T> > class SortedList +{ + public: + + /** + * Class constructor. + * Creates an empty list without a headnode and + * a node count of zero. + */ + SortedList() : headNode(0), nodeCount(0) + { + } + + /** + * Class destructor. + * Deletes the nodes but not the data contained in the nodes. + */ + ~SortedList() + { + while (headNode) + { + SortedListNode<T> *tmp = headNode; + headNode = headNode->next; + delete tmp; + } + } + + /** + * Inserts the given item in the list. If the given item + * is (T*)0, then assertion fails. If not, a new SortedListNode<T>* + * is created and added to the list in it's designated position. + * If the same data already exists in the list, the newly created node + * is not inserted in the list and deleted whilst preserving the data + * in the node. + * If the head node is empty, the newly created SortedListNode becomes + * the nead node and the function returns.+ * If the head node already exists, the middle of the list is determined + * by calling get( (Size) (nodeCount / 2)) and the second insert is called. + * This saves up to twice the time needed to insert a node because at most
+ * half of the list has to be searched and compared. + * + * @param t The data to insert to the list.+ * @see SortedList::insert(SortedListNode<T>* t, SortedListNode<T>* from)
+ */ + void insert(T* t) + { + assertRead(t); + assert(t); + + /* Create a new node from the given data. */ + SortedListNode<T>* n + = new SortedListNode<T>(t + , (SortedListNode<T>*) 0 + , (SortedListNode<T>*) 0); + + if(!headNode) + { + /* headNode == 0, so the list is still empty. */ + headNode = n; + nodeCount++; + } else { + /* + * The list is filled. That means we have to + * retrieve the node in the middle + */ + SortedListNode<T>* middle + = get( (Size)(nodeCount / 2) ); + insert(n, middle); + } + + } + + /** + * Returns the head node of the list. + * @return The head node if this list. + */ + SortedListNode<T>* head() const + { + return headNode; + } + + private: + + /** Head of the SortedList. */ + SortedListNode<T>* headNode; + + /** Number of items currently in the SortedList. */ + Size nodeCount; + + /** + * Returns the SortedListNode at the nth position. + * @param n The position of the node to get.+ * @return The node at position n or (SortedListNode<Comparable<T>
*)0
+ * if it doesn't exist. + */ + SortedListNode<T>* get(Size n) + { + if( n >= nodeCount ) + { + return (SortedListNode<T>*)0; + } + + SortedListNode<T>* item = headNode; + + for(Size s = 0; s < n && item; s++) + { + item = item->next; + } + + return item; + } + + /**+ * Inserts the SortedListNode in the SortedList, but starts comparing + * as of the given position. This prevents unnecessary searches through
+ * the SortedList and can save up to half the SortedList's length. + * @param t The SortedListNode to add. + * @param pos The position to start the insert. + */ + void insert(SortedListNode<T>* t, + SortedListNode<T>* from) + { + + if(!from) + {+ /* The `from' node doesn't exist. TODO: exit(EXIT_FAILURE)*/
+ return; + } + T* tc = t->data; + T* fc = from->data; + int result = tc->compareTo(fc); + + if( result == 0 ) + { + /* The nodes contain the same data, so quit */ + return; + } else if( result < 0 ) + {+ /* t->data is less then from->data so search the first half */
+ SortedListNode<T>* tmp = headNode; + + do + { + if( tmp->data->compareTo(tc) > 0 ) + { + /* Insert t between tmp->prev and tmp. */ + SortedListNode<T>* p = tmp->prev; + if(p) + { + p->next = t; + t->prev = p; + t->next = tmp; + tmp->prev = t; + } else { + t->next = tmp; + t->prev = (SortedListNode<T>*)0; + tmp->prev = t; + headNode = t; + } + break; + } + + tmp = tmp->next; + } + while( tmp->prev != from ); + nodeCount++; + return; + } ++ /* t->data is greater then from->data so search the last half */
+ SortedListNode<T>* tmp = from; + + do + { + + if(!tmp->next) + { + tmp->next = t; + t->prev = tmp; + break; + } else if( tmp->data->compareTo(tc) > 0 ) + { + /* Insert t between tmp->prev and tmp. */ + SortedListNode<T>* p = tmp->prev; + if(p) + { + p->next = t; + t->prev = p; + t->next = tmp; + tmp->prev = t; + } else { + t->next = tmp; + tmp->prev = t; + headNode = t; + } + break; + } + + tmp = tmp->next; + } + while( tmp ); + nodeCount++; + return; + } +}; + +#endif /* __SORTEDLIST_H */ ======================================= --- /trunk/bin/parse/Main.cpp Mon Aug 3 14:38:28 2009 +++ /trunk/bin/parse/Main.cpp Sun Aug 9 02:14:08 2009 @@ -22,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> #include <fcntl.h> +#include <SortedList.h> void usage(char*); @@ -43,6 +44,7 @@ delete url; delete parent; + return EXIT_SUCCESS; } ======================================= --- /trunk/include/Comparable.h Thu Mar 5 17:11:51 2009 +++ /trunk/include/Comparable.h Sun Aug 9 02:14:08 2009 @@ -39,6 +39,16 @@ */ virtual bool equals(const T &t) = 0; + /** + * Compares this Comparable to the given + * Comparable and returns whether this Comparable + * is equal to, less, or greater then the given Comparable. + * @param c The Comparable to compare us to. + * @return an int < 0, 0, > 0 if we are respectively less then, + * equal to or greater then the given Comparable. + */ + virtual int compareTo(const T &t) = 0; + /** * Get the size of the object. * @return Size in bytes. ======================================= --- /trunk/include/Integer.h Sat Apr 25 16:17:47 2009 +++ /trunk/include/Integer.h Sun Aug 9 02:14:08 2009 @@ -77,6 +77,25 @@ { return value == i.value; } + + /** + * Compares two Integers. + * @param i Constant Integer instance. + * @return an int < 0, 0 or > 0 if this Integer is + * less than, equal to or greater than i. + */ + int compareTo(const Integer<Int> &i) + { + if( value == i.value ) + { + return 0; + } else if( value < i.value ) + { + return -1; + } + + return 1; + } /** * Compare two Integers's. ======================================= --- /trunk/include/String.h Sun Aug 2 06:41:29 2009 +++ /trunk/include/String.h Sun Aug 9 02:14:08 2009 @@ -463,6 +463,36 @@ assertRead(s.value); return strcmp(value, s.value) == 0; } + + /** + * Compares this String to the given String. + * @param s The String to compare us to. + * @return int < 0, 0, > 0 if we are greater then, equal to + * or less then the given String. + */ + int compareTo(const String & s) + { + assertRead(s.value); + Size length = strlen(value); + + if(strlen(s.value) < length) + { + length = strlen(s.value); + } + + for(Size pos = 0; pos < length; pos++) + { + if( value[pos] > s.value[pos] ) + { + return 1; + } else if( value[pos] < s.value[pos] ) + { + return -1; + } + } + + return 0; + } /** * Compares this String to the given String, ignoring