双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以后的笔记潇汀会尽量详细讲解一些相关知识的,希望大家继续关注我的博客。
本节笔记到这里就结束了。

潇汀一有时间就会把自己的学习心得,觉得比较好的知识点写出来和大家一起分享。
编程开发的路很长很长,非常希望能和大家一起交流,共同学习,共同进步。
如果文章中有什么疏漏的地方,也请大家指正。也希望大家可以多留言来和我探讨编程相关的问题。
最后,谢谢你们一直的支持~~~

C++完整个代码示例(代码在VS2005下测试可运行)

AL_ListDouble.h

/**
@(#)$Id: AL_ListDouble.h 26 2013-09-02 06:38:34Z xiaoting $
@brief Also called double-linked list doubly linked list is a list in which each data node in both two pointers that point to a
direct successor and direct precursors. Therefore, two-way linked list from any one of the node point, can easily access its
predecessor and successor nodes node. @Author $Author: xiaoting $
@Date $Date: 2013-09-02 14:38:34 +0800 (周一, 02 九月 2013) $
@Revision $Revision: 26 $
@URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_ListDouble.h $
@Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_ListDouble.h 26 2013-09-02 06:38:34Z xiaoting $
*/ #ifndef CXX_AL_LISTDOUBLE_H
#define CXX_AL_LISTDOUBLE_H #ifndef CXX_AL_NODE_H
#include "AL_Node.h"
#endif ///////////////////////////////////////////////////////////////////////////
// AL_ListDouble
/////////////////////////////////////////////////////////////////////////// template<typename T>
class AL_ListDouble
{
public:
static const DWORD LISTDOUBLE_POSITION_INVALID = 0xffffffff;
/**
* Construction
*
* @param
* @return
* @note
* @attention
*/
AL_ListDouble(); /**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
~AL_ListDouble(); /**
* Length
*
* @param VOID
* @return DWORD
* @note get the length of the list
* @attention
*/
DWORD Length() const; /**
* Find
*
* @param const T& tTemplate
* @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
* @return BOOL
* @note the tTemplate is in the list?
* @attention
*/
BOOL IsElement(const T& tTemplate ) const; /**
* Insert
*
* @param DWORD dwIndex
* @param const T& tTemplate
* @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
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
BOOL InsertBegin(const T& tTemplate ); /**
* InsertEnd
*
* @param const T& tTemplate
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
BOOL InsertEnd(const T& tTemplate ); /**
* Remove
*
* @param const T& tTemplate
* @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
* @return BOOL
* @note get the const T& at the position
* @attention the dwIndex must is little than the list length
*/
T Get(DWORD dwIndex) const; /**
* Set
*
* @param DWORD dwIndex
* @param const T& tTemplate
* @return BOOL
* @note Replaced with the element element element on position index, and returns the old element...
* @attention Index must in the list
*/
T Set(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
* @return BOOL
* @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;
}; ///////////////////////////////////////////////////////////////////////////
// AL_ListDouble
///////////////////////////////////////////////////////////////////////////
/**
* Construction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_ListDouble<T>::AL_ListDouble():
m_pHeader(NULL)
{
m_pHeader = new AL_Node<T>;
} /**
* Destruction
*
* @param
* @return
* @note
* @attention
*/
template<typename T>
AL_ListDouble<T>::~AL_ListDouble()
{
Clear();
//delete the header
delete m_pHeader;
m_pHeader = NULL;
} /**
* Length
*
* @param
* @return
* @note get the length of the list
* @attention
*/
template<typename T> DWORD
AL_ListDouble<T>::Length() const
{
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
* @return DWORD
* @note find the position of tTemplate
* @attention if not find, will be return 0xffffffff
*/
template<typename T> DWORD
AL_ListDouble<T>::Find(const T& tTemplate ) const
{
if (TRUE == IsEmpty()) {
return LISTDOUBLE_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 LISTDOUBLE_POSITION_INVALID;
} /**
* IsElement
*
* @param const T& tTemplate
* @return BOOL
* @note the tTemplate is in the list?
* @attention
*/
template<typename T> BOOL
AL_ListDouble<T>::IsElement(const T& tTemplate ) const
{
if (LISTDOUBLE_POSITION_INVALID == Find(tTemplate )) {
return FALSE;
} return TRUE;
} /**
* Insert
*
* @param const T& tTemplate
* @param DWORD dwIndex
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
template<typename T> BOOL
AL_ListDouble<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;
pInsert->m_pPre = pPre;
}
else {
//among of the list
AL_Node<T>* pIndexNode = pPre->m_pNext;
if ((NULL == pIndexNode)) {
//error
return FALSE;
}
pInsert->m_pNext = pIndexNode;
pIndexNode->m_pPre = pInsert; pPre->m_pNext = pInsert;
pInsert->m_pPre = pPre;
}
return TRUE;
} /**
* InsertBegin
*
* @param const T& tTemplate
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
template<typename T> BOOL
AL_ListDouble<T>::InsertBegin(const T& tTemplate )
{
return Insert(0, tTemplate);
} /**
* InsertEnd
*
* @param const T& tTemplate
* @return BOOL
* @note inset the tTemplate into the list at the position
* @attention
*/
template<typename T> BOOL
AL_ListDouble<T>::InsertEnd(const T& tTemplate )
{
return Insert(Length(), tTemplate);
} /**
* Remove
*
* @param const T& tTemplate
* @return BOOL
* @note remove the tTemplate into the list
* @attention
*/
template<typename T> BOOL
AL_ListDouble<T>::Remove(const T& tTemplate )
{
if (TRUE == IsEmpty()) {
return FALSE;
} DWORD dwPosition = Find(tTemplate);
if (LISTDOUBLE_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 = pDelete->m_pPre;
} if (NULL == pPre) {
//error
return FALSE;
}
pPre->m_pNext = pDelete->m_pNext; AL_Node<T>* pNext = pDelete->m_pNext;
if (NULL != pNext) {
//among of the list
pNext->m_pPre = pPre;
} delete pDelete;
pDelete = NULL;
return TRUE;
} /**
* IsEmpty
*
* @param
* @return BOOL
* @note the list has data?
* @attention
*/
template<typename T> BOOL
AL_ListDouble<T>::IsEmpty() const
{
return (NULL == m_pHeader->m_pNext) ? TRUE:FALSE;
} /**
* Get
*
* @param
* @return T
* @note get the T at the position
* @attention the dwIndex must is little than the list length
*/
template<typename T> T
AL_ListDouble<T>::Get(DWORD dwIndex) const
{
T tTypeTemp;
memset(&tTypeTemp, 0x00, sizeof(T)); if (TRUE == IsEmpty()) {
//error
return tTypeTemp;
} if (Length()-1 < dwIndex) {
//error
return tTypeTemp;
} AL_Node<T>* pGet = GetNodeByIndex(dwIndex);
if (NULL == pGet) {
//error
return tTypeTemp;
}
return pGet->m_data;
} /**
* Set
*
* @param DWORD dwIndex
* @param const T& tTemplate
* @return T
* @note Replaced with the element element element on position index, and returns the old element...
* @attention Index must in the list
*/
template<typename T> T
AL_ListDouble<T>::Set(DWORD dwIndex, const T& tTemplate )
{
T tTypeTemp;
memset(&tTypeTemp, 0x00, sizeof(T)); if (Length()-1 < dwIndex) {
//error
return tTypeTemp;
} AL_Node<T>* pSet = GetNodeByIndex(dwIndex);
if (NULL == pSet) {
//error
return tTypeTemp;
} tTypeTemp = pSet->m_data;
pSet->m_data = tTemplate;
return tTypeTemp;
} /**
* Clear
*
* @param VOID
* @return VOID
* @note clear the data in the list
* @attention all data will be clear
*/
template<typename T> VOID
AL_ListDouble<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;
}
} /**
* GetNodeByIndex
*
* @param
* @return BOOL
* @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_ListDouble<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; /*
//forward loop (only for test)
//get the end node
AL_Node<T>* pEnd = NULL;
AL_Node<T>* pMove = NULL;
//loop the next data;
pMove = m_pHeader->m_pNext;
while (NULL != pMove->m_pNext) {
pMove = pMove->m_pNext;
}
pEnd = pMove;
pMove = NULL; DWORD dwCount = Length();
//loop the next data;
pMove = pEnd;
while (m_pHeader != pMove->m_pPre) {
if (dwCount-1 == dwIndex) {
//get this place
return pMove;
}
dwCount --;
pMove = pMove->m_pPre;
} //the end
return pMove;
*/
} #endif // CXX_AL_LISTDOUBLE_H
/* EOF */

测试代码

#ifdef TEST_AL_LISTDOUBLE
AL_ListDouble<DWORD> cListDouble;
BOOL bEmpty = cListDouble.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++)
cListDouble.Insert(cListDouble.Length(), array[i]);
bEmpty = cListDouble.IsEmpty();
std::cout<<bEmpty<<std::endl; //test the interface
DWORD dwListSeqLen = cListDouble.Length();
std::cout<<dwListSeqLen<<std::endl; DWORD dwFind = cListDouble.Find(16);
std::cout<<dwFind<<std::endl;
dwFind = cListDouble.Find(12);
std::cout<<dwFind<<std::endl; BOOL bElement = cListDouble.IsElement(16);
std::cout<<bElement<<std::endl;
bElement = cListDouble.IsElement(14);
std::cout<<bElement<<std::endl; BOOL bInsert = cListDouble.Insert(0, 0);
std::cout<<bInsert<<std::endl;
bInsert = cListDouble.Insert(16, 16);
std::cout<<bInsert<<std::endl;
bInsert = cListDouble.Insert(16, 999);
std::cout<<bInsert<<std::endl; BOOL bRemove = cListDouble.Remove(9846354);
std::cout<<bRemove<<std::endl;
bRemove = cListDouble.Remove(999);
std::cout<<bRemove<<std::endl; bRemove = cListDouble.Remove(10);
std::cout<<bRemove<<std::endl; INT it = 0x00;
for (DWORD i=0; i<cListDouble.Length(); i++) {
it = cListDouble.Get(i);
std::cout<<it<<std::endl;
} DWORD dwSet = cListDouble.Set(16, 999);
std::cout<<dwSet<<std::endl;
dwSet = cListDouble.Set(0, 888);
std::cout<<dwSet<<std::endl;
dwSet = cListDouble.Set(11, 777);
std::cout<<dwSet<<std::endl; for (DWORD i=0; i<cListDouble.Length(); i++) {
it = cListDouble.Get(i);
std::cout<<it<<std::endl;
} cListDouble.Clear();
bEmpty = cListDouble.IsEmpty();
std::cout<<bEmpty<<std::endl;
dwListSeqLen = cListDouble.Length();
std::cout<<dwListSeqLen<<std::endl; bInsert = cListDouble.Insert(1, 999);
std::cout<<bInsert<<std::endl; bInsert = cListDouble.Insert(0, 666);
std::cout<<bInsert<<std::endl;
bRemove = cListDouble.Remove(666);
std::cout<<bRemove<<std::endl;
bEmpty = cListDouble.IsEmpty();
std::cout<<bEmpty<<std::endl;
dwListSeqLen = cListDouble.Length();
std::cout<<dwListSeqLen<<std::endl;
#endif

[置顶] ※数据结构※→☆线性表结构(list)☆============双向链表结构(list double)(三)的更多相关文章

  1. [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)

    优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...

  2. [置顶] ※数据结构※→☆线性表结构(stack)☆============栈 序列表结构(stack sequence)(六)

    栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线性表.栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据.栈 ...

  3. [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)

    循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...

  4. [置顶] ※数据结构※→☆线性表结构(queue)☆============队列 顺序存储结构(queue sequence)(八)

    队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的 ...

  5. [置顶] ※数据结构※→☆线性表结构(list)☆============单向链表结构(list single)(二)

    单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始:链表是使用指针进行构造的列表:又称为结点列表,因为链表是由一个个结点组装起来的:其中每个结点都有指 ...

  6. 数据结构线性表的动态分配顺序存储结构算法c语言具体实现和算法时间复杂度分析

    #include<stdio.h>#include<stdlib.h>//线性表的动态分配顺序存储结构#define LIST_INIT_SIZE 100//线性表存储空间的初 ...

  7. [数据结构-线性表1.2] 链表与 LinkedList<T>(.NET 源码学习)

    [数据结构-线性表1.2] 链表与 LinkedList<T> [注:本篇文章源码内容较少,分析度较浅,请酌情选择阅读] 关键词:链表(数据结构)    C#中的链表(源码)    可空类 ...

  8. C语言 线性表 双向链式结构 实现

    一个双向链式结构实现的线性表 duList (GCC编译). /** * @brief 线性表双向链表结构 * @author wid * @date 2013-10-28 * * @note 若代码 ...

  9. [从今天开始修炼数据结构]线性表及其实现以及实现有Itertor的ArrayList和LinkedList

    一.线性表 1,什么是线性表 线性表就是零个或多个数据元素的有限序列.线性表中的每个元素只能有零个或一个前驱元素,零个或一个后继元素.在较复杂的线性表中,一个数据元素可以由若干个数据项组成.比如牵手排 ...

随机推荐

  1. PB+MS SQL+触发器必须指出

    PB+MS SQL+触发器必须指出: 若触发器存在两笔以上的返回值,比方两条update 语句,被误判为数据有改变.存盘不成功. 提示: Row changed between retrieve an ...

  2. Linux - Linux系统目录架构

    Linux系统目录架构   Bin: 保存的是二进制可执行文件,也就是我们所敲的那些命令. Boot: 引导目录,整个操作系统的引导启动都是在boot目录下面.最主要的文件是vmLinuz-……,内核 ...

  3. 2007LA 3902 网络(树+贪心)

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=283&am ...

  4. Oracle Autonomous Transactions(自治事务)

    Oracle Autonomous Transactions Autonomous transactions allow you to leave the context of the calling ...

  5. 实用Shell命令备忘

    开场白:这里简单记录一些常用的bash命令,一则备忘,二来希望可以帮助别人解决一些问题. 1.检测文件是否存在 if [ -f ./foo.txt ] then echo the file exist ...

  6. mysql READ-COMMITTED 模式下 行锁不会升级到表级锁

    mysql> select sn,id,info from s100 group by id; +-----+------+------+ | sn | id | info | +-----+- ...

  7. VirtualBox集群建立和网络配置

    安装 1. 安装 安装Oracle VM VirtualBox之后,新建一个虚拟机,制定好内存等信息,开始安装操作系统,这里安装ubuntu-12.04.2-desktop-i386版本. 2. 拷贝 ...

  8. [C#基础] 继承

    虚方法和覆写方法 虚方法可以使基类的引用访问"升至"派生类中 可以使用基类引用调用派生类的方法,只需满足下面的条件 派生类的方法和基类的方法有相同的签名和返回类型 基类的方法使用v ...

  9. Delphi调用C++导出的QT类

    打开VS2008创建一个dll项目(创建了一个QT Library项目),新建头文件q4dapplication.h定义纯虚类: #ifndef Q4DAPPLICATION#define Q4DAP ...

  10. js中获取jsp中的参数

    碰到一个问题需要再js中根据jsp中request的参数判断执行那段代码 第一种写法: if('${method}'=="add"){js代码段1}else{js代码段2} 第二种 ...