#ifndef LIST_H
#define LIST_H
#include <exception>
using namespace std;
//異常類,當查詢的索引發生錯誤的時候拋出這個異常
class BadIndex :public exception
{
public:
virtual const char* what() const throw()
{
return "你輸入的索引位置錯誤";
}
};
template <typename T>
class List;
//計數類指針,用來在list中使用。沒有定義複製控制,默認的就符合要求
template <typename P>
class ListRep
{
private:
P *m_rep;
int m_useCount;
friend class List<P>;
ListRep(P* rep);
~ListRep();
//將使用計數增加一
void increment();
//將使用計數減少一,當使用計數減小到0的時候刪除指針所指向的資源
//不能刪除對象本身,那樣會出錯
void decrement();
//將一個指針所指向的資源複製到另一個指針中
//這主要是在list中進行插入,刪除以及向其中添加數據的時候使用
//當進行這些操作的時候不能改變指針多指向的單元因爲這個時候不止
//一個指針指向它,所以要複製單獨的一份進行操作
void copy(const ListRep *lr, int size);
};
template <typename P>
void ListRep<P>::copy(const ListRep *lr, int size) //不會對目標區間的大小做檢查
{
for (int i = 0; i != size; ++i)
(this->m_rep)[i] = (lr->m_rep)[i];
}
template <typename P>
ListRep<P>::ListRep(P *rep):m_rep(rep), m_useCount(1)//不能將參數的指針聲明爲const
{}
template <typename P>
inline void ListRep<P>::increment()
{
++m_useCount;
}
template <typename P>
inline void ListRep<P>::decrement()
{
if (--m_useCount == 0)
delete [] m_rep;
}
template <typename P>
ListRep<P>::~ListRep() //忘記加模板參數
{
delete [] m_rep;
}
template <typename T>
class List
{
private:
int m_maxSize;
ListRep<T> *m_ptr;
int m_size;
//檢查一個索引是否爲表中的正確的位置,如果表爲空那麼任何的位置都是錯的
bool rightPo(int po) const;
//在表的某個位置插入數據val,在push中也使用這個函數
void intoList(int po, const T &val);
public:
//構造一個指定長度的線性表,如果沒有給出長度那個有默認的值進行構造
explicit List(int maxSize = 5);
//將源表中的數據複製到目標表中
List(const List &l);
//模板類中可以不用指定參數把類名當作類型名
//但是作爲返回值則要指定類的參數
const List<T>& operator = (const List &l);
//兩個表具有相同的長度,同時包含相同的數據
//並且數據在表中的位置具有一一對應咋這兩個表相同
bool operator == (const List &l) const;
//利用==實現
bool operator != (const List &l) const;
//將表清空,刪除表原來擁有的資源
void clear();
//表是否爲空
bool empty() const;
//返回表的長度
int listLengh() const;
//返回某個位置的數據,如果該位置正確用t返回這個數據並返回true,如果位置不正確
//則t的值是個爲定義的數據,返回false
T getElem(int po) const;
//在某個位置之前插入一個 數據,如果該位置不是表中正確的位置
//則不向表中插入任何的數據
void insert(int po, const T &val);
//刪除某個位置上的數據,如果該位置不是個正確的位置不做任何刪除操作
void erase(int po);
//向表中壓入數據
void push(const T& val);
};
template <typename T>
bool List<T>::rightPo(int po) const
{
if (m_size == 0)
return false;
else
{
if (po < 0 || po >= m_size)
return false;
else
return true;
}
}
template <typename T>
void List<T>::intoList(int po, const T &val)
{
if (m_size > m_maxSize)
m_maxSize *= 2;
ListRep<T> *p = new ListRep<T>(new T[m_maxSize]);
p->copy(m_ptr, m_size-1);
m_ptr->decrement();
m_ptr = p;
T *fp;
T *sp;
fp = (m_ptr->m_rep) + m_size -1;
sp = fp -1;
for (; fp != (m_ptr->m_rep)+po; --sp, --fp)
*fp = *sp;
*fp = val;
}
template <typename T>
List<T>::List(int maxSize):m_maxSize(maxSize),m_ptr(new ListRep<T>(new T[m_maxSize]))
{
m_size = 0;
}
template <typename T>
List<T>::List(const List &l)
{
m_maxSize = l.m_maxSize;
m_size = l.m_size;
m_ptr = l.m_ptr;
m_ptr->increment();
}
template <typename T>
const List<T>& List<T>::operator =(const List &l)
{
if (this != &l)
{
m_size = l.m_size;
m_maxSize = l.maxSize;
m_ptr->decrement();
m_ptr = l.m_ptr;
m_ptr->increment();
}
return *this;
}
template <typename T>
bool List<T>::operator == (const List &l) const
{
if (m_size == l.m_size)
{
if (m_ptr == l.m_ptr)
return true;
}
return false;
}
template <typename T>
bool List<T>::operator != (const List &l) const
{
return !(*this == l);
}
template <typename T>
void List<T>::clear()
{
m_size = 0;
m_maxSize = 5;
m_ptr->decrement();
m_ptr = new ListRep<T>(new T[m_maxSize]); //使用模板類進行動態分配的時候
//要記得帶上參數
}
template <typename T>
inline bool List<T>::empty() const
{
return m_size == 0;
}
template <typename T>
inline int List<T>::listLengh() const
{
return m_size;
}
template <typename T>
T List<T>::getElem(int po) const
{
if (rightPo(po))
return (m_ptr->m_rep)[po];
else
throw BadIndex();
}
template <typename T>
void List<T>::insert(int po, const T &val)
{
if (rightPo(po))
{
++m_size;
intoList(po, val);
}
else
throw BadIndex();
}
template <typename T>
void List<T>::erase(int po)
{
if (rightPo(po))
{
ListRep<T> *p = new ListRep<T>(new T[m_size]);
p->copy(m_ptr, m_size);
m_ptr->decrement();
m_ptr = p;
T *fp;
T *sp;
fp = (m_ptr->m_rep)+po;
sp = fp + 1;
--m_size;
for (; fp != (m_ptr->m_rep)+m_size; ++fp, ++sp)
*fp = *sp;
}
else
throw BadIndex();
}
template <typename T>
void List<T>::push(const T &val)
{
if (m_size + 1 <= m_maxSize)
{
(m_ptr->m_rep)[m_size] = val;
++m_size;
}
else
{
++m_size;
intoList(m_size, val);
}
}
#endif