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