線性表的順序存儲(chǔ)結(jié)構(gòu)是用一段地址連續(xù)的存儲(chǔ)單元依次存儲(chǔ)線性表中的數(shù)據(jù)元素。
十年的藍(lán)田網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。全網(wǎng)整合營銷推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整藍(lán)田建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“藍(lán)田網(wǎng)站設(shè)計(jì)”,“藍(lán)田網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
使用一維數(shù)組實(shí)現(xiàn)順序存儲(chǔ)結(jié)構(gòu)。
template <typename T>
class SeqList:public List<T>
{
protected:
T* m_array;//順序存儲(chǔ)空間
int m_length;//當(dāng)前線性表的長度
};
一維順序存儲(chǔ)結(jié)構(gòu)可以是原生數(shù)組或是動(dòng)態(tài)分配的空間。因此,根據(jù)空間分配的不同,分為靜態(tài)線性表和動(dòng)態(tài)線性表。
(1)元素的獲取
順序存儲(chǔ)結(jié)構(gòu)的元素獲取操作:
A、判斷目標(biāo)位置是否合法
B、將目標(biāo)位置作為數(shù)組下標(biāo)獲取元素
bool get(int index, T& value)
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index < m_length);
if(ret)
{
//將目標(biāo)位置作為下標(biāo)獲取元素
value = m_array[index];
}
return ret;
}
(2)元素的插入操作
順序存儲(chǔ)結(jié)構(gòu)的元素插入操作:
A、判斷目標(biāo)位置是否合法
B、將目標(biāo)位置后的所有元素向后移一位
C、將新元素插入目標(biāo)位置
D、線性表長度增加1
bool insert(int index, const T& value)
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index <= m_length);
ret = ret && ((m_length + 1) <= capacity());
if(ret)
{
//將目標(biāo)位置后的所有元素后移一個(gè)位置
for(int i = m_length -1; index <= i; i--)
{
m_array[i+1] = m_array[i];
}
//將新元素插入到目標(biāo)位置
m_array[index] = value;
//線性表長度加1
m_length++;
}
return ret;
}
(3)元素的刪除操作
順序存儲(chǔ)結(jié)構(gòu)的元素刪除操作:
A、判斷目標(biāo)位置是否合法
B、將目標(biāo)位置后的所有元素前移一個(gè)位置
C、線性表長度減1
bool remove(int index)
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index < m_length);
if(ret)
{
//將目標(biāo)位置后的所有元素前移一位
for(int i = index; i < m_length-1; i++)
{
m_array[i] = m_array[i+1];
}
//將線性表長度減1
m_length--;
}
return ret;
}
(4)元素值的修改
順序存儲(chǔ)結(jié)構(gòu)中元素值的修改:
A、判斷目標(biāo)位置是否合法
B、修改目標(biāo)位置元素的值
bool set(int index, const T& value)
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index < m_length);
if(ret)
{
//修改目標(biāo)位置元素的值
m_array[index] = value;
}
return ret;
}
(5)線性表長度的獲取
順序存儲(chǔ)結(jié)構(gòu)線性表的長度獲取
int length()const
{
//線性表長度
return m_length;
}
(6)線性表的清空
void clear()
{
//清空線性表
m_length = 0;
}
(7)[]操作符重載
//[]操作符重載
T& operator[](int index)
{
//判斷目標(biāo)位置是否合法
if((0 <= index) && (index < m_length))
{
//返回下標(biāo)相應(yīng)的元素
return m_array[index];
}
else
{
THROW_EXCEPTION(IndexOutOfBoudsException, "Paramenter index is invalid...");
}
}
//const對(duì)象的[]重載
T operator[](int index)const
{
//轉(zhuǎn)換為非const對(duì)象后使用[]操作
return (const_cast<SeqList<T>&>(*this))[index];
}
(8)順序存儲(chǔ)結(jié)構(gòu)空間的大小
virtual int capacity()const = 0;
由于存儲(chǔ)空間在子類分配,因此為純虛函數(shù)。
template <typename T>
class SeqList:public List<T>
{
public:
bool insert(int index, const T& value)
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index <= m_length);
ret = ret && ((m_length + 1) <= capacity());
if(ret)
{
//將目標(biāo)位置后的所有元素后移一個(gè)位置
for(int i = m_length -1; index <= i; i--)
{
m_array[i+1] = m_array[i];
}
//將新元素插入到目標(biāo)位置
m_array[index] = value;
//線性表長度加1
m_length++;
}
return ret;
}
bool remove(int index)
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index < m_length);
if(ret)
{
//將目標(biāo)位置后的所有元素前移一位
for(int i = index; i < m_length-1; i++)
{
m_array[i] = m_array[i+1];
}
//將線性表長度減1
m_length--;
}
return ret;
}
bool set(int index, const T& value)
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index < m_length);
if(ret)
{
//修改目標(biāo)位置元素的值
m_array[index] = value;
}
return ret;
}
bool get(int index, T& value)const
{
//判斷目標(biāo)位置是否合法
bool ret = (0 <= index) && (index < m_length);
if(ret)
{
//將目標(biāo)位置作為下標(biāo)獲取元素
value = m_array[index];
}
return ret;
}
int length()const
{
//線性表長度
return m_length;
}
void clear()
{
//清空線性表
m_length = 0;
}
int find(const T& value)const
{
int ret = -1;
//遍歷線性表
for(int i = 0; i < m_length; i++)
{
//如果找到元素,退出循環(huán)
if(m_array[i] == value)
{
ret = i;
break;
}
}
return ret;
}
//[]操作符重載
T& operator[](int index)
{
//判斷目標(biāo)位置是否合法
if((0 <= index) && (index < m_length))
{
//返回下標(biāo)相應(yīng)的元素
return m_array[index];
}
else
{
THROW_EXCEPTION(IndexOutOfBoudsException, "Paramenter index is invalid...");
}
}
//const對(duì)象的[]重載
T operator[](int index)const
{
//轉(zhuǎn)換為非const對(duì)象后使用[]操作
return (const_cast<SeqList<T>&>(*this))[index];
}
virtual int capacity()const = 0;
protected:
T* m_array;//順序存儲(chǔ)空間
int m_length;//當(dāng)前線性表的長度
};
數(shù)據(jù)元素的前移:
將后面的數(shù)據(jù)元素向前移動(dòng),需要先將前面的數(shù)據(jù)元素前移,依次移動(dòng),直到最后一個(gè)數(shù)據(jù)元素前移,一般用于刪除一個(gè)數(shù)據(jù)元素后將后面的數(shù)據(jù)元素前移。
//將目標(biāo)位置后的所有元素前移一位
for(int i = index; i < m_length-1; i++)
{
m_array[i] = m_array[i+1];
}
數(shù)據(jù)元素的后移:
將前面的數(shù)據(jù)元素向后移動(dòng),需要先將最后的數(shù)據(jù)元素后移,依次移動(dòng),直到第i個(gè)數(shù)據(jù)元素被后移,一般用于插入一個(gè)新的數(shù)據(jù)元素,需要先將插入位置后的所有數(shù)據(jù)元素后移,在位置處放入新的數(shù)據(jù)元素。
//將目標(biāo)位置后的所有元素后移一個(gè)位置
for(int i = m_length -1; index <= i; i--)
{
m_array[i+1] = m_array[i];
}
使用原生數(shù)組作為順序存儲(chǔ)空間,使用模板參數(shù)確定數(shù)組大小。
template <typename T, int N>
class StaticList:public SeqList<T>
{
public:
StaticList()
{
this->m_array = m_space;//指定父類指針指向的空間
this->m_length = 0;//設(shè)置初始長度
}
int capacity() const
{
return N;
}
protected:
T m_space[N];//順序存儲(chǔ)空間,N為模板參數(shù)
};
需要父類的實(shí)現(xiàn)純虛函數(shù)capacity()。
使用動(dòng)態(tài)申請(qǐng)的堆空間作為順序存儲(chǔ)空間,動(dòng)態(tài)設(shè)置順序存儲(chǔ)空間的大小并確保重置順序存儲(chǔ)空間大小時(shí)的異常安全。
函數(shù)異常安全要求不泄漏任何資源,不允許破壞數(shù)據(jù)。為了確保異常安全,在異常拋出時(shí),必須確保:
A、對(duì)象內(nèi)的任何成員仍然能保持有效狀態(tài)
B、沒有數(shù)據(jù)的破壞及資源泄漏。
template <typename T>
class DynamicList:public SeqList<T>
{
public:
DynamicList(int capacity)
{
//申請(qǐng)動(dòng)態(tài)空間
this->m_array = new T[capacity];
if(this->m_array)
{
this->m_length = 0;//初始長度
this->m_capacity = capacity;//空間大小
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory...");
}
}
int capacity() const
{
return m_capacity;
}
void resize(int capacity)
{
if(capacity != m_capacity)
{
T* array = new T[capacity];
if(array)
{
int length = (this->length() < capacity ? this->length():capacity);
for(int i = 0; i < length; i++)
{
array[i] = this->m_array[i];
//如果拋出異常,原數(shù)組狀態(tài)沒有改變
}
T* temp = this->m_array;
this->m_array = array;
this->m_capacity = capacity;
this->m_length = length;
delete[] temp;
//如果拋出異常,重置后的數(shù)組狀態(tài)已經(jīng)改變
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory...");
}
}
}
~DynamicList()
{
delete[] this->m_array;//釋放申請(qǐng)的動(dòng)態(tài)空間
}
protected:
int m_capacity;//順序存儲(chǔ)空間的大小
};
順序存儲(chǔ)結(jié)構(gòu)線性表的插入和刪除操作的時(shí)間復(fù)雜度都是O(n),但是由于插入和刪除操作都會(huì)涉及到線性表中數(shù)據(jù)元素的移動(dòng),因此會(huì)頻繁涉及拷貝構(gòu)造函數(shù)和賦值操作符的調(diào)用,如果數(shù)據(jù)元素對(duì)象內(nèi)部的資源較多,對(duì)象間的復(fù)制、賦值將是非常耗時(shí)的,同時(shí)由于線性表是泛型模板,無法確定實(shí)際實(shí)例化的對(duì)象類型是否是占有資源的類類型,因此需要禁用拷貝構(gòu)造函數(shù)和賦值操作符,禁用的方式只需要將拷貝構(gòu)造函數(shù)和賦值操作符聲明為protected即可。
template <typename T>
class List:public Object
{
protected:
List(const List<T>& other);
List<T>& operator=(const List<T>& other);
public:
List(){}
virtual bool insert(int index, const T& value) = 0;
virtual bool remove(int index) = 0;
virtual bool set(int index, const T& value) = 0;
virtual bool get(int index, T& value) = 0;
virtual int length()const = 0;
virtual void clear() = 0;
};
順序存儲(chǔ)結(jié)構(gòu)線性表重載了[]操作符,因此可以使用[]操作符訪問順序存儲(chǔ)結(jié)構(gòu)線性表中的元素。但是線性表中必須存在要訪問的元素,即先插入元素才能使用[]操作符訪問元素。
要?jiǎng)?chuàng)建一個(gè)數(shù)組類取代原生數(shù)組,數(shù)組類需要避免原生數(shù)組的缺陷:
A、數(shù)組類包含長度信息
B、數(shù)組類能夠主動(dòng)發(fā)現(xiàn)越界訪問
數(shù)組類的設(shè)計(jì)如下:
A、抽象類模板,存儲(chǔ)空間的位置和大小由子類完成
B、重載數(shù)組操作符,判斷訪問下標(biāo)是否越界
C、提供數(shù)組長度的抽象訪問函數(shù)
D、拷貝構(gòu)造函數(shù)和賦值操作符需要在子類實(shí)現(xiàn)
數(shù)組的實(shí)現(xiàn):
template <typename T>
class Array:public Object
{
public:
virtual bool set(int index, const T& value)
{
bool ret = (0 <= index) && (index < length());
if(ret)
{
m_array[index] = value;
}
return ret;
}
virtual bool get(int index, T& value)
{
bool ret = (0 <= index) && (index < length());
if(ret)
{
value = m_array[index];
}
return ret;
}
T& operator[](int index)
{
if((0 <= index) && (index < length()))
{
return m_array[index];
}
else
{
THROW_EXCEPTION(IndexOutOfBoudsException, "Parameter index is valid...");
}
}
T operator[](int index)const
{
return const_cast<T&>(*this)[index];
}
virtual int length()const = 0;
protected:
T* m_array;
};
}
指定原生數(shù)組作為數(shù)組類的存儲(chǔ)空間實(shí)現(xiàn)靜態(tài)數(shù)組類,使用模板參數(shù)指定數(shù)組大小,實(shí)現(xiàn)函數(shù)返回?cái)?shù)組的長度,實(shí)現(xiàn)重載拷貝構(gòu)造函數(shù)和賦值操作符。
template <typename T,int N> class StaticArray:public Array<T> { public: StaticArray() { this->m_array = m_space; } //拷貝構(gòu)造函數(shù) StaticArray(const StaticArray<T,N>& other) { this->m_array = m_space; for(int i = 0; i < N; i++) { m_space[i] = other.m_space[i]; } } //賦值操作符 StaticArray& operator=(const StaticArray<T,N>& other) { if(this != &other) { for(int i = 0; i< N; i++) { m_space[i] = other.m_space[i]; } } return *this; } int length() const { return N; } protected: T m_space[N];//存儲(chǔ)空間 };
3、動(dòng)態(tài)分配數(shù)組實(shí)現(xiàn)
使用動(dòng)態(tài)分配的堆空間作為數(shù)組類的存儲(chǔ)空間實(shí)現(xiàn)動(dòng)態(tài)分配數(shù)組類。 類模板設(shè)計(jì)需要?jiǎng)討B(tài)確定分配存儲(chǔ)空間的大小,實(shí)現(xiàn)函數(shù)返回?cái)?shù)組大小,實(shí)現(xiàn)拷貝構(gòu)造函數(shù)和賦值操作符。
template <typename T> class DynamicArray:public Array<T> { public: //構(gòu)造函數(shù) DynamicArray(int length) { this->m_array = new T[length]; if(this->m_array != NULL) { this->m_length = length; } else { THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory..."); } } //拷貝構(gòu)造函數(shù) DynamicArray(const DynamicArray<T>& other) { this->m_array = new T[other.m_length]; if(this->m_array != NULL) { this->m_length = other.m_length; } else { THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory..."); } } //賦值操作符 DynamicArray<T>& operator=(const DynamicArray<T>& other) { if(this != &other) { T* array = new T[other.m_length]; if(array != NULL) { for(int i = 0; i < other.m_length; i++) { array[i] = other.m_array[i]; } T* temp = this->m_array; this->m_array = array; this->m_length = other.m_length; delete[] temp; } else { THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory..."); } } return *this;
}
int length()const
{
return m_length;
}
//重置數(shù)組長度
void resize(int length)
{
if(this->m_length != length)
{
T* array = new T[length];
if(array != NULL)
{
int size = (length < this->m_length)?length:this->m_length;
for(int i = 0; i < size; i++)
{
array[i] = this->m_array[i];
}
T* temp = this->m_array;
this->m_array = array;
this->m_length = length;
delete[] temp;
}
else
{
THROW_EXCEPTION(NoEnoughMemoryException, "No enough memory...");
}
}
}
~DynamicArray()
{
delete[] this->m_array;
}
protected:
int m_length;//數(shù)組長度
};
網(wǎng)站欄目:數(shù)據(jù)結(jié)構(gòu)(三)——基于順序存儲(chǔ)結(jié)構(gòu)的線性表
路徑分享:http://chinadenli.net/article42/gppjhc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、靜態(tài)網(wǎng)站、網(wǎng)站收錄、網(wǎng)站導(dǎo)航、定制開發(fā)、網(wǎng)頁設(shè)計(jì)公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)