mirror of
https://github.com/DarkflameUniverse/DarkflameServer
synced 2024-08-30 18:43:58 +00:00
1260 lines
33 KiB
C
1260 lines
33 KiB
C
|
/// \file
|
||
|
/// \brief \b [Internal] Straightforward linked list data structure.
|
||
|
///
|
||
|
/// This file is part of RakNet Copyright 2003 Kevin Jenkins.
|
||
|
///
|
||
|
/// Usage of RakNet is subject to the appropriate license agreement.
|
||
|
/// Creative Commons Licensees are subject to the
|
||
|
/// license found at
|
||
|
/// http://creativecommons.org/licenses/by-nc/2.5/
|
||
|
/// Single application licensees are subject to the license found at
|
||
|
/// http://www.jenkinssoftware.com/SingleApplicationLicense.html
|
||
|
/// Custom license users are subject to the terms therein.
|
||
|
/// GPL license users are subject to the GNU General Public
|
||
|
/// License as published by the Free
|
||
|
/// Software Foundation; either version 2 of the License, or (at your
|
||
|
/// option) any later version.
|
||
|
|
||
|
#ifndef __LINKED_LIST_H
|
||
|
#define __LINKED_LIST_H
|
||
|
|
||
|
#include "Export.h"
|
||
|
#include "RakMemoryOverride.h"
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning( push )
|
||
|
#endif
|
||
|
|
||
|
/// The namespace DataStructures was only added to avoid compiler errors for commonly named data structures
|
||
|
/// As these data structures are stand-alone, you can use them outside of RakNet for your own projects if you wish.
|
||
|
namespace DataStructures
|
||
|
{
|
||
|
// Prototype to prevent error in CircularLinkedList class when a reference is made to a LinkedList class
|
||
|
template <class LinkedListType>
|
||
|
class RAK_DLL_EXPORT LinkedList;
|
||
|
|
||
|
/**
|
||
|
* \brief (Circular) Linked List ADT (Doubly Linked Pointer to Node Style) -
|
||
|
*
|
||
|
* By Kevin Jenkins (http://www.rakkar.org)
|
||
|
* Initilize with the following command
|
||
|
* LinkedList<TYPE>
|
||
|
* OR
|
||
|
* CircularLinkedList<Type>
|
||
|
*
|
||
|
* Has the following member functions
|
||
|
* - size: returns number of elements in the linked list
|
||
|
* - insert(item): inserts @em item at the current position in
|
||
|
* the LinkedList.
|
||
|
* - add(item): inserts @em item after the current position in
|
||
|
* the LinkedList. Does not increment the position
|
||
|
* - replace(item): replaces the element at the current position @em item.
|
||
|
* - peek: returns the element at the current position
|
||
|
* - pop: returns the element at the current position and deletes it
|
||
|
* - del: deletes the current element. Does nothing for an empty list.
|
||
|
* - clear: empties the LinkedList and returns storage
|
||
|
* - bool IsInitem): Does a linear search for @em item. Does not set
|
||
|
* the position to it, only returns true on item found, false otherwise
|
||
|
* - bool find(item): Does a linear search for @em item and sets the current
|
||
|
* position to point to it if and only if the item is found. Returns true
|
||
|
* on item found, false otherwise
|
||
|
* - sort: Sorts the elements of the list with a mergesort and sets the
|
||
|
* current pointer to the first element
|
||
|
* - concatenate(list L): This appends L to the current list
|
||
|
* - ++(prefix): moves the pointer one element up in the list and returns the
|
||
|
* appropriate copy of the element in the list
|
||
|
* - --(prefix): moves the pointer one element back in the list and returns
|
||
|
* the appropriate copy of the element in the list
|
||
|
* - beginning - moves the pointer to the start of the list. For circular
|
||
|
* linked lists this is first 'position' created. You should call this
|
||
|
* after the sort function to read the first value.
|
||
|
* - end - moves the pointer to the end of the list. For circular linked
|
||
|
* lists this is one less than the first 'position' created
|
||
|
* The assignment and copy constructor operators are defined
|
||
|
*
|
||
|
* \note
|
||
|
* 1. LinkedList and CircularLinkedList are exactly the same except LinkedList
|
||
|
* won't let you wrap around the root and lets you jump to two positions
|
||
|
* relative to the root/
|
||
|
* 2. Postfix ++ and -- can be used but simply call the prefix versions.
|
||
|
*
|
||
|
*
|
||
|
* EXAMPLE:
|
||
|
* @code
|
||
|
* LinkedList<int> A; // Creates a Linked List of integers called A
|
||
|
* CircularLinkedList<int> B; // Creates a Circular Linked List of
|
||
|
* // integers called B
|
||
|
*
|
||
|
* A.Insert(20); // Adds 20 to A. A: 20 - current is 20
|
||
|
* A.Insert(5); // Adds 5 to A. A: 5 20 - current is 5
|
||
|
* A.Insert(1); // Adds 1 to A. A: 1 5 20 - current is 1
|
||
|
*
|
||
|
* A.IsIn1); // returns true
|
||
|
* A.IsIn200); // returns false
|
||
|
* A.Find(5); // returns true and sets current to 5
|
||
|
* A.Peek(); // returns 5
|
||
|
* A.Find(1); // returns true and sets current to 1
|
||
|
*
|
||
|
* (++A).Peek(); // Returns 5
|
||
|
* A.Peek(); // Returns 5
|
||
|
*
|
||
|
* A.Replace(10); // Replaces 5 with 10.
|
||
|
* A.Peek(); // Returns 10
|
||
|
*
|
||
|
* A.Beginning(); // Current points to the beginning of the list at 1
|
||
|
*
|
||
|
* (++A).Peek(); // Returns 5
|
||
|
* A.Peek(); // Returns 10
|
||
|
*
|
||
|
* A.Del(); // Deletes 10. Current points to the next element, which is 20
|
||
|
* A.Peek(); // Returns 20
|
||
|
*
|
||
|
* A.Beginning(); // Current points to the beginning of the list at 1
|
||
|
*
|
||
|
* (++A).Peek(); // Returns 5
|
||
|
* A.Peek(); // Returns 20
|
||
|
*
|
||
|
* A.Clear(); // Deletes all nodes in A
|
||
|
*
|
||
|
* A.Insert(5); // A: 5 - current is 5
|
||
|
* A.Insert(6); // A: 6 5 - current is 6
|
||
|
* A.Insert(7); // A: 7 6 5 - current is 7
|
||
|
*
|
||
|
* A.Clear();
|
||
|
* B.Clear();
|
||
|
*
|
||
|
* B.Add(10);
|
||
|
* B.Add(20);
|
||
|
* B.Add(30);
|
||
|
* B.Add(5);
|
||
|
* B.Add(2);
|
||
|
* B.Add(25);
|
||
|
* // Sorts the numbers in the list and sets the current pointer to the
|
||
|
* // first element
|
||
|
* B.sort();
|
||
|
*
|
||
|
* // Postfix ++ just calls the prefix version and has no functional
|
||
|
* // difference.
|
||
|
* B.Peek(); // Returns 2
|
||
|
* B++;
|
||
|
* B.Peek(); // Returns 5
|
||
|
* B++;
|
||
|
* B.Peek(); // Returns 10
|
||
|
* B++;
|
||
|
* B.Peek(); // Returns 20
|
||
|
* B++;
|
||
|
* B.Peek(); // Returns 25
|
||
|
* B++;
|
||
|
* B.Peek(); // Returns 30
|
||
|
* @endcode
|
||
|
*/
|
||
|
template <class CircularLinkedListType>
|
||
|
|
||
|
class CircularLinkedList : public RakNet::RakMemoryOverride
|
||
|
{
|
||
|
|
||
|
public:
|
||
|
|
||
|
struct node
|
||
|
{
|
||
|
CircularLinkedListType item;
|
||
|
|
||
|
node* previous;
|
||
|
node* next;
|
||
|
};
|
||
|
|
||
|
CircularLinkedList();
|
||
|
~CircularLinkedList();
|
||
|
CircularLinkedList( const CircularLinkedList& original_copy );
|
||
|
// CircularLinkedList(LinkedList<CircularLinkedListType> original_copy) {CircularLinkedList(original_copy);} // Converts linked list to circular type
|
||
|
bool operator= ( const CircularLinkedList& original_copy );
|
||
|
CircularLinkedList& operator++(); // CircularLinkedList A; ++A;
|
||
|
CircularLinkedList& operator++( int ); // Circular_Linked List A; A++;
|
||
|
CircularLinkedList& operator--(); // CircularLinkedList A; --A;
|
||
|
CircularLinkedList& operator--( int ); // Circular_Linked List A; A--;
|
||
|
bool IsIn( const CircularLinkedListType& input );
|
||
|
bool Find( const CircularLinkedListType& input );
|
||
|
void Insert( const CircularLinkedListType& input );
|
||
|
|
||
|
CircularLinkedListType& Add ( const CircularLinkedListType& input )
|
||
|
|
||
|
; // Adds after the current position
|
||
|
void Replace( const CircularLinkedListType& input );
|
||
|
|
||
|
void Del( void );
|
||
|
|
||
|
unsigned int Size( void );
|
||
|
|
||
|
CircularLinkedListType& Peek( void );
|
||
|
|
||
|
CircularLinkedListType Pop( void );
|
||
|
|
||
|
void Clear( void );
|
||
|
|
||
|
void Sort( void );
|
||
|
|
||
|
void Beginning( void );
|
||
|
|
||
|
void End( void );
|
||
|
|
||
|
void Concatenate( const CircularLinkedList& L );
|
||
|
|
||
|
protected:
|
||
|
unsigned int list_size;
|
||
|
|
||
|
node *root;
|
||
|
|
||
|
node *position;
|
||
|
|
||
|
node* FindPointer( const CircularLinkedListType& input );
|
||
|
|
||
|
private:
|
||
|
CircularLinkedList Merge( CircularLinkedList L1, CircularLinkedList L2 );
|
||
|
|
||
|
CircularLinkedList Mergesort( const CircularLinkedList& L );
|
||
|
};
|
||
|
|
||
|
template <class LinkedListType>
|
||
|
|
||
|
class LinkedList : public CircularLinkedList<LinkedListType>
|
||
|
{
|
||
|
|
||
|
public:
|
||
|
LinkedList()
|
||
|
{}
|
||
|
|
||
|
LinkedList( const LinkedList& original_copy );
|
||
|
~LinkedList();
|
||
|
bool operator= ( const LinkedList<LinkedListType>& original_copy );
|
||
|
LinkedList& operator++(); // LinkedList A; ++A;
|
||
|
LinkedList& operator++( int ); // Linked List A; A++;
|
||
|
LinkedList& operator--(); // LinkedList A; --A;
|
||
|
LinkedList& operator--( int ); // Linked List A; A--;
|
||
|
|
||
|
private:
|
||
|
LinkedList Merge( LinkedList L1, LinkedList L2 );
|
||
|
LinkedList Mergesort( const LinkedList& L );
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
inline void CircularLinkedList<CircularLinkedListType>::Beginning( void )
|
||
|
{
|
||
|
if ( this->root )
|
||
|
this->position = this->root;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
inline void CircularLinkedList<CircularLinkedListType>::End( void )
|
||
|
{
|
||
|
if ( this->root )
|
||
|
this->position = this->root->previous;
|
||
|
}
|
||
|
|
||
|
template <class LinkedListType>
|
||
|
bool LinkedList<LinkedListType>::operator= ( const LinkedList<LinkedListType>& original_copy )
|
||
|
{
|
||
|
typename LinkedList::node * original_copy_pointer, *last, *save_position;
|
||
|
|
||
|
if ( ( &original_copy ) != this )
|
||
|
{
|
||
|
|
||
|
this->Clear();
|
||
|
|
||
|
|
||
|
if ( original_copy.list_size == 0 )
|
||
|
{
|
||
|
this->root = 0;
|
||
|
this->position = 0;
|
||
|
this->list_size = 0;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
if ( original_copy.list_size == 1 )
|
||
|
{
|
||
|
this->root = new typename LinkedList::node;
|
||
|
// root->item = new LinkedListType;
|
||
|
this->root->next = this->root;
|
||
|
this->root->previous = this->root;
|
||
|
this->list_size = 1;
|
||
|
this->position = this->root;
|
||
|
// *(root->item)=*((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
// Setup the first part of the root node
|
||
|
original_copy_pointer = original_copy.root;
|
||
|
this->root = new typename LinkedList::node;
|
||
|
// root->item = new LinkedListType;
|
||
|
this->position = this->root;
|
||
|
// *(root->item)=*((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = this->position;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
|
||
|
|
||
|
// Save the current element
|
||
|
last = this->position;
|
||
|
|
||
|
// Point to the next node in the source list
|
||
|
original_copy_pointer = original_copy_pointer->next;
|
||
|
|
||
|
// Create a new node and point position to it
|
||
|
this->position = new typename LinkedList::node;
|
||
|
// position->item = new LinkedListType;
|
||
|
|
||
|
// Copy the item to the new node
|
||
|
// *(position->item)=*(original_copy_pointer->item);
|
||
|
this->position->item = original_copy_pointer->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = this->position;
|
||
|
|
||
|
|
||
|
// Set the previous pointer for the new node
|
||
|
( this->position->previous ) = last;
|
||
|
|
||
|
// Set the next pointer for the old node to the new node
|
||
|
( last->next ) = this->position;
|
||
|
|
||
|
}
|
||
|
|
||
|
while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
|
||
|
|
||
|
// Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node
|
||
|
this->position->next = this->root;
|
||
|
|
||
|
this->root->previous = this->position;
|
||
|
|
||
|
this->list_size = original_copy.list_size;
|
||
|
|
||
|
this->position = save_position;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>::CircularLinkedList()
|
||
|
{
|
||
|
this->root = 0;
|
||
|
this->position = 0;
|
||
|
this->list_size = 0;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>::~CircularLinkedList()
|
||
|
{
|
||
|
this->Clear();
|
||
|
}
|
||
|
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>::~LinkedList()
|
||
|
{
|
||
|
this->Clear();
|
||
|
}
|
||
|
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>::LinkedList( const LinkedList& original_copy )
|
||
|
{
|
||
|
typename LinkedList::node * original_copy_pointer, *last, *save_position;
|
||
|
|
||
|
if ( original_copy.list_size == 0 )
|
||
|
{
|
||
|
this->root = 0;
|
||
|
this->position = 0;
|
||
|
this->list_size = 0;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
if ( original_copy.list_size == 1 )
|
||
|
{
|
||
|
this->root = new typename LinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
this->root->next = this->root;
|
||
|
this->root->previous = this->root;
|
||
|
this->list_size = 1;
|
||
|
this->position = this->root;
|
||
|
// *(root->item) = *((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
// Setup the first part of the root node
|
||
|
original_copy_pointer = original_copy.root;
|
||
|
this->root = new typename LinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
this->position = this->root;
|
||
|
// *(root->item)=*((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = this->position;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Save the current element
|
||
|
last = this->position;
|
||
|
|
||
|
// Point to the next node in the source list
|
||
|
original_copy_pointer = original_copy_pointer->next;
|
||
|
|
||
|
// Create a new node and point position to it
|
||
|
this->position = new typename LinkedList::node;
|
||
|
// position->item = new CircularLinkedListType;
|
||
|
|
||
|
// Copy the item to the new node
|
||
|
// *(position->item)=*(original_copy_pointer->item);
|
||
|
this->position->item = original_copy_pointer->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = this->position;
|
||
|
|
||
|
// Set the previous pointer for the new node
|
||
|
( this->position->previous ) = last;
|
||
|
|
||
|
// Set the next pointer for the old node to the new node
|
||
|
( last->next ) = this->position;
|
||
|
|
||
|
}
|
||
|
|
||
|
while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
|
||
|
|
||
|
// Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node
|
||
|
this->position->next = this->root;
|
||
|
|
||
|
this->root->previous = this->position;
|
||
|
|
||
|
this->list_size = original_copy.list_size;
|
||
|
|
||
|
this->position = save_position;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
|
||
|
#endif
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>::CircularLinkedList( const CircularLinkedList& original_copy )
|
||
|
{
|
||
|
node * original_copy_pointer;
|
||
|
node *last;
|
||
|
node *save_position;
|
||
|
|
||
|
if ( original_copy.list_size == 0 )
|
||
|
{
|
||
|
this->root = 0;
|
||
|
this->position = 0;
|
||
|
this->list_size = 0;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
if ( original_copy.list_size == 1 )
|
||
|
{
|
||
|
this->root = new typename CircularLinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
this->root->next = this->root;
|
||
|
this->root->previous = this->root;
|
||
|
this->list_size = 1;
|
||
|
this->position = this->root;
|
||
|
// *(root->item) = *((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
// Setup the first part of the root node
|
||
|
original_copy_pointer = original_copy.root;
|
||
|
this->root = new typename CircularLinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
this->position = this->root;
|
||
|
// *(root->item)=*((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = this->position;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
|
||
|
|
||
|
// Save the current element
|
||
|
last = this->position;
|
||
|
|
||
|
// Point to the next node in the source list
|
||
|
original_copy_pointer = original_copy_pointer->next;
|
||
|
|
||
|
// Create a new node and point position to it
|
||
|
this->position = new typename CircularLinkedList::node;
|
||
|
// position->item = new CircularLinkedListType;
|
||
|
|
||
|
// Copy the item to the new node
|
||
|
// *(position->item)=*(original_copy_pointer->item);
|
||
|
this->position->item = original_copy_pointer->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = position;
|
||
|
|
||
|
// Set the previous pointer for the new node
|
||
|
( this->position->previous ) = last;
|
||
|
|
||
|
// Set the next pointer for the old node to the new node
|
||
|
( last->next ) = this->position;
|
||
|
|
||
|
}
|
||
|
|
||
|
while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
|
||
|
|
||
|
// Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node
|
||
|
this->position->next = this->root;
|
||
|
|
||
|
this->root->previous = position;
|
||
|
|
||
|
this->list_size = original_copy.list_size;
|
||
|
|
||
|
this->position = save_position;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning( disable : 4701 ) // warning C4701: local variable <variable name> may be used without having been initialized
|
||
|
#endif
|
||
|
template <class CircularLinkedListType>
|
||
|
bool CircularLinkedList<CircularLinkedListType>::operator= ( const CircularLinkedList& original_copy )
|
||
|
{
|
||
|
node * original_copy_pointer;
|
||
|
node *last;
|
||
|
node *save_position;
|
||
|
|
||
|
if ( ( &original_copy ) != this )
|
||
|
{
|
||
|
|
||
|
this->Clear();
|
||
|
|
||
|
|
||
|
if ( original_copy.list_size == 0 )
|
||
|
{
|
||
|
this->root = 0;
|
||
|
this->position = 0;
|
||
|
this->list_size = 0;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
if ( original_copy.list_size == 1 )
|
||
|
{
|
||
|
this->root = new typename CircularLinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
this->root->next = this->root;
|
||
|
this->root->previous = this->root;
|
||
|
this->list_size = 1;
|
||
|
this->position = this->root;
|
||
|
// *(root->item)=*((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
// Setup the first part of the root node
|
||
|
original_copy_pointer = original_copy.root;
|
||
|
this->root = new typename CircularLinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
this->position = this->root;
|
||
|
// *(root->item)=*((original_copy.root)->item);
|
||
|
this->root->item = original_copy.root->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = this->position;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Save the current element
|
||
|
last = this->position;
|
||
|
|
||
|
// Point to the next node in the source list
|
||
|
original_copy_pointer = original_copy_pointer->next;
|
||
|
|
||
|
// Create a new node and point position to it
|
||
|
this->position = new typename CircularLinkedList::node;
|
||
|
// position->item = new CircularLinkedListType;
|
||
|
|
||
|
// Copy the item to the new node
|
||
|
// *(position->item)=*(original_copy_pointer->item);
|
||
|
this->position->item = original_copy_pointer->item;
|
||
|
|
||
|
if ( original_copy_pointer == original_copy.position )
|
||
|
save_position = this->position;
|
||
|
|
||
|
// Set the previous pointer for the new node
|
||
|
( this->position->previous ) = last;
|
||
|
|
||
|
// Set the next pointer for the old node to the new node
|
||
|
( last->next ) = this->position;
|
||
|
|
||
|
}
|
||
|
|
||
|
while ( ( original_copy_pointer->next ) != ( original_copy.root ) );
|
||
|
|
||
|
// Complete the circle. Set the next pointer of the newest node to the root and the previous pointer of the root to the newest node
|
||
|
this->position->next = this->root;
|
||
|
|
||
|
this->root->previous = this->position;
|
||
|
|
||
|
this->list_size = original_copy.list_size;
|
||
|
|
||
|
this->position = save_position;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
void CircularLinkedList<CircularLinkedListType>::Insert( const CircularLinkedListType& input )
|
||
|
{
|
||
|
node * new_node;
|
||
|
|
||
|
if ( list_size == 0 )
|
||
|
{
|
||
|
this->root = new typename CircularLinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
//*(root->item)=input;
|
||
|
this->root->item = input;
|
||
|
this->root->next = this->root;
|
||
|
this->root->previous = this->root;
|
||
|
this->list_size = 1;
|
||
|
this->position = this->root;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
if ( list_size == 1 )
|
||
|
{
|
||
|
this->position = new typename CircularLinkedList::node;
|
||
|
// position->item = new CircularLinkedListType;
|
||
|
this->root->next = this->position;
|
||
|
this->root->previous = this->position;
|
||
|
this->position->previous = this->root;
|
||
|
this->position->next = this->root;
|
||
|
// *(position->item)=input;
|
||
|
this->position->item = input;
|
||
|
this->root = this->position; // Since we're inserting into a 1 element list the old root is now the second item
|
||
|
this->list_size = 2;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
|
||
|
B
|
||
|
|
|
||
|
A --- C
|
||
|
|
||
|
position->previous=A
|
||
|
new_node=B
|
||
|
position=C
|
||
|
|
||
|
Note that the order of the following statements is important */
|
||
|
|
||
|
new_node = new typename CircularLinkedList::node;
|
||
|
// new_node->item = new CircularLinkedListType;
|
||
|
|
||
|
// *(new_node->item)=input;
|
||
|
new_node->item = input;
|
||
|
|
||
|
// Point next of A to B
|
||
|
( this->position->previous ) ->next = new_node;
|
||
|
|
||
|
// Point last of B to A
|
||
|
new_node->previous = this->position->previous;
|
||
|
|
||
|
// Point last of C to B
|
||
|
this->position->previous = new_node;
|
||
|
|
||
|
// Point next of B to C
|
||
|
new_node->next = this->position;
|
||
|
|
||
|
// Since the root pointer is bound to a node rather than an index this moves it back if you insert an element at the root
|
||
|
|
||
|
if ( this->position == this->root )
|
||
|
{
|
||
|
this->root = new_node;
|
||
|
this->position = this->root;
|
||
|
}
|
||
|
|
||
|
// Increase the recorded size of the list by one
|
||
|
this->list_size++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::Add ( const CircularLinkedListType& input )
|
||
|
{
|
||
|
node * new_node;
|
||
|
|
||
|
if ( this->list_size == 0 )
|
||
|
{
|
||
|
this->root = new typename CircularLinkedList::node;
|
||
|
// root->item = new CircularLinkedListType;
|
||
|
// *(root->item)=input;
|
||
|
this->root->item = input;
|
||
|
this->root->next = this->root;
|
||
|
this->root->previous = this->root;
|
||
|
this->list_size = 1;
|
||
|
this->position = this->root;
|
||
|
// return *(position->item);
|
||
|
return this->position->item;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
if ( list_size == 1 )
|
||
|
{
|
||
|
this->position = new typename CircularLinkedList::node;
|
||
|
// position->item = new CircularLinkedListType;
|
||
|
this->root->next = this->position;
|
||
|
this->root->previous = this->position;
|
||
|
this->position->previous = this->root;
|
||
|
this->position->next = this->root;
|
||
|
// *(position->item)=input;
|
||
|
this->position->item = input;
|
||
|
this->list_size = 2;
|
||
|
this->position = this->root; // Don't move the position from the root
|
||
|
// return *(position->item);
|
||
|
return this->position->item;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
|
||
|
B
|
||
|
|
|
||
|
A --- C
|
||
|
|
||
|
new_node=B
|
||
|
position=A
|
||
|
position->next=C
|
||
|
|
||
|
Note that the order of the following statements is important */
|
||
|
|
||
|
new_node = new typename CircularLinkedList::node;
|
||
|
// new_node->item = new CircularLinkedListType;
|
||
|
|
||
|
// *(new_node->item)=input;
|
||
|
new_node->item = input;
|
||
|
|
||
|
// Point last of B to A
|
||
|
new_node->previous = this->position;
|
||
|
|
||
|
// Point next of B to C
|
||
|
new_node->next = ( this->position->next );
|
||
|
|
||
|
// Point last of C to B
|
||
|
( this->position->next ) ->previous = new_node;
|
||
|
|
||
|
// Point next of A to B
|
||
|
( this->position->next ) = new_node;
|
||
|
|
||
|
// Increase the recorded size of the list by one
|
||
|
this->list_size++;
|
||
|
|
||
|
// return *(new_node->item);
|
||
|
return new_node->item;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
inline void CircularLinkedList<CircularLinkedListType>::Replace( const CircularLinkedListType& input )
|
||
|
{
|
||
|
if ( this->list_size > 0 )
|
||
|
// *(position->item)=input;
|
||
|
this->position->item = input;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
void CircularLinkedList<CircularLinkedListType>::Del()
|
||
|
{
|
||
|
node * new_position;
|
||
|
|
||
|
if ( this->list_size == 0 )
|
||
|
return ;
|
||
|
|
||
|
else
|
||
|
if ( this->list_size == 1 )
|
||
|
{
|
||
|
// delete root->item;
|
||
|
delete this->root;
|
||
|
this->root = this->position = 0;
|
||
|
this->list_size = 0;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
( this->position->previous ) ->next = this->position->next;
|
||
|
( this->position->next ) ->previous = this->position->previous;
|
||
|
new_position = this->position->next;
|
||
|
|
||
|
if ( this->position == this->root )
|
||
|
this->root = new_position;
|
||
|
|
||
|
// delete position->item;
|
||
|
delete this->position;
|
||
|
|
||
|
this->position = new_position;
|
||
|
|
||
|
this->list_size--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
bool CircularLinkedList<CircularLinkedListType>::IsIn(const CircularLinkedListType& input )
|
||
|
{
|
||
|
node * return_value, *old_position;
|
||
|
|
||
|
old_position = this->position;
|
||
|
|
||
|
return_value = FindPointer( input );
|
||
|
this->position = old_position;
|
||
|
|
||
|
if ( return_value != 0 )
|
||
|
return true;
|
||
|
else
|
||
|
return false; // Can't find the item don't do anything
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
bool CircularLinkedList<CircularLinkedListType>::Find( const CircularLinkedListType& input )
|
||
|
{
|
||
|
node * return_value;
|
||
|
|
||
|
return_value = FindPointer( input );
|
||
|
|
||
|
if ( return_value != 0 )
|
||
|
{
|
||
|
this->position = return_value;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
return false; // Can't find the item don't do anything
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
typename CircularLinkedList<CircularLinkedListType>::node* CircularLinkedList<CircularLinkedListType>::FindPointer( const CircularLinkedListType& input )
|
||
|
{
|
||
|
node * current;
|
||
|
|
||
|
if ( this->list_size == 0 )
|
||
|
return 0;
|
||
|
|
||
|
current = this->root;
|
||
|
|
||
|
// Search for the item starting from the root node and incrementing the pointer after every check
|
||
|
// If you wind up pointing at the root again you looped around the list so didn't find the item, in which case return 0
|
||
|
do
|
||
|
{
|
||
|
// if (*(current->item) == input) return current;
|
||
|
|
||
|
if ( current->item == input )
|
||
|
return current;
|
||
|
|
||
|
current = current->next;
|
||
|
}
|
||
|
|
||
|
while ( current != this->root );
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
inline unsigned int CircularLinkedList<CircularLinkedListType>::Size( void )
|
||
|
{
|
||
|
return this->list_size;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
inline CircularLinkedListType& CircularLinkedList<CircularLinkedListType>::Peek( void )
|
||
|
{
|
||
|
// return *(position->item);
|
||
|
return this->position->item;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedListType CircularLinkedList<CircularLinkedListType>::Pop( void )
|
||
|
{
|
||
|
CircularLinkedListType element;
|
||
|
element = Peek();
|
||
|
Del();
|
||
|
return CircularLinkedListType( element ); // return temporary
|
||
|
}
|
||
|
|
||
|
// Prefix
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++()
|
||
|
{
|
||
|
if ( this->list_size != 0 )
|
||
|
position = position->next;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
// Postfix
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++(int)
|
||
|
{
|
||
|
CircularLinkedList<CircularLinkedListType> before;
|
||
|
before=*this;
|
||
|
operator++();
|
||
|
return before;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator++( int )
|
||
|
{
|
||
|
return this->operator++();
|
||
|
}
|
||
|
|
||
|
// Prefix
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--()
|
||
|
{
|
||
|
if ( this->list_size != 0 )
|
||
|
this->position = this->position->previous;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
// Postfix
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--(int)
|
||
|
{
|
||
|
CircularLinkedList<CircularLinkedListType> before;
|
||
|
before=*this;
|
||
|
operator--();
|
||
|
return before;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType>& CircularLinkedList<CircularLinkedListType>::operator--( int )
|
||
|
{
|
||
|
return this->operator--();
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
void CircularLinkedList<CircularLinkedListType>::Clear( void )
|
||
|
{
|
||
|
if ( this->list_size == 0 )
|
||
|
return ;
|
||
|
else
|
||
|
if ( this->list_size == 1 ) // {delete root->item; delete root;}
|
||
|
{
|
||
|
delete this->root;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
node* current;
|
||
|
node* temp;
|
||
|
|
||
|
current = this->root;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
temp = current;
|
||
|
current = current->next;
|
||
|
// delete temp->item;
|
||
|
delete temp;
|
||
|
}
|
||
|
|
||
|
while ( current != this->root );
|
||
|
}
|
||
|
|
||
|
this->list_size = 0;
|
||
|
this->root = 0;
|
||
|
this->position = 0;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
inline void CircularLinkedList<CircularLinkedListType>::Concatenate( const CircularLinkedList<CircularLinkedListType>& L )
|
||
|
{
|
||
|
unsigned int counter;
|
||
|
node* ptr;
|
||
|
|
||
|
if ( L.list_size == 0 )
|
||
|
return ;
|
||
|
|
||
|
if ( this->list_size == 0 )
|
||
|
* this = L;
|
||
|
|
||
|
ptr = L.root;
|
||
|
|
||
|
this->position = this->root->previous;
|
||
|
|
||
|
// Cycle through each element in L and add it to the current list
|
||
|
for ( counter = 0; counter < L.list_size; counter++ )
|
||
|
{
|
||
|
// Add item after the current item pointed to
|
||
|
// add(*(ptr->item));
|
||
|
|
||
|
Add ( ptr->item );
|
||
|
|
||
|
// Update pointers. Moving ptr keeps the current pointer at the end of the list since the add function does not move the pointer
|
||
|
ptr = ptr->next;
|
||
|
|
||
|
this->position = this->position->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
inline void CircularLinkedList<CircularLinkedListType>::Sort( void )
|
||
|
{
|
||
|
if ( this->list_size <= 1 )
|
||
|
return ;
|
||
|
|
||
|
// Call equal operator to assign result of mergesort to current object
|
||
|
*this = Mergesort( *this );
|
||
|
|
||
|
this->position = this->root;
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::Mergesort( const CircularLinkedList& L )
|
||
|
{
|
||
|
unsigned int counter;
|
||
|
node* location;
|
||
|
CircularLinkedList<CircularLinkedListType> L1;
|
||
|
CircularLinkedList<CircularLinkedListType> L2;
|
||
|
|
||
|
location = L.root;
|
||
|
|
||
|
// Split the list into two equal size sublists, L1 and L2
|
||
|
|
||
|
for ( counter = 0; counter < L.list_size / 2; counter++ )
|
||
|
{
|
||
|
// L1.add (*(location->item));
|
||
|
L1.Add ( location->item );
|
||
|
location = location->next;
|
||
|
}
|
||
|
|
||
|
for ( ;counter < L.list_size; counter++ )
|
||
|
{
|
||
|
// L2.Add(*(location->item));
|
||
|
L2.Add ( location->item );
|
||
|
location = location->next;
|
||
|
}
|
||
|
|
||
|
// Recursively sort the sublists
|
||
|
if ( L1.list_size > 1 )
|
||
|
L1 = Mergesort( L1 );
|
||
|
|
||
|
if ( L2.list_size > 1 )
|
||
|
L2 = Mergesort( L2 );
|
||
|
|
||
|
// Merge the two sublists
|
||
|
return Merge( L1, L2 );
|
||
|
}
|
||
|
|
||
|
template <class CircularLinkedListType>
|
||
|
CircularLinkedList<CircularLinkedListType> CircularLinkedList<CircularLinkedListType>::Merge( CircularLinkedList L1, CircularLinkedList L2 )
|
||
|
{
|
||
|
CircularLinkedList<CircularLinkedListType> X;
|
||
|
CircularLinkedListType element;
|
||
|
L1.position = L1.root;
|
||
|
L2.position = L2.root;
|
||
|
|
||
|
// While neither list is empty
|
||
|
|
||
|
while ( ( L1.list_size != 0 ) && ( L2.list_size != 0 ) )
|
||
|
{
|
||
|
// Compare the first items of L1 and L2
|
||
|
// Remove the smaller of the two items from the list
|
||
|
|
||
|
if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) )
|
||
|
// if ((*((L1.root)->item)) < (*((L2.root)->item)))
|
||
|
{
|
||
|
// element = *((L1.root)->item);
|
||
|
element = ( L1.root ) ->item;
|
||
|
L1.Del();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// element = *((L2.root)->item);
|
||
|
element = ( L2.root ) ->item;
|
||
|
L2.Del();
|
||
|
}
|
||
|
|
||
|
// Add this item to the end of X
|
||
|
X.Add( element );
|
||
|
|
||
|
X++;
|
||
|
}
|
||
|
|
||
|
// Add the remaining list to X
|
||
|
if ( L1.list_size != 0 )
|
||
|
X.Concatenate( L1 );
|
||
|
else
|
||
|
X.Concatenate( L2 );
|
||
|
|
||
|
return X;
|
||
|
}
|
||
|
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType> LinkedList<LinkedListType>::Mergesort( const LinkedList& L )
|
||
|
{
|
||
|
unsigned int counter;
|
||
|
typename LinkedList::node* location;
|
||
|
LinkedList<LinkedListType> L1;
|
||
|
LinkedList<LinkedListType> L2;
|
||
|
|
||
|
location = L.root;
|
||
|
|
||
|
// Split the list into two equal size sublists, L1 and L2
|
||
|
|
||
|
for ( counter = 0; counter < L.LinkedList_size / 2; counter++ )
|
||
|
{
|
||
|
// L1.add (*(location->item));
|
||
|
L1.Add ( location->item );
|
||
|
location = location->next;
|
||
|
}
|
||
|
|
||
|
for ( ;counter < L.LinkedList_size; counter++ )
|
||
|
{
|
||
|
// L2.Add(*(location->item));
|
||
|
L2.Add ( location->item );
|
||
|
location = location->next;
|
||
|
}
|
||
|
|
||
|
// Recursively sort the sublists
|
||
|
if ( L1.list_size > 1 )
|
||
|
L1 = Mergesort( L1 );
|
||
|
|
||
|
if ( L2.list_size > 1 )
|
||
|
L2 = Mergesort( L2 );
|
||
|
|
||
|
// Merge the two sublists
|
||
|
return Merge( L1, L2 );
|
||
|
}
|
||
|
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType> LinkedList<LinkedListType>::Merge( LinkedList L1, LinkedList L2 )
|
||
|
{
|
||
|
LinkedList<LinkedListType> X;
|
||
|
LinkedListType element;
|
||
|
L1.position = L1.root;
|
||
|
L2.position = L2.root;
|
||
|
|
||
|
// While neither list is empty
|
||
|
|
||
|
while ( ( L1.LinkedList_size != 0 ) && ( L2.LinkedList_size != 0 ) )
|
||
|
{
|
||
|
// Compare the first items of L1 and L2
|
||
|
// Remove the smaller of the two items from the list
|
||
|
|
||
|
if ( ( ( L1.root ) ->item ) < ( ( L2.root ) ->item ) )
|
||
|
// if ((*((L1.root)->item)) < (*((L2.root)->item)))
|
||
|
{
|
||
|
element = ( L1.root ) ->item;
|
||
|
// element = *((L1.root)->item);
|
||
|
L1.Del();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
element = ( L2.root ) ->item;
|
||
|
// element = *((L2.root)->item);
|
||
|
L2.Del();
|
||
|
}
|
||
|
|
||
|
// Add this item to the end of X
|
||
|
X.Add( element );
|
||
|
}
|
||
|
|
||
|
// Add the remaining list to X
|
||
|
if ( L1.LinkedList_size != 0 )
|
||
|
X.concatenate( L1 );
|
||
|
else
|
||
|
X.concatenate( L2 );
|
||
|
|
||
|
return X;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Prefix
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++()
|
||
|
{
|
||
|
if ( ( this->list_size != 0 ) && ( this->position->next != this->root ) )
|
||
|
this->position = this->position->next;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
// Postfix
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++(int)
|
||
|
{
|
||
|
LinkedList<LinkedListType> before;
|
||
|
before=*this;
|
||
|
operator++();
|
||
|
return before;
|
||
|
}
|
||
|
*/
|
||
|
// Postfix
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator++( int )
|
||
|
{
|
||
|
return this->operator++();
|
||
|
}
|
||
|
|
||
|
// Prefix
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--()
|
||
|
{
|
||
|
if ( ( this->list_size != 0 ) && ( this->position != this->root ) )
|
||
|
this->position = this->position->previous;
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
// Postfix
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--(int)
|
||
|
{
|
||
|
LinkedList<LinkedListType> before;
|
||
|
before=*this;
|
||
|
operator--();
|
||
|
return before;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
// Postfix
|
||
|
template <class LinkedListType>
|
||
|
LinkedList<LinkedListType>& LinkedList<LinkedListType>::operator--( int )
|
||
|
{
|
||
|
return this->operator--();
|
||
|
}
|
||
|
|
||
|
} // End namespace
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#pragma warning( pop )
|
||
|
#endif
|
||
|
|
||
|
#endif
|