單向連結清單(單連結清單)是連結清單的一種,其特點是連結清單的連結方向是單向的,對連結清單的通路要通過順序讀取從頭部開始;連結清單是使用指針進行構造的清單;又稱為結點清單,因為連結清單是由一個個結點組裝起來的;其中每個結點都有指針成員變量指清單中的下一個結點;
清單是由結點構成,由head指針指向第一個成為表頭的結點而終止于最後一個指向nuLL的指針;
鍊式存儲結構
在計算機中用一組任意的存儲單元存儲線性表的資料元素(這組存儲單元可以是連續的,也可以是不連續的).
它不要求邏輯上相鄰的元素在實體位置上也相鄰.是以它沒有順序存儲結構所具有的弱點,但也同時失去了順序表可随機存取的優點.
鍊式存儲結構特點:
1、比順序存儲結構的存儲密度小 (每個節點都由資料域和指針域組成,是以相同空間内假設全存滿的話順序比鍊式存儲更多)。
2、邏輯上相鄰的節點實體上不必相鄰。
3、插入、删除靈活 (不必移動節點,隻要改變節點中的指針)。
4、查找結點時鍊式存儲要比順序存儲慢。
5、每個結點是由資料域和指針域組成。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以後的筆記潇汀會盡量詳細講解一些相關知識的,希望大家繼續關注我的部落格。
本節筆記到這裡就結束了。
潇汀一有時間就會把自己的學習心得,覺得比較好的知識點寫出來和大家一起分享。
程式設計開發的路很長很長,非常希望能和大家一起交流,共同學習,共同進步。
如果文章中有什麼疏漏的地方,也請大家指正。也希望大家可以多留言來和我探讨程式設計相關的問題。
最後,謝謝你們一直的支援~~~
C++完整個代碼示例(代碼在VS2005下測試可運作)
AL_Node.h
/**
@(#)$Id: AL_Node.h 44 2013-09-13 08:50:04Z xiaoting $
@brief store data, and be used to AL_ListSingle, AL_ListDouble, AL_ListCircular and so on
Chain storage structure//
The computer using a set of arbitrary linear table storage unit stores data elements (which may be a continuous plurality of memory cells, it can be discontinuous).
It does not require the logic elements of adjacent physical location is adjacent to and therefore it is not sequential storage structure has a weakness, but also lost the sequence table can be accessed randomly advantages.
Chain store structural features:
1, compared with sequential storage density storage structure (each node consists of data fields and pointers domains, so the same space is full, then assume full order of more than chain stores).
2, the logic is not required on the adjacent node is physically adjacent.
3, insert, delete and flexible (not the mobile node, change the node as long as the pointer).
4, find the node when stored sequentially slower than the chain stores.
5, each node is a pointer to the data fields and domains.
@Author $Author: xiaoting $
@Date $Date: 2013-09-13 16:50:04 +0800 (周五, 13 九月 2013) $
@Revision $Revision: 44 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_Node.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_Node.h 44 2013-09-13 08:50:04Z xiaoting $
*/
#ifndef CXX_AL_NODE_H
#define CXX_AL_NODE_H
///
// AL_Node
///
template<typename T> class AL_ListSingle;
template<typename T> class AL_ListDouble;
template<typename T> class AL_ListCircularSingle;
template<typename T> class AL_ListCircularDouble;
template<typename T> class AL_StackList;
template<typename T> class AL_QueueList;
template<typename T> class AL_QueuePriorityList;
template<typename T>
class AL_Node
{
public:
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_Node();
protected:
private:
friend class AL_ListSingle<T>;
friend class AL_ListDouble<T>;
friend class AL_ListCircularSingle<T>;
friend class AL_ListCircularDouble<T>;
friend class AL_StackList<T>;
friend class AL_QueueList<T>;
friend class AL_QueuePriorityList<T>;
/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
AL_Node();
/**
* Construction
*
* @param const T& tTemplate <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
AL_Node(const T& tTemplate);
public:
protected:
private:
T m_data; //the friend class can use it directly
AL_Node *m_pPre; //previous data AL_ListDouble will use it
AL_Node *m_pNext; //next data
};
///
// AL_Node
///
/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
template<typename T>
AL_Node<T>::AL_Node():
m_pPre(NULL),
m_pNext(NULL)
{
//memset(&m_data, 0x00, sizeof(T)); //can not use memset, as to pointer or virtural pointer of class
}
/**
* Construction
*
* @param const T& tTemplate <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
template<typename T>
AL_Node<T>::AL_Node(const T& tTemplate):
m_data(tTemplate),
m_pPre(NULL),
m_pNext(NULL)
{
}
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_Node<T>::~AL_Node()
{
//it doesn't matter to clear the pointer or not.
m_pPre = NULL;
m_pNext = NULL;
}
#endif // CXX_AL_NODE_H
/* EOF */
AL_ListSingle.h
/**
@(#)$Id: AL_ListSingle.h 44 2013-09-13 08:50:04Z xiaoting $
@brief Singly linked list (single list) is a list, which is characterized by the direction of the chain links are unidirectional,
Chain accessed through sequential reads starting from the head; linked list is constructed using pointers list; known the list of
nodes, as a linked list nodes is assembled; wherein each node has a pointer member variable refers to the next list node;
@Author $Author: xiaoting $
@Date $Date: 2013-09-13 16:50:04 +0800 (周五, 13 九月 2013) $
@Revision $Revision: 44 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_ListSingle.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_ListSingle.h 44 2013-09-13 08:50:04Z xiaoting $
*/
#ifndef CXX_AL_LISTSINGLE_H
#define CXX_AL_LISTSINGLE_H
#ifndef CXX_AL_NODE_H
#include "AL_Node.h"
#endif
///
// AL_ListSingle
///
template<typename T>
class AL_ListSingle
{
public:
static const DWORD LISTSINGLE_POSITION_INVALID = 0xffffffff;
/**
* Construction
*
* @param
* @return
* @note
* @attention
*/
AL_ListSingle();
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_ListSingle();
/**
* Length
*
* @param VOID
* @return DWORD
* @note get the length of the list
* @attention
*/
DWORD Length() const;
/**
* Find
*
* @param const T& tTemplate <IN>
* @return DWORD
* @note find the position of tTemplate
* @attention if not find, will be return 0xffffffff
*/
DWORD Find(const T& tTemplate) const;
/**
* IsElement
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note the tTemplate is in the list?
* @attention
*/
BOOL IsElement(const T& tTemplate) const;
/**
* Insert
*
* @param DWORD dwIndex <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
BOOL Insert(DWORD dwIndex,const T& tTemplate);
/**
* InsertBegin
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
BOOL InsertBegin(const T& tTemplate);
/**
* InsertEnd
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
BOOL InsertEnd(const T& tTemplate);
/**
* Remove
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note remove the tTemplate into the list
* @attention
*/
BOOL Remove(const T& tTemplate);
/**
* IsEmpty
*
* @param VOID
* @return BOOL
* @note the list has data?
* @attention
*/
BOOL IsEmpty() const;
/**
* Get
*
* @param T& tTypeOut <OUT>
* @param DWORD dwIndex <IN>
* @return BOOL
* @note get the const T& at the position
* @attention the dwIndex must is little than the list length
*/
BOOL Get(T& tTypeOut, DWORD dwIndex) const;
/**
* Set
*
* @param T& tTypeOut <OUT>
* @param DWORD dwIndex <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note Replaced with the element element element on position index, and returns the old element...
* @attention Index must in the list
*/
BOOL Set(T& tTypeOut, DWORD dwIndex, const T& tTemplate);
/**
* Clear
*
* @param VOID
* @return VOID
* @note clear the data in the list
* @attention all data will be clear
*/
VOID Clear();
protected:
private:
/**
* GetNodeByIndex
*
* @param DWORD dwIndex <IN>
* @return AL_Node<T>*
* @note get the const T& at the position
* @attention the dwIndex must is little than the list length
*/
AL_Node<T>* GetNodeByIndex(DWORD dwIndex) const;
public:
protected:
private:
AL_Node<T>* m_pHeader;
DWORD m_dwSize;
};
///
// AL_ListSingle
///
/**
* Construction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_ListSingle<T>::AL_ListSingle():
m_pHeader(NULL),
m_dwSize(0x00)
{
m_pHeader = new AL_Node<T>;
}
/**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_ListSingle<T>::~AL_ListSingle()
{
Clear();
//delete the header
if (NULL != m_pHeader) {
delete m_pHeader;
m_pHeader = NULL;
}
}
/**
* Length
*
* @param
* @return
* @note get the length of the list
* @attention
*/
template<typename T> DWORD
AL_ListSingle<T>::Length() const
{
return m_dwSize;
/*
if (TRUE == IsEmpty()) {
return 0;
}
AL_Node<T>* pMove = NULL;
DWORD dwCount = 1;
pMove = m_pHeader->m_pNext;
while (NULL != pMove->m_pNext) {
dwCount ++;
pMove = pMove->m_pNext;
}
return dwCount;
*/
}
/**
* Find
*
* @param const T& tTemplate <IN>
* @return DWORD
* @note find the position of tTemplate
* @attention if not find, will be return 0xffffffff
*/
template<typename T> DWORD
AL_ListSingle<T>::Find(const T& tTemplate) const
{
if (TRUE == IsEmpty()) {
return LISTSINGLE_POSITION_INVALID;
}
AL_Node<T>* pMove = NULL;
DWORD dwCount = 1;
//loop the next data;
pMove = m_pHeader->m_pNext;
while (NULL != pMove->m_pNext) {
if (tTemplate == pMove->m_data) {
//find the data
return dwCount-1;
}
dwCount ++;
pMove = pMove->m_pNext;
}
//the end
if (tTemplate == pMove->m_data) {
//find the data
return dwCount-1;
}
return LISTSINGLE_POSITION_INVALID;
}
/**
* IsElement
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note the tTemplate is in the list?
* @attention
*/
template<typename T> BOOL
AL_ListSingle<T>::IsElement(const T& tTemplate) const
{
if (LISTSINGLE_POSITION_INVALID == Find(tTemplate )) {
return FALSE;
}
return TRUE;
}
/**
* Insert
*
* @param DWORD dwIndex <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
template<typename T> BOOL
AL_ListSingle<T>::Insert(DWORD dwIndex, const T& tTemplate)
{
if (dwIndex > Length()) {
//can not insert to this position
return FALSE;
}
AL_Node<T>* pInsert = new AL_Node<T>;
pInsert->m_data = tTemplate;
AL_Node<T>* pPre = NULL;
//get the previous Node
if (0x00 == dwIndex) {
pPre = m_pHeader;
}
else {
pPre = GetNodeByIndex(dwIndex - 1);
}
if ((NULL == pPre)) {
//error
return FALSE;
}
if (Length() == dwIndex){
//end
pPre->m_pNext = pInsert;
}
else {
//among of the list
AL_Node<T>* pIndexNode = GetNodeByIndex(dwIndex);
if ((NULL == pIndexNode)) {
//error
return FALSE;
}
pInsert->m_pNext = pIndexNode;
pPre->m_pNext = pInsert;
}
m_dwSize++;
return TRUE;
/*
AL_Node<T>* pMove = NULL;
DWORD dwCount = 1;
//loop the next data;
pMove = m_pHeader->m_pNext;
while (NULL != pMove->m_pNext) {
if (dwCount-1 == dwIndex) {
//insert this place
pInsert->m_pNext = pMove->m_pNext
pMove->m_pNext = pInsert;
return TRUE;
}
dwCount++
pMove = pMove->m_pNext;
}
// the end
pMove->m_pNext = pInsert;
return TRUE;
*/
}
/**
* InsertBegin
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
template<typename T> BOOL
AL_ListSingle<T>::InsertBegin(const T& tTemplate)
{
return Insert(0, tTemplate);
}
/**
* InsertEnd
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
template<typename T> BOOL
AL_ListSingle<T>::InsertEnd(const T& tTemplate)
{
return Insert(Length(), tTemplate);
}
/**
* Remove
*
* @param const T& tTemplate <IN>
* @return BOOL
* @note remove the tTemplate into the list
* @attention
*/
template<typename T> BOOL
AL_ListSingle<T>::Remove(const T& tTemplate)
{
if (TRUE == IsEmpty()) {
return FALSE;
}
DWORD dwPosition = Find(tTemplate);
if (LISTSINGLE_POSITION_INVALID == dwPosition) {
//can not find the data
return FALSE;
}
AL_Node<T>* pDelete = GetNodeByIndex(dwPosition);
if (NULL == pDelete) {
//error
return FALSE;
}
AL_Node<T>* pPre = NULL;
//get the previous Node
if (0x00 == dwPosition) {
pPre = m_pHeader;
}
else {
pPre = GetNodeByIndex(dwPosition - 1);
}
if (NULL == pPre) {
//error
return FALSE;
}
pPre->m_pNext = pDelete->m_pNext;
delete pDelete;
pDelete = NULL;
m_dwSize--;
return TRUE;
/*
AL_Node<T>* pMove = NULL;
AL_Node<T>* pPreMove = NULL;
//loop the next data;
pMove = m_pHeader->m_pNext;
do {
if (tTemplate == pMove->m_data) {
//remove the data
pPreMove->m_pNext = pMove->m_pNext;
delete pMove;
pMove = NULL;
return TRUE;
}
pMove = pMove->m_pNext;
pPreMove = pMove;
} while (NULL != pMove->m_pNext);
return FALSE;
*/
}
/**
* IsEmpty
*
* @param
* @return BOOL
* @note the list has data?
* @attention
*/
template<typename T> BOOL
AL_ListSingle<T>::IsEmpty() const
{
return (NULL == m_pHeader->m_pNext) ? TRUE:FALSE;
}
/**
* Get
*
* @param T& tTypeOut <OUT>
* @param DWORD dwIndex <IN>
* @return BOOL
* @note get the T at the position
* @attention the dwIndex must is little than the list length
*/
template<typename T> BOOL
AL_ListSingle<T>::Get(T& tTypeOut, DWORD dwIndex) const
{
if (TRUE == IsEmpty()) {
//error
return FALSE;
}
if (Length()-1 < dwIndex) {
//error
return FALSE;
}
AL_Node<T>* pGet = GetNodeByIndex(dwIndex);
if (NULL == pGet) {
//error
return FALSE;
}
tTypeOut = pGet->m_data;
return TRUE;
/*
AL_Node<T>* pMove = NULL;
DWORD dwCount = 0;
//loop the next data;
pMove = m_pHeader->m_pNext;
do {
if (dwCount == dwIndex) {
//insert this place
return pMove->m_data;
}
dwCount++;
pMove = pMove->m_pNext;
} while (NULL != pMove->m_pNext);
//the end
tTypeOut = pMove->m_data;
return TRUE;
*/
}
/**
* Set
*
* @param T& tTypeOut <OUT>
* @param DWORD dwIndex <IN>
* @param const T& tTemplate <IN>
* @return BOOL
* @note Replaced with the element element element on position index, and returns the old element...
* @attention Index must in the list
*/
template<typename T> BOOL
AL_ListSingle<T>::Set(T& tTypeOut, DWORD dwIndex, const T& tTemplate)
{
if (Length()-1 < dwIndex) {
//error
return FALSE;
}
AL_Node<T>* pSet = GetNodeByIndex(dwIndex);
if (NULL == pSet) {
//error
return tTypeOut;
}
tTypeOut = pSet->m_data;
pSet->m_data = tTemplate;
return TRUE;
}
/**
* Clear
*
* @param VOID
* @return VOID
* @note clear the data in the list
* @attention all data will be clear
*/
template<typename T> VOID
AL_ListSingle<T>::Clear()
{
if (TRUE == IsEmpty()) {
//No data,
return;
}
AL_Node<T>* pDelete = NULL;
while(NULL != m_pHeader->m_pNext){
//get the node
pDelete = m_pHeader->m_pNext;
m_pHeader->m_pNext = pDelete->m_pNext;
delete pDelete;
pDelete = NULL;
}
m_dwSize = 0x00;
}
/**
* GetNodeByIndex
*
* @param DWORD dwIndex <IN>
* @return AL_Node<T>*
* @note get the const T& at the position
* @attention the dwIndex must is little than the list length
*/
template<typename T> AL_Node<T>*
AL_ListSingle<T>::GetNodeByIndex(DWORD dwIndex) const
{
if (Length()-1 < dwIndex) {
//error
return NULL;
}
AL_Node<T>* pMove = NULL;
DWORD dwCount = 1;
//loop the next data;
pMove = m_pHeader->m_pNext;
while (NULL != pMove->m_pNext) {
if (dwCount-1 == dwIndex) {
//get this place
return pMove;
}
dwCount ++;
pMove = pMove->m_pNext;
}
//the end
return pMove;
}
#endif // CXX_AL_LISTSINGLE_H
/* EOF */
測試代碼
#ifdef TEST_AL_LISTSINGLE
AL_ListSingle<DWORD> cListSingle;
BOOL bEmpty = cListSingle.IsEmpty();
std::cout<<bEmpty<<std::endl;
int array[15]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
for(int i=0;i<15;i++)
cListSingle.Insert(cListSingle.Length(), array[i]);
bEmpty = cListSingle.IsEmpty();
std::cout<<bEmpty<<std::endl;
//test the interface
DWORD dwListSeqLen = cListSingle.Length();
std::cout<<dwListSeqLen<<std::endl;
DWORD dwFind = cListSingle.Find(16);
std::cout<<dwFind<<std::endl;
dwFind = cListSingle.Find(12);
std::cout<<dwFind<<std::endl;
BOOL bElement = cListSingle.IsElement(16);
std::cout<<bElement<<std::endl;
bElement = cListSingle.IsElement(14);
std::cout<<bElement<<std::endl;
BOOL bInsert = cListSingle.Insert(0, 0);
std::cout<<bInsert<<std::endl;
bInsert = cListSingle.Insert(16, 16);
std::cout<<bInsert<<std::endl;
bInsert = cListSingle.Insert(16, 999);
std::cout<<bInsert<<std::endl;
BOOL bRemove = cListSingle.Remove(9846354);
std::cout<<bRemove<<std::endl;
bRemove = cListSingle.Remove(999);
std::cout<<bRemove<<std::endl;
bRemove = cListSingle.Remove(10);
std::cout<<bRemove<<std::endl;
DWORD it = 0x00;
for (DWORD i=0; i<cListSingle.Length(); i++) {
cListSingle.Get(it, i);
std::cout<<it<<std::endl;
}
DWORD dwSet = 0x00;
cListSingle.Set(dwSet, 16, 999);
std::cout<<dwSet<<std::endl;
cListSingle.Set(dwSet, 0, 888);
std::cout<<dwSet<<std::endl;
cListSingle.Set(dwSet, 11, 777);
std::cout<<dwSet<<std::endl;
for (DWORD i=0; i<cListSingle.Length(); i++) {
cListSingle.Get(it, i);
std::cout<<it<<std::endl;
}
cListSingle.Clear();
bEmpty = cListSingle.IsEmpty();
std::cout<<bEmpty<<std::endl;
dwListSeqLen = cListSingle.Length();
std::cout<<dwListSeqLen<<std::endl;
bInsert = cListSingle.Insert(1, 999);
std::cout<<bInsert<<std::endl;
bInsert = cListSingle.Insert(0, 666);
std::cout<<bInsert<<std::endl;
bRemove = cListSingle.Remove(666);
std::cout<<bRemove<<std::endl;
bEmpty = cListSingle.IsEmpty();
std::cout<<bEmpty<<std::endl;
dwListSeqLen = cListSingle.Length();
std::cout<<dwListSeqLen<<std::endl;
#endif