  | 
   Linked List Class 
   Submitted by  |   
  
  
This is the same Linked List class that was submitted by Chris Thompson a few
weeks ago, only optimised. As Chris had said at the time, it was a simple class
that was not optimised and written quickly. It was an excellent learning
experience for me, and that was only as such because of its simplicity. I had
since spoken with Chris and he had no problems with me re-submitting the code.
Some changes made are big, but overall, only one effect is made to how the class
is used:
        List made 2 way
        List Inserts now insert at the end of the list, and will not insert
into the specified position.
                index parameter was left for 3 reasons:
                        removing the parameter would effect code that used the
parameter
                        if someone wanted to re-add positional inserts, then
they would not have to make any drastic changes.
                        im lazy.
        The [] operator now works in milestones, jumping in m_msJump and
m_msJump2 distances respectively. Basically, the list is now linked on three
different levels, the bottom level being each element to the next, the next
level being linked every m_msJump elements, and the third being linked every
m_msJump2 distances (for the very large lists).
 
  Any advice is encouraged (although flaming is not - I am relatively new to c++,
so gimme a break). If anyone knows of a possible better way of doing a list (not
including using STL - i'm optimising this list for a learning experience),
please feel free to post a message. The optimisations has taken my code from
0.1fps to ~35-40fps, so I'm happy with my optmisations.
  
Hope to hear from you all,
  Richard Szalay
 | 
 
 
 
Download Associated File: newlist.h (7,026 bytes)
 
 /*
Name: List.h
Purpose: Linked List template class (declarations and definitions)
Original Author: Chris Thompson
Author: Richard Szalay
Created: 27th September, 2000
History: 08/10/00 :	Added primary/secondary milestone system
*/
  #ifndef __LIST_H__
#define __LIST_H__
  #include <stdio.h>
  template <class ListItem>
class List
{
public:
    List() 
        :m_numelements(0),
		m_lastIndex(0),
		m_msJump(64),
		m_msJump2(256)
    {
        m_head = new Link;
        m_tail = new Link;
          m_head->next = m_tail;
		m_head->prev = m_head;
          m_tail->next = m_tail;
		m_tail->prev = m_head;
      };
      ~List()
    {    
        Link* before = m_head;
        Link* after;
          while (before->next != m_tail)
        {
            after = before->next->next;
            delete before->next;
            before->next = after;
        }
          delete m_head;
        delete m_tail;
    };
      void Insert(int index, const ListItem& data)
    {
		/* Positioning removed from insert
		   - data in inserted before the tail */
          Link* newnode = new Link(data); // Create the new node
		/* inform the surrounding nodes	*/
		newnode->prev		= m_tail->prev;
		newnode->prev->next = newnode;
  		m_tail->prev  = newnode;
		newnode->next = m_tail;
  		/* 0 is an exception to the Milestone counter */
		if (m_numelements == 0)
		{
			m_lastMilestone = newnode;
			m_tail->prevMS = newnode;
  			m_lastMilestone2 = newnode;
			m_tail->prevMS2 = newnode;
  			m_lastNode = newnode;
			m_lastIndex = 0;
		}
  		newnode->prevMS = m_lastMilestone; // remember the previous milestone
		newnode->prevMS2 = m_lastMilestone2;
  		/* Primary Level Milestone */
		if (((m_numelements) % m_msJump) == 0)
		{
			m_lastMilestone = newnode;
			newnode->prevMS->nextMS = newnode;
			newnode->nextMS = newnode;
			m_tail->prevMS = newnode;
		}
  		/* Secondary Level Milestone */
		if (((m_numelements) % m_msJump2) == 0)
		{
			m_lastMilestone2 = newnode;
			newnode->prevMS2->nextMS2 = newnode;
			newnode->nextMS2 = newnode;
			m_tail->prevMS2 = newnode;
		}
          m_numelements++;
    }
      void Remove(int index)
    {
        Link* before = m_head;
        Link* after;
  		/* 
			Could/Should impliment a faster
			Remove function - but i've never 
			actually used it 
		*/
          for (int i=0;i<index;i++)
            before = before->next;
          after = before->next->next;
        delete before->next;
        before->next = after;
		after->prev = before;
        m_numelements--;
    }
      ListItem operator[](int index)
    {
        Link* element;
		int start, end, lastIndex;
  		start = 0;
		end = m_numelements;
		lastIndex = m_lastIndex;
  		element = m_head->next;
  		/*
			Before we do anything else, check
			if we are within 16 of the beginning 
			or the end
		*/
			// Near beginning
			if (index < m_msJump)
			{
				for (int i=0; i<index; i++)
				{
					element = element->next;
				}
				m_lastIndex = index;
				m_lastNode = element;
				return element->data;
			}
			// Near end
			if (index > (m_numelements - (m_numelements % m_msJump)))
			{
				element = m_tail;
				for (int i=m_numelements; i>index; i--)
				{
					element = element->prev;
				}
				m_lastIndex = index;
				m_lastNode = element;
				return element->data;
			}
  		/*
			Also, check if we are within 16 of the 
			last requested index
		*/
		// <- to the left
		if ((index < m_lastIndex)&&((m_lastIndex - index) < (m_msJump >> 1)))
		{
			element = m_lastNode;
  			for (int i=m_lastIndex;i>index;i--)
			{
				element = element->prev;
			}
			m_lastIndex = index;
			m_lastNode = element;
			return element->data;
		}
		// -> to the right
		if ((index >= m_lastIndex)&&((index - m_lastIndex) < (m_msJump >> 1)))
		{
			element = m_lastNode;
  			for (int i=m_lastIndex;i<index;i++)
			{
				element = element->next;
			}
			m_lastIndex = index;
			m_lastNode = element;
			return element->data;
		}
  		/*
			If we are here we arent close
			to anything 'nice'. So we find
			our closest 'milestone'
		*/
		int diffModulo = (index % m_msJump);
		int closePrevMS = (index - diffModulo);
		int diffModulo2 = (closePrevMS % m_msJump2);
		int closePrevMS2 = (closePrevMS - diffModulo2);
		int i;
  		/* Find secondary level milestone */
		// Which end should we start at? 
		// (which half of the list is it?)
		if (closePrevMS2 > (m_numelements >> 1)) // end?
		{
			element = m_tail->prevMS2;
			int supl = (m_numelements-(m_numelements%m_msJump2));
			for (i=supl; i>closePrevMS2; i-=m_msJump2)
			{
				element = element->prevMS2;
			}
		}
		else // beginning ?
		{
			for (i=0; i<closePrevMS2; i+=m_msJump2)
			{
				element = element->nextMS2;
			}
		}
  		/* Find primary level milestone */
		// Which end should we start at? 
		// (which half of the list is it?)
		if ((diffModulo2 > (m_msJump2 >> 1)) && (element->nextMS2 != element))
		{
			element = element->nextMS2; // jumpin'
			i += m_msJump2; // we start one jump forward (for counting)
			if ((element->prevMS->nextMS != element) && 
												(element->prevMS != element))
			{
				element = element->prevMS;
				i-=m_msJump;
			}
  			for (i=i; i>closePrevMS; i-=m_msJump)
			{
				element = element->prevMS;
			}
		}
		else // no - stay here and go forwards
		{
			if ((element->prevMS->nextMS != element) && 
												(element->prevMS != element))
			{
				element = element->prevMS;
				i-=m_msJump;
			}
  			for (i=i; i<closePrevMS; i+=m_msJump)
			{
				element = element->nextMS;
			}
		}
  		/* 
			- Final Stage -
			The closest lowest-level milestone has been located
			From here go (forwards or backwards) to find the node
		*/
  		//	Should we jump to the next milestone and go backwards?
		if ((diffModulo > (m_msJump >> 1)) && (element->nextMS != element))
		{
			// yes - jump and go backwards
			element = element->nextMS; // jumpin'
			i += m_msJump; // we start one jump forward (for counting)
			for (i=i; i>index; i--)
			{
				element = element->prev;
			}
		}
		else // no - stay here and go forwards
		{
			for (i=i; i<index; i++)
			{
				element = element->next;
			}
		}
  		m_lastIndex = index;
		m_lastNode = element;
        return element->data;
    }
      int Size()      // number of elements in the list
    {
        return m_numelements;
    }
  private:
      // node in our list
    struct Link
    {
        Link()
            :next(NULL) {};
        Link(const ListItem& datain)
            :data(datain),
            next(NULL) {};
        Link*   next;   // next node in list    
		Link*	prev;	// previous node
        ListItem    data;   // data stored in this node
		Link*	nextMS;
		Link*	prevMS;
		Link*	nextMS2;
		Link*	prevMS2;
    };
      // head and tail
    Link*   m_head;
    Link*   m_tail;
	Link*	m_lastNode;
    int     m_numelements;
	int		m_lastIndex;
	Link*	m_lastMilestone; // link of primary level jumps (milestones)
	Link*	m_lastMilestone2; // link of secondary level jumps (milestones)
	int		m_msJump; // Size of jump for primary level
	int		m_msJump2; // Size of jump for secondary level
};
  #endif   |  
  
 | 
 
 
 
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
 
 
 |