想要搶先看後面的章節?打賞本文10元,即可獲得帶插圖全本下載地址!

打賞完成記得私信我哦 :p

10.5.2 刪除容器中的冗餘元素

現實世界流行減肥,各位愛美女士都想減去自己身上多餘的贅肉。這股減肥風潮也很快吹到了C++世界,各個容器也都嚷著要「減肥」——刪除容器當中冗餘的數據元素。

現實世界中的減肥比等房價下降還難,可是對於C++世界中的STL來說,「減肥」卻是一件很容易的事情,只需要利用幾個演算法三下兩下就可以刪除容器中的冗餘元素幫容器瘦身,效果要比那些個所謂的「減肥茶」好多了。本來這是STL的獨家祕方,可是看各個容器求瘦心切,於是就大方公佈出來,好讓各個容器藉此方一瘦為快。

很多時候,容器中都不可避免地會出現冗餘元素,可能是用戶錯誤地重複輸入,也可能是程序處理過程中產生的冗餘元素。這就像某些人喝涼水都會長肉一樣,容器中冗餘元素的出現,幾乎是不可避免的:

// 這裡的st1和st3雖然是不同的對象,但是它們的屬性都相同,
// 代表了相同的意義,因而可以認為它們是相互重複的,其中一個是冗餘的元素
Student st1("ChenLiangqiao", 173);
Student st2("WangGang", 163);
Student st3("ChenLiangqiao", 173); // 與st1相同
// 將這些對象都添加到容器中,容器中產生了冗餘元素
vector<Student> vecStu = {st1,st2,st3};

冗餘元素的出現,不僅會導致程序業務邏輯的混亂(兩個對象表示了同一個實體事物,有可能產生不一致),同時還會浪費寶貴的內存資源(原本只需要兩個Student對象空間的容器卻不得不佔用三個Student對象的空間)。容器中出現冗餘元素不要緊,因為我們有STL祖傳的「瘦身大法」,只要用上,很快就可以刪除容器中的冗餘元素,讓容器恢復苗條身材。STL的「瘦身大法」一共有三步:

第一步,對容器中的所有數據進行排序。例如:

// 第一步:讓容器中的Student對象按照身高排序
sort(vecStu.begin(), vecStu.end(), sortbyHeight);

第二步,也是最關鍵的一步,使用unique()演算法刪除容器中的冗餘元素。unique()演算法會調用容器中數據相應類型的「==」操作符來判斷兩個數據元素是否相等,如果兩個元素相等,就刪除其中的一個元素,只在容器中保留其中的一個。因為這裡容器中的數據是自定義的Student類型的對象,所以需要先重載這個類的「==」操作符,然後才能使用unique()演算法刪除其中的冗餘元素:

class Student
{
// …
public:
// 重載「==」操作符,判斷兩個對象是否相同
// 如果兩個對象的姓名和身高屬性都相同,則認為這兩個對象相同
bool operator == (const Student& st) const
{
// 使用「&&」保證兩個條件同時成立
return m_strName == st.GetName()
&& m_nHeight == st.GetHeight();
}
// …
};
// 第二步:刪除容器中的冗餘元素
auto it = unique( vecStu.begin(),
vecStu.end());

第三步,使用earse()演算法徹底刪除容器中的冗餘元素。在第二步中,我們使用unique()演算法刪除容器中的冗餘元素,其實並沒有真正意義上從容器中刪除這些冗餘數據,而只是將這些冗餘數據挪動到了容器的末尾位置,同時它會返回一個指向容器中有效數據的結束位置的迭代器。通過從begin()到這個迭代器範圍,我們就可以訪問到容器中沒有冗餘的所有數據。從使用的意義上來講,unique()演算法讓我們可以訪問容器中所有沒有冗餘的數據,達到了刪除容器中冗餘數據的目的,但是這些冗餘數據實際上仍然存在於容器中,仍然嚴重影響著容器的身材,所以作為STL「瘦身大法」的最後一步,還需要使用erase()演算法從容器中徹底刪除這些冗餘數據,達到真正「瘦身」的目的:

// 第三步:刪除容器末尾遺留的多餘元素
vecStu.erase( it, vecStu.end() );

從此,身輕如燕!


推薦閱讀:
相關文章