CList的用法理解
CList是一個(gè)雙向鏈表類(lèi)。CList的優(yōu)勢(shì)是快速靈活的插入和刪除。但是在訪問(wèn)元素的時(shí)候,會(huì)多一個(gè)N的時(shí)間復(fù)雜度。在元素很多的時(shí)候,建議把數(shù)據(jù)分段存儲(chǔ)。
1、包含頭文件Afxtempl.h
???? 在你要使用CList鏈表類(lèi)的地方,使用#include? <Afxtempl.h>,或者直接在stdafx.h中包含這句。
2、理解CList的聲明和構(gòu)造方法
CList的聲明如下:
template< class TYPE, class ARG_TYPE >
class CList : public CObject
CList的聲明有2種方式,決定的是參數(shù)的使用是引用,還是復(fù)制。
例如:
CList<CString ,CString&> list1;??????? //注意引用符號(hào)的位置是在類(lèi)型后面。<類(lèi)型&>
CList<CString,CString> list2;??????????
第一個(gè)參數(shù),表示的是鏈表的元素的數(shù)據(jù)類(lèi)型,這里類(lèi)似一個(gè)聲明,聲明你使用的鏈表中的數(shù)據(jù)類(lèi)型是什么。
第二個(gè)參數(shù),分2種形式,一種是引用形式,一種是復(fù)制形式,那么這個(gè)引用和復(fù)制,體現(xiàn)的作用在哪里呢?其實(shí),這個(gè)引用和復(fù)制,只是體現(xiàn)在元素的添加,查找上面。比如我們往剛才聲明的這個(gè)鏈表list1中添加元素。
CList<CString ,CString&> list1; //
CString str = "abc";
list1.AddTail(str);????????????? //str是以引用的方式,添加到list1中的,類(lèi)似聲明一個(gè)函數(shù) void fun(CString &a);
再看另外一個(gè)中聲明方式:
CList<CString,CString> list2;//
CString str = "abc";
list2.AddTail(str);???????????? //str是以復(fù)制的方式添加的。
其實(shí)2種方式都能達(dá)到向鏈表中添加數(shù)據(jù)的目的,在數(shù)據(jù)結(jié)構(gòu)很小的時(shí)候,其實(shí)是沒(méi)有什么差別的,但是在數(shù)據(jù)結(jié)構(gòu)很大的時(shí)候,比如一個(gè)數(shù)據(jù)元素就有1M,甚至10M,引用就變得有意義了,這個(gè)時(shí)候使用引用,鏈表是直接把str的地址中的內(nèi)容添加到鏈表中了,使用復(fù)制,還需要先在內(nèi)存中復(fù)制一下str,然后再把復(fù)制的內(nèi)容添加到list中去。好了,現(xiàn)在懂了嗎?如果沒(méi)有,還得看下C++函數(shù)的形參的設(shè)置。是引用,還是非引用~
3、添加元素
? 例如:CList<CStirng,CString&>? myList;
(1)在CList的尾部添加元素?
?????????? POSITION AddTail( ARG_TYPE newElement );???? //在尾部添加一個(gè)元素,返回值是新插入元素的位置
????????void AddTail( CList* pNewList );????????????????????????????????????? //在尾部添加另一個(gè)鏈表中的內(nèi)容。鏈表的數(shù)據(jù)類(lèi)型要一致。
????????? 比如:myList.AddTail("abc");
??(2)? 在CList的頭部添加元素
????????? POSITION AddHead( ARG_TYPE newElement );?????? //在鏈表最開(kāi)始插入一個(gè)元素,返回值是新插入的元素的位置
????????? void AddHead( CList* pNewList );
???????? 例如:myList.AddHead(CString("ABC"));
?(3)在一個(gè)位置之前添加元素
????????? POSITION InsertBefore( POSITION position, ARG_TYPE newElement );????? //在position前面插入一個(gè)元素,返回新插入元素的位置。其實(shí)就是position前面一個(gè)位置
???????? 例如:
???????? POSITION pos = myList.GetHeadPostion();
?????????pos = myList.InsertBefore(pos, CString("ABC"));
???????? pos = myList.InsertBefore(pos, CString("123"));
?(4)在一個(gè)位置之后添加元素
????????? POSITION InsertAfter( POSITION position, ARG_TYPE newElement );?????? //在postion后面插入一個(gè)元素,返回新插入元素的位置
????????? 例如:
????????? POSITION pos = myList.GetTailPostion();
??????????pos = myList.InsertAfter(pos, CString("ABC"));
????????? pos = myList.InsertAfter(pos, CString("123"));
4、???? 查找元素:CList有2個(gè)函數(shù),是非常方便我們查找的。
?????? (1)直接查找元素
??????????? POSITION Find( ARG_TYPE searchValue, POSITION startAfter = NULL) const; 返回的是查找到的元素的第一個(gè)位置(如果鏈表中有多個(gè)重復(fù)的元素)。沒(méi)有找到就返回空
?????????? 例如:
??????????? CList<CString,CString&> myList;
?????????? myList.AddHead(CString("XYZ"));
?????????? myList.AddHead(CString("ABC"));
?????????? myList.AddHead(CString("123"));
????????? POSITION pos = myList.GetAt(pos));
???????? 然后就可以通過(guò)pos來(lái)操作這個(gè)元素了。比如GetAt(pos),InsertAfter(pos)等。
???????? (2)通過(guò)下標(biāo)來(lái)查找位置,通過(guò)下標(biāo)是非常方便的。
?????????? POSITION FindIndex( int nIndex ) const;?????????? //返回第i個(gè)元素的位置,然后可以通過(guò)位置來(lái)對(duì)元素進(jìn)行操作。
???????????例如:
?????????? CList<CString,CString&> myList;
????????? ?myList.AddTail(CString("XYZ"));
?????????? myList.AddTail(CString("ABC"));
?????????? myList.AddTail(CString("123"));
?????????? POSITION pos1 = myList.FindIndex(0);
?????????? POSITION pos2 = myList.FindIndex(2);
?????????? CString str1 = myList.GetAt(pos1);??????????? //str1就等于"XYZ"
?????????? CString?str2 = myList.GetAt(pos2);??????????? //str2就等于“123”
?????????? CStirng?str3 = myList.GetAt(myList.FindIndex(1));???? //str3等于"ABC"
???????? (3)遍歷查找???????
//如果鏈表是const類(lèi)型的,這些函數(shù),返回的是一個(gè)復(fù)制元素,如果不是const的,返回的是鏈表中元素的引用。但是怎么設(shè)置成一個(gè)const類(lèi)型的,我都還不知道。所以,一般我們使用這些函數(shù)得到的元素,都是引用的,可以直接對(duì)鏈表的元素復(fù)制:比如myList.GetHead() = "AAA";就能把表頭置為"AAA"。
TYPE& GetHead( );?????????????????? //得到第一個(gè)元素,確保鏈表不為空,使用IsEmpty()
TYPE GetHead( ) const;?????????
TYPE& GetTail( );?????????????????????//得到表尾元素
TYPE GetTail() const;
TYPE& GetNext( POSITION& rPosition );????????????????
TYPE GetNext( POSITION& rPosition ) const;
TYPE& GetPrev( POSITION& rPosition );
TYPE GetPrev( POSITION& rPosition ) const;
TYPE& GetAt( POSITION position );
TYPE GetAt( POSITION position ) const;
?
5、刪除元素
?????????? (1)刪除全部元素,刪除后,鏈表為空。
???????????? void RemoveAll( );?????????
?????????例如: myList.RemoveAll();
??????(2)刪除position處的元素
????????? void RemoveAt( POSITIONposition );??? //這里要保證position是有效的,不是空的,如果是空的,調(diào)試版本會(huì)報(bào)錯(cuò)。release版本不會(huì)報(bào)錯(cuò)。
???????? 例如:myList.RemoveAt(myList.FindIndex(1));
??????(3)刪除表頭??????
????????? TYPE RemoveHead( );??????????????????? //返回值是沒(méi)有刪除的時(shí)候的表頭元素。
?????(4)刪除表尾
???????? TYPE RemoveTail( );?????????????????????? //返回值是沒(méi)有刪除的時(shí)候的表尾元素。
6、鏈表的遍歷
????????? 方式1:
???????? POSITION pos = myList.GetHeadPostion();
???????? while(pos != NULL)
???????? {
?????????????????? CString? str = myList.GetNext(pos);???????????????? //GetNext(pos),先返回pos位置的元素的值,再把pos指向當(dāng)前位置的下一個(gè)。
???????? }
???????? 方式2:
???????? for(int i = 0 ; i < myList.GetCount(); i++)
????????? {
?????????????????? CString str = myList.GetAt(myList.FindIndex(i));
?????????? }
???????? 總結(jié):方式2,明顯比方式1慢.方式1只需要執(zhí)行N此就可以了,方式2,需要執(zhí)行1+2+。。。+N = (1 + N)*N/2次
由于時(shí)間關(guān)系,寫(xiě)的也不是非常完整,需要這方面知識(shí)的,請(qǐng)多看MSDN幫助信息,祝你順利~
最后還是請(qǐng)教一下大家,怎么把CList聲明為const類(lèi)型?歡迎留言~
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的CList的用法理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: 双时隙的工作原理_一文读懂跨阻放大器的工
 - 下一篇: 【正点原子Linux连载】第三十三章 U