List(C++模版实现的带哨兵的双向链表)
#ifndef C11LEARN_LIST_H
#define C11LEARN_LIST_H
template<typename T>
class List
{
protected:
class Node
{
public:
Node *pre;
Node *next;
T key;
Node(){}
Node(const T key):key(key){}
};
private:
Node* Nil;
int size;
public:
List();
virtual ~List();
List(const List<T> & list);
const List<T> & operator=(const List<T> & list);
const List<T> & operator+(const List<T> & list);
const List<T> & operator-(const List<T> & list);
List<T> merge(const List<T> & list);
List<T> except(const List<T> & list);
List<T> intersect(const List<T> & list);
void add(const T key);
void insert(const T key,int position);
bool remove(const T key);
bool remove_all(const T key);
bool remove_at(int index);
bool contain(const T &key);
T operator[](int index) const;
T & operator[] (int index);
bool empty();
void clear();
int length() const;
int length();
void sort(bool ascending = true);
void sort(void(*f)(T *array,int length));
const List<T> & distinct();
private:
Node* search(const T & key);
Node* get(int index)const;
void add(Node* node);
bool remove(Node* node);
void quick_sort(T*array,int start,int end,bool ascending = true);
int partition(T*array,int start,int end,bool ascending);
};
template<typename T>
List<T>::List()
{
Nil = new Node();
Nil->next = Nil;
Nil->pre = Nil;
size = 0;
}
template<typename T>
List<T>::~List(){
clear();
delete Nil;
}
template<typename T>
List<T>::List(const List<T> & list)
{
Nil = new Node();
Nil->next = Nil;
Nil->pre = Nil;
size = 0;
Node * current = list.Nil->next;
while (current != list.Nil)
{
add(current->key);
current = current->next;
}
}
template<typename T>
const List<T>& List<T>::operator=(const List<T> & list){
if(&list == this)return *this;
clear();
Node * current = list.Nil->next;
while (current != list.Nil)
{
add(current->key);
current = current->next;
}
return *this;
}
template<typename T>
List<T> List<T>::merge(const List<T> & list)
{
List<T> temp(*this);
temp.distinct();
Node* current = list.Nil->next;
while (current!=list.Nil)
{
if(!temp.contain(current->key))
{
temp.add(current->key);
}
current = current->next;
}
return temp;
}
template<typename T>
List<T> List<T>::except(const List<T> & list){
List<T> temp(*this);
temp.distinct();
Node* current = list.Nil->next;
while (current!=list.Nil)
{
if(temp.contain(current->key))
{
temp.remove(current->key);
}
current = current->next;
}
return temp;
}
template<typename T>
List<T> List<T>::intersect(const List<T> & list){
List<T> temp;
Node* current = list.Nil->next;
while (current!=list.Nil)
{
if(contain(current->key))
{
temp.add(current->key);
}
current = current->next;
}
temp.distinct();
return temp;
}
template<typename T>
const List<T> & List<T>::distinct(){
if(size == 0) return *this;
T* array = new T[size];
int index = 0;
Node* current = Nil->next;
while (current!=Nil)
{
array[index] = current->key;
current =current->next;
index++;
}
quick_sort(array,0,size-1);
T current_key = array[0];
for (int i = 1; i < size; ++i) {
if(current_key == array[i])
{
remove(current_key);
}
else
{
current_key = array[i];
}
}
delete[] array;
return *this;
}
template<typename T>
void List<T>::add(const T key)
{
Node* node = new Node(key);
size++;
add(node);
}
template<typename T>
void List<T>::add(Node* node){
if(Nil->next == Nil)
{
Nil->pre = node;
Nil->next = node;
node->pre = Nil;
node->next = Nil;
}
else
{
Nil->pre->next = node;
node->pre = Nil->pre;
node->next = Nil;
Nil->pre = node;
}
}
template<typename T>
void List<T>::insert(const T key,int position)
{
if(position<0 || position>size)
throw "out of bound";
if(position == size || size == 0)
{
add(key);
}
else
{
Node* node = new Node(key);
Node* current = get(position);
current->pre->next = node;
node->pre = current->pre;
node->next = current;
current->pre = node;
size++;
if(position == 0)
{
Nil->next = node;
}
}
}
template<typename T>
bool List<T>::remove(const T key){
Node *result = search(key);
if(result!= Nil)
{
remove(result);
return true;
}
return false;
}
template<typename T>
bool List<T>::contain(const T& key){
return search(key) != Nil;
}
template<typename T>
bool List<T>::empty(){
return Nil->next == Nil;
}
template<typename T>
typename List<T>::Node* List<T>::search(const T &key) {
Node * current = Nil->next;
while (current != Nil && current->key!=key)
{
current = current->next;
}
return current;
}
template<typename T>
bool List<T>::remove(Node* node){
if(empty()) return false;
node->pre->next = node->next;
node->next->pre = node->pre;
size --;
delete node;
return true;
}
template<typename T>
void List<T>::clear(){
Node* current = Nil->next;
while (current!= Nil)
{
Node * temp = current;
current = current->next;
delete temp;
}
Nil->next = Nil;
Nil->pre = Nil;
size = 0;
}
template<typename T>
int List<T>::length() const {
return size;
}
template<typename T>
int List<T>::length() {
return size;
}
template<typename T>
T List<T>::operator[](int index) const{
return get(index)->key;
}
template<typename T>
T & List<T>::operator[] (int index){
return get(index)->key;
}
template<typename T>
typename List<T>::Node* List<T>::get(int index) const{
if(index>=size || index < 0) throw "Index out of bounds";
Node * current;
if(index>=size/2)
{
index = size - index - 1;
current = Nil->pre;
while (index-->0)
{
current = current->pre;
}
}
else
{
current = Nil->next;
while (index-->0)
{
current = current->next;
}
}
return current;
}
template<typename T>
bool List<T>::remove_at(int index){
if(index>=size) return false;
return remove(get(index));
}
template<typename T>
void List<T>::quick_sort(T*array,int start,int end,bool ascending){
if(start<end)
{
int k = partition(array,start,end,ascending);
quick_sort(array,start,k-1,ascending);
quick_sort(array,k+1,end,ascending);
}
}
template<typename T>
int List<T>::partition(T*array,int start,int end,bool ascending){
T key = array[end];
int p = start - 1;
T temp;
for (int i = start; i < end; ++i) {
if((array[i] <= key && ascending) ||(array[i] >= key && !ascending) )
{
p++;
temp = array[p];
array[p] = array[i];
array[i] = temp;
}
}
array[end] = array[p+1];
array[p+1] = key;
return p+1;
}
template<typename T>
void List<T>::sort(bool ascending){
if(size == 0) return;
T*array = new T[size];
Node* current = Nil->next;
int index = 0;
while (current!=Nil)
{
array[index] = current->key;
current = current->next;
index++;
}
quick_sort(array,0,size - 1,ascending);
int length = size;
clear();
for (int i = 0; i < length; ++i) {
add(array[i]);
}
delete[] array;
}
template<typename T>
void List<T>::sort(void(*f)(T *array,int length)){
if(size == 0) return;
T*array = new T[size];
Node* current = Nil->next;
int index = 0;
while (current!=Nil)
{
array[index] = current->key;
current = current->next;
index++;
}
f(array,size);
int length = size;
clear();
for (int i = 0; i < length; ++i) {
add(array[i]);
}
delete[] array;
}
template<typename T>
const List<T> & List<T>::operator+(const List<T> & list){
Node* current = list.Nil->next;
while (current!=list.Nil)
{
add(current->key);
current = current->next;
}
return *this;
}
template<typename T>
const List<T> & List<T>::operator-(const List<T> & list){
Node* current = list.Nil->next;
while (current!=list.Nil)
{
remove_all(current->key);
current = current->next;
}
return *this;
}
template<typename T>
bool List<T>::remove_all(const T key){
Node* current = Nil->next;
bool success = false;
while (current!=Nil)
{
if(current->key == key)
{
success = true;
Node* node = current;
current = current->next;
node->pre->next = node->next;
node->next->pre = node->pre;
size --;
delete node;
}
else
{
current = current->next;
}
}
return success;
}
#endif