数据结构之线性结构--双向链表
2016-10-02 21:39
218 查看
一、双向链表
在单链表中若需要查找某一个元素时,都必须从第一个元素开始进行查找,而双向链表除开头节点和最后一个节点外每个节点中储存有两个指针,这连个指针分别指向前一个节点的地址和后一个节点的地址,这样无论通过那个节点都能够寻找到其他的节点。二、双向链表的基本操作
双链表的删除除元素的时候需要注意的是,他有一个指向前驱指针和一个指向下一个节点的指针,当元素被删除时,上一个节点的指针会指向被删除节点的下一个节点,而被删除的节点的下一节点的指针会指向被删除节点的上一个节点.双链表的插入操作需要将前一个节点指针指向插入节点,然后插入节点的两个指针分别指向前后两个节点,后一个节点的指针指向插入节点。
双向链表的C++代码实现:
AL_Node.h文件
template<typename T> class AL_ListDouble; template<typename T> class AL_Node { //声明一个朋友类,使这个朋友类可以访问这个类的私有元素 friend class AL_ListDouble<T>; public : ~AL_Node(); private : AL_Node(); AL_Node(const T &tTemplate); AL_Node(const AL_Node<T>& cAL_Node); T m_data;//存储数据 AL_Node *m_pPre;//记录链表的头结点地址 AL_Node *m_pNext; //指向下一个节点地址 }; template<typename T> AL_Node<T>::AL_Node():m_pPre(NULL),m_pNext(NULL) { } template<typename T> AL_Node<T>::AL_Node(const T &tTemplate):m_pPre(NULL),m_pNext(NULL),m_data(tTemplate) { } template<typename T> AL_Node<T>::~AL_Node() { m_pPre=NULL; m_pNext=NULL; } #endif // AL_NODE
AL_ListDouble.h文件
#ifndef AL_LISTDOUBLE_INCLUDE #define AL_LISTDOUBLE_INCLUDE #include <windows.h> #include "AL_Node.h" template<typename T> class AL_ListDouble { public: static const DWORD LISTDOUBLE_POSITION_INVALID = 0xffffffff; AL_ListDouble(); ~AL_ListDouble(); DWORD Length() const; DWORD Find(const T &tTemplate)const; bool IsElement(const T & tTemplate)const; bool Insert(DWORD dwIndex, const T & tTemplate); bool InsertBegin(const T &tTemplate); bool InsertEnd(const T &tTemplate); bool Remove(const T &tTemplate); bool IsEmpty()const; bool Get(T & tTypeOut, DWORD dwIndex)const; bool Set(const DWORD &tTemplate, DWORD dwIndex, T &tTypeOut); void Clear(); private: AL_Node<T> * GetNodeByIndex(DWORD dwIndex) const; AL_Node<T> * m_Header; DWORD m_dwSize; }; template<typename T> inline AL_ListDouble<T>::AL_ListDouble():m_Header(NULL),m_dwSize(0x00) { //创建指向头结点的指针 m_Header = new AL_Node<T>(); } template<typename T> inline AL_ListDouble<T>::~AL_ListDouble() { Clear(); if (m_Header!=NULL) { delete m_Header; m_Header = NULL; } } template<typename T> inline DWORD AL_ListDouble<T>::Length() const { return m_dwSize; } template<typename T> inline DWORD AL_ListDouble<T>::Find(const T & tTemplate) const { if (IsEmpty()==true) { return LISTDOUBLE_POSITION_INVALID; } AL_Node<T> * pMove = NULL; DWORD dwCount = 1; pMove = m_Header->m_pNext; while (pMove->m_pNext!=NULL) { if (pMove->m_data==tTemplate) { return dwCount-1; } dwCount++; pMove = pMove->m_pNext; } if (pMove->m_data==tTemplate) { return dwCount - 1; } return LISTDOUBLE_POSITION_INVALID; } template<typename T> inline bool AL_ListDouble<T>::IsElement(const T & tTemplate) const { if (Find(tTemplate) == LISTDOUBLE_POSITION_INVALID) { return false; } return true; } template<typename T> inline bool AL_ListDouble<T>::Insert(DWORD dwIndex, const T & tTemplate) { if (dwIndex>Length()) { return false; } AL_Node<T>* pInsert = new AL_Node<T>; pInsert->m_data = tTemplate; AL_Node<T> * pPer = NULL; if (dwIndex==0x00) { pPer = m_Header; } else { pPer = GetNodeByIndex(dwIndex - 1); } if (pPer==NULL) { return false; } if (dwIndex == Length()) { //将节点指向插入的节点 pPer->m_pNext = pInsert; //将插入节点的指针指向他的前驱节点 pInsert->m_pPre = pPer; } else { AL_Node<T>* pIndexNode = pPer->m_pNext; if (pIndexNode==NULL) { return false; } pPer->m_pNext = pInsert; pInsert->m_pPre = pPer; pInsert->m_pNext = pIndexNode; pIndexNode->m_pPre = pInsert; } m_dwSize++; return true; } template<typename T> inline bool AL_ListDouble<T>::InsertBegin(const T & tTemplate) { return Insert(0x00,tTemplate); } template<typename T> inline bool AL_ListDouble<T>::InsertEnd(const T & tTemplate) { return Insert(Length(),tTemplate); } template<typename T> inline bool AL_ListDouble<T>::Remove(const T & tTemplate) { if (IsEmpty()==true) { return false; } DWORD dwPosition = Find(tTemplate); if (dwPosition == LISTDOUBLE_POSITION_INVALID) { return false; } AL_Node<T> * p_Deltet =GetNodeByIndex(dwPosition); if (p_Deltet==NULL) { return false; } AL_Node<T> * pPer = NULL; if (dwPosition==0x00) { pPer = m_Header; } else { //指向要删除的节点的前驱节点 pPer = p_Deltet->m_pPre; } if (pPer==NULL) { return false; } pPer->m_pNext = p_Deltet->m_pNext; //获取要删除节点的后一个节点 AL_Node<T>*p_Next = p_Deltet->m_pNext; //设置它的前驱节点 if (p_Next!=NULL) { p_Next->m_pPre = pPer; } delete p_Deltet; p_Deltet = NULL; m_dwSize--; return true; } template<typename T> inline bool AL_ListDouble<T>::IsEmpty() const { return (m_Header->m_pNext == NULL) ? true : false; } template<typename T> inline bool AL_ListDouble<T>::Get(T & tTypeOut, DWORD dwIndex) const { if (IsEmpty()==true) { return false; } if (Length()-1<dwIndex) { return false; } AL_Node<T> *pGet = GetNodeByIndex(dwIndex); if (pGet==NULL) { return false; } tTypeOut = pGet->m_data; return true; } template<typename T> inline bool AL_ListDouble<T>::Set(const DWORD & tTemplate, DWORD dwIndex, T & tTypeOut) { if (Length()-1<dwIndex) { return false; } AL_Node<T>*pSet = GetNodeByIndex(dwIndex); if (pSet==NULL) { return false; } tTypeOut = pSet->m_data; pSet->m_data = tTemplate; return true; } template<typename T> inline void AL_ListDouble<T>::Clear() { if (IsEmpty()==true) { return; } AL_Node<T>*pDelete = NULL; while (m_Header->m_pNext != NULL) { pDelete = m_Header->m_pNext; m_Header->m_pNext = pDelete->m_pNext; delete pDelete; pDelete = NULL; } m_dwSize = 0x00; } template<typename T> inline AL_Node<T>* AL_ListDouble<T>::GetNodeByIndex(DWORD dwIndex) const { if (Length()-1<dwIndex) { return NULL; } AL_Node<T>*pMove = NULL; DWORD dwCount = 1; pMove = m_Header->m_pNext; while (pMove->m_pNext!=NULL) { if (dwIndex==dwCount-1) { return pMove; } dwCount++; pMove = pMove->m_pNext; } return pMove; } #endif
测试代码:
void DoubleTest() { //创建一个双链表 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(); DWORD cLength = cListDouble.Length(); std::cout << bEmpty << " " << cLength << std::endl; //寻找元素的位置 DWORD dwFind = cListDouble.Find(11); std::cout << dwFind << std::endl; //判断元素是否存在 bool dwemdw = cListDouble.IsElement(47); bool dwendw2 = cListDouble.IsElement(14); std::cout << dwemdw << " " << dwendw2 << std::endl; //测试删除元素 dwemdw = cListDouble.Remove(456); dwendw2 = cListDouble.Remove(13); cLength = cListDouble.Length(); std::cout << dwemdw << " " << dwendw2 << " " << cLength << std::endl; //获取元素修改元素 DWORD SU,w; bool byGet = cListDouble.Get(SU, cListDouble.Length()-1); bool bySet = cListDouble.Set(25, cListDouble.Length()-1,w); std::cout << byGet << " " << SU << std::endl; std::cout << bySet << " " << w << std::endl; byGet = cListDouble.Get(SU, cListDouble.Length() - 1); std::cout << byGet<<" "<<SU << std::endl; } int main(int argc, char *argv[]) { DoubleTest(); getchar(); return 0; }
运行结果:
相关文章推荐
- 数据结构之线性结构--数组
- PAT 数据结构 02-线性结构4. Pop Sequence (25)
- js 把线性的数据结构改成树形结构
- (C语言)栈的线性结构实现(数据结构八)
- java数据结构--线性结构
- 线性结构————数据结构
- 数据结构 02-线性结构1 两个有序链表序列的合并
- 08-数据结构_线性结构-离散存储-链表_1
- 【郝斌数据结构自学笔记】57-59_递归8 _ 汉诺塔_1线性结构总复习 2线性结构和非线性结构关系 3栈队列链表数组之间的关系【重点】
- 数据结构 线性结构中的链表
- 数据结构 PAT 02-线性结构1 一元多项式的乘法与加法运算
- PAT 数据结构 02-线性结构3. 求前缀表达式的值(25)
- 我的数据结构思考--理解线性结构
- 数据结构(1) -- 线性结构
- 陈越《数据结构》第二章 线性结构
- 离散数据结构,线性数据结构
- (C语言)栈的线性结构实现(数据结构八)
- java数据结构--线性结构
- 进击的数据结构一之线性表的顺序结构
- 【数据结构】线性表的单链表存储结构表示和实现