Circular linked list Please review this:

#include &lt;iostream&gt;
using namespace std;

template &lt;class T&gt;
struct Node
{
  T data;
  Node * next;
  Node(T data) : data(data), next(NULL) {}
};

template &lt;class T&gt;
class CircularLinkedList
{
public:
  CircularLinkedList() : head(NULL) {}
  ~CircularLinkedList();
  void addNode(T data);
  void deleteNode(T data);
  template &lt;class U&gt;
  friend std::ostream &amp; operator&lt;&lt;(std::ostream &amp; os, const CircularLinkedList&lt;U&gt; &amp; cll);
private:
  Node&lt;T&gt; * head;
};

template &lt;class T&gt;
CircularLinkedList&lt;T&gt;::~CircularLinkedList()
{
  if (head)
    {
      Node&lt;T&gt; * tmp = head;
      while (tmp-&gt;next != head)
        {
          Node&lt;T&gt; * t = tmp;
          tmp = tmp-&gt;next;
          delete(t);
        }
      delete tmp;
      head = NULL;
    }
}

template &lt;class T&gt;
void CircularLinkedList&lt;T&gt;::addNode(T data)
{
  Node&lt;T&gt; * t = new Node&lt;T&gt;(data);

  if (head == NULL)
    {
      t-&gt;next = t;
      head = t;
      return;
    }

  Node&lt;T&gt; * tmp = head;
  while (tmp-&gt;next !=  head)
    {
      tmp = tmp-&gt;next;
    }

  tmp-&gt;next = t;
  t-&gt;next = head;
}

template &lt;class T&gt;
void CircularLinkedList&lt;T&gt;::deleteNode(T data)
{
  Node&lt;T&gt; * tmp = head;
  Node&lt;T&gt; * prev = NULL;
  while (tmp-&gt;next !=  head)
    {
      if (tmp-&gt;data == data) break;
      prev = tmp;
      tmp = tmp-&gt;next;
    }

  if (tmp == head)
    {
      while (tmp-&gt;next != head)
        {
          tmp = tmp-&gt;next;
        }
      tmp-&gt;next = head-&gt;next;
      delete head;
      head = tmp-&gt;next;
    }
  else
    {
      prev-&gt;next = tmp-&gt;next;
      delete tmp;
    }
}

template &lt;class U&gt;
std::ostream &amp; operator&lt;&lt;(std::ostream &amp; os, const CircularLinkedList&lt;U&gt; &amp; cll)
{
  Node&lt;U&gt; * head = cll.head;
  if (head)
    {
      Node&lt;U&gt; * tmp = head;
      while (tmp-&gt;next != head)
        {
          os &lt;&lt; tmp-&gt;data &lt;&lt; " ";
          tmp = tmp-&gt;next;
        }
      os &lt;&lt; tmp-&gt;data;
    }
  return os;
}

int main()
{
  CircularLinkedList&lt;int&gt; cll;

  cll.addNode(1);
  cll.addNode(2);
  cll.addNode(3);
  cll.addNode(4);
  cll.addNode(5);

  cout &lt;&lt; cll &lt;&lt; endl;

  cll.deleteNode(3);
  cll.deleteNode(1);
  cll.deleteNode(5);

  cout &lt;&lt; cll &lt;&lt; endl;

  return 0;
}
)

My first comment is you should start looking at smart pointers.
They will definitely simplify your code.

The second comment: look at the STL containers.
Containers in C++ follow a specific pattern. The idea is that we want to use algorithms on containers interchangeably and thus containers follow these conventions to make them easy to use with the standard algorithms.

Third comment: you fail to follow the rule of three.
Basically. If you define one of 'Destructor'/'Copy-Constructor'/'Assignment-Operator' (rather than using the compiler generated defaults) then you probably need to define all three. In this case your code is going to crash if you make a copy of the list. The problem arises from having an owned pointer in your code.

Fourth comment: Prefer to be pass parameters by const reference. For simple objects like integers it will not make any difference. But you have templatised the code and T can be any type. Thus passing by value is going to cause a copy (which may be expensive).

Reviewing the above code:
The complexity of adding a node is O(n). By maintaining a head and a tail pointer you can change this to have a complexity of O(1). ie. this loop becomes unnecessary.

Node&lt;T&gt; * tmp = head;
while (tmp-&gt;next !=  head)
{
  tmp = tmp-&gt;next;
}


You have an output operator std::ostream &amp; operator&lt;&lt;(std::ostream &amp; os, const CircularLinkedList&lt;U&gt; &amp; cll) It would be nice if you had a symmetric input operator. In this situation you need to worry about the size of the list (or adding a special terminating character). So the creation of the input operator will affect your design of the output operator.