CS 250 Computer Programming and Problem Solving - FALL 1998 

[ Home | Syllabus | Notes | Glossary | CS250 WEB Version Home Page ]


 

Linked Lists Implementation of List Object


// A node in a singly linked list.

template <class T>
class Tnode {
  friend class Tlist<T>; // why?
  friend ostream & operator <<(ostream & os,
         const Tnode<T> & N);
  // PRE: type T has overloaded the insertion operator
  // POST: outputs data value in node
public:
  Tnode();
  // POST: create node with next pointer NULL
  // the value field will use its default constructor

  Tnode( const T & val );
  // PRE: type T has a copy constructor
  // POST: create node with NULL next pointer
  // and value set to "val"

  Tnode<T> * Next() const; 
  // POST: returns pointer to successor node
// why not a get/set of the value field?? 

private:
  T value;          // data stored in node
  Tnode * next;     // points to next node
};


// A singly linked list of Tnode objects.

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

  bool Advance();
  // Return 0 if current position is already at 
  // the end of the list; otherwise, increment
  // current and return 1.

  void Append( const T & nodeVal );
  // Add a new node to the end of the list.

  void Clear();
  // Remove all nodes.

  T Get() const;
  // Get the data at the current position.

  void GoLast();
  // Set current to the last node in the list.

  void GoTop();
  // Set current to the header node.

  void InsertAfter( const T & nodeVal );
  // Insert new node after current one.

  int IsEmpty() const;
  // Return 1 if the list is empty; otherwise,
  // return 0.

  void Prepend( const T & nodeVal );
  // Insert a node at the beginning of the list.

  void Replace( const T & newVal );
  // Replace the data in the current node.

  friend ostream & operator <<(ostream &, const Tlist<T> &);

private:
  Tnode<T> * head;      // dummy head node
  Tnode<T> * tail;      // dummy tail node
  Tnode<T> * current;   // current position
};

Implementation of Tnode

//............Tnode<T> class ............

template <class T>
Tnode<T>::Tnode()
{
  next = NULL;
}
template <class T>
Tnode<T>::Tnode( const T & val ): value(val)// use non-default constructor
{
  next = NULL;
}

template <class T>
Tnode<T> * Tnode<T>::Next() const // can you parse this?
{
  return next;
}


template <class T>
ostream & operator <<( ostream & os, const Tnode<T> & N )
{
  os << N.value << ',';
  return os;
}

//............ Tlist<T> class ............


template <class T>
Tlist<T>::Tlist()
{
  head = new Tnode<T>; // dummy nodes avoid special cases at the ends
  tail = new Tnode<T>;
  head->next = tail;
  tail->next = head;
  current = head;
}

template <class T>
Tlist<T>::~Tlist()
{
  Clear();
  delete head;
  delete tail;
}

template <class T>
bool Tlist<T>::Advance()
{
  if( !current ) throw NoCurrentNode(); // we'll explain this later
  if( current->next != tail )
  {
    current = current->next;
    return true;
  }
  return false;
}

template <class T>
void Tlist<T>::Append( const T & nodeVal )
{
  GoLast();
  InsertAfter( nodeVal );
}

template <class T>
void Tlist<T>::Clear()
{
  current = head->next; // why not just head?
  while( current != tail )
  {
	 head->next = current->next; // use as temp
	 delete current;
	 current = head->next;
  }
  current = head;
  head->next = tail; // is this necessary?
}

template <class T>
int Tlist<T>::IsEmpty() const
{
  return head->next == tail; // what is being tested here?
}

template <class T>
T Tlist<T>::Get() const
{
  if( !current ) throw NoCurrentNode();
  return current->value;
}

template <class T>
void Tlist<T>::GoLast()
//PRE: current cannot point to tail or else what?
{
  if( !current ) throw NoCurrentNode();
  while( current->next != tail )
	 current = current->next;
}

template <class T>
void Tlist<T>::GoTop()
{
  current = head;
}

template <class T>
void Tlist<T>::InsertAfter( const T & nodeVal )
{
  if( !current ) throw NoCurrentNode();
  Tnode<T> * p = new Tnode<T>( nodeVal );
  p->next = current->next; // normal list insertion
  current->next = p;
  current = p;
}

template <class T>
void Tlist<T>::Prepend( const T & nodeVal )
{
  GoTop();
  InsertAfter( nodeVal );
}

template <class T>
void Tlist<T>::Replace( const T & newVal )
{
  if( !current ) throw NoCurrentNode();
  current->value = newVal;
}

template <class T>
ostream & operator <<( ostream & os,
		  const Tlist<T> & S )
{
  if( S.IsEmpty()) return os;

  Tnode<T> * p = S.head->Next();
  while( p != S.tail )
  {
	 os << *p;
	 p = p->Next();
  }
  os << endl;
  return os;
}




Copyright chris wild 1998.
For problems or questions regarding this website contact [Chris Wild (e-mail:wild@cs.odu.edu].
Last updated: October 26, 1998.