zoukankan      html  css  js  c++  java
  • 双链表

    【1】双链表

    双链表即双向链表,双链表的节点结构定义如下:

    1 typedef int Elemtype;
    2  
    3 // 双链表节点结构定义
    4 typedef struct dNode 
    5 {
    6     Elemtype data; /*数据域*/
    7     struct dNode *prev;  /*指向前驱节点的指针域*/
    8     struct dNode *next;  /*指向后继节点的指针域*/
    9 }*pDLinkNode, *DLinkList;

    双链表节点结构如下图示:

     

    双链表节点比单链表多一个前驱指针域。

    【2】C语言版双链表

    1、无环双链表。实现部分代码如下:

      1 // C语言实现无环双链表
      2 #include <stdio.h>
      3 #include <memory.h>
      4 #include <assert.h>
      5 #include <stdlib.h>
      6 
      7 // 循环双链表的节点结构
      8 typedef struct DOUBLE_LINK_NODE
      9 {  
     10     int data;  // 数据域
     11     struct DOUBLE_LINK_NODE* prev;  // 前向指针域  
     12     struct DOUBLE_LINK_NODE* next;  // 后向指针域
     13 } DLINK_NODE;
     14 
     15 // 创建双链表的节点
     16 DLINK_NODE* create_link_node(int value)
     17 {  
     18     DLINK_NODE* pDLinkNode = NULL;
     19     pDLinkNode = (DLINK_NODE*)malloc(sizeof(DLINK_NODE));
     20     assert(NULL != pDLinkNode);
     21     memset(pDLinkNode, 0, sizeof(DLINK_NODE));
     22     pDLinkNode->data = value;
     23     return pDLinkNode;
     24 }  
     25 
     26 // 递归删除双链表的所有节点(包括头节点)
     27 void delete_all_link_node(DLINK_NODE** pDLinkNode)  
     28 {  
     29     DLINK_NODE* pNode = NULL;  
     30     if (NULL == *pDLinkNode)  
     31         return;  
     32   
     33     pNode = *pDLinkNode;  
     34     *pDLinkNode = pNode->next;
     35     free(pNode);
     36 
     37     delete_all_link_node(pDLinkNode);  
     38 }  
     39 
     40 // 在双链表中查询数据
     41 DLINK_NODE* find_data_in_link(const DLINK_NODE* pDLinkNode, int data)  
     42 {  
     43     DLINK_NODE* pNode = NULL;  
     44     if (NULL == pDLinkNode)  
     45         return NULL;  
     46   
     47     pNode = (DLINK_NODE*)pDLinkNode;
     48     while (NULL != pNode)
     49     {  
     50         if (data == pNode->data)  
     51             return pNode;
     52 
     53         pNode = pNode ->next;  
     54     }  
     55       
     56     return NULL;
     57 }  
     58 
     59 // 向双链表中添加数据
     60 bool add_data_into_link(DLINK_NODE** ppDLinkNode, int data)  
     61 {  
     62     DLINK_NODE* pNode = NULL;
     63     DLINK_NODE* pIndex = NULL;  
     64   
     65     if (NULL == ppDLinkNode)  
     66         return false;  
     67   
     68     if (NULL == *ppDLinkNode)
     69     {
     70         pNode = create_link_node(data);  
     71         assert(NULL != pNode);  
     72         *ppDLinkNode = pNode;  
     73         (*ppDLinkNode)->prev = (*ppDLinkNode)->next = NULL;  
     74         return true;  
     75     }  
     76   
     77     if (NULL != find_data_in_link(*ppDLinkNode, data))  
     78         return false;  
     79   
     80     pNode = create_link_node(data);  
     81     assert(NULL != pNode);
     82 
     83     pIndex = *ppDLinkNode;  
     84     while (NULL != pIndex->next)  
     85         pIndex = pIndex->next;
     86 
     87     pNode->prev = pIndex;
     88     pNode->next = pIndex->next;
     89     pIndex->next = pNode;  
     90     return true;  
     91 }  
     92 
     93 // 从双链表中删除数据
     94 bool delete_data_from_link(DLINK_NODE** ppDLinkNode, int data)  
     95 {  
     96     DLINK_NODE* pNode = NULL;
     97     if (NULL == ppDLinkNode || NULL == *ppDLinkNode)
     98         return false;
     99   
    100     pNode = find_data_in_link(*ppDLinkNode, data); 
    101     if (NULL == pNode)
    102         return false;
    103   
    104     if (pNode == *ppDLinkNode)
    105     {
    106         if (NULL == (*ppDLinkNode)->next)
    107         {  
    108             *ppDLinkNode = NULL;
    109         }
    110         else
    111         {  
    112             *ppDLinkNode = pNode->next;
    113             (*ppDLinkNode)->prev = NULL;
    114         }
    115     }
    116     else
    117     {
    118         if (pNode->next != NULL)
    119         {
    120             pNode->next->prev = pNode->prev;
    121         }
    122         pNode->prev->next = pNode->next;
    123     }  
    124   
    125     free(pNode);
    126     return true;
    127 }  
    128 
    129 // 统计链表中数据个数
    130 int count_number_in_link(const DLINK_NODE* pDLinkNode)  
    131 {  
    132     int count = 0;  
    133     DLINK_NODE* pNode = (DLINK_NODE*)pDLinkNode;  
    134   
    135     while (NULL != pNode)
    136     {  
    137         if (pNode->data != -1)  // 头节点除外
    138         {
    139             ++count;  
    140         }
    141         pNode = pNode->next;
    142     }
    143 
    144     return count;
    145 }  
    146 
    147 // 打印双链表中数据
    148 void print_link_node(const DLINK_NODE* pDLinkNode)  
    149 {  
    150     printf("打印元素:
    ");
    151     DLINK_NODE* pNode = (DLINK_NODE*)pDLinkNode;  
    152   
    153     while (NULL != pNode)
    154     {
    155         if (pNode->data != -1)
    156         {
    157             printf("%d ", pNode->data);
    158         }
    159         pNode = pNode ->next;
    160     }  
    161 
    162     printf("
    ");
    163 }  
    164 
    165 void main()
    166 {
    167     printf("测试无环有头双链表效果:
    ");
    168     DLINK_NODE* pHeadNode = NULL;
    169     add_data_into_link(&pHeadNode, -1);  // 头节点
    170     int nItems[10] = {12, 23, 34, 45, 56, 67, 78, 89, 99, 100};
    171     for (int i = 0; i < 10; ++i)
    172     {
    173         if (!add_data_into_link(&pHeadNode, nItems[i]))
    174         {
    175             break;
    176         }
    177     }
    178 
    179     int nCount = count_number_in_link(pHeadNode);
    180     printf("无环有头双链表元素个数:%d 
    ", nCount);
    181 
    182     print_link_node(pHeadNode);
    183 
    184     delete_data_from_link(&pHeadNode, 56);
    185     printf("删除56后
    ");
    186     print_link_node(pHeadNode);
    187 
    188     delete_all_link_node(&pHeadNode);
    189     printf("删除所有节点后");
    190     print_link_node(pHeadNode);
    191 
    192     printf("测试无环无头双链表效果:
    ");
    193     DLINK_NODE* pNode = NULL;
    194     int nItems2[10] = {11, 22, 33, 44, 55, 66, 77, 88, 99, 100};
    195     for (int i = 0; i < 10; ++i)
    196     {
    197         if (!add_data_into_link(&pNode, nItems2[i]))
    198         {
    199             break;
    200         }
    201     }
    202 
    203     int nNoHeadCount = count_number_in_link(pNode);
    204     printf("无环无头双链表元素个数:%d 
    ", nNoHeadCount);
    205 
    206     print_link_node(pNode);
    207 
    208     delete_data_from_link(&pNode, 55);
    209     printf("删除55后
    ");
    210     print_link_node(pNode);
    211 
    212     delete_data_from_link(&pNode, 11);
    213     printf("删除11后
    ");
    214     print_link_node(pNode);
    215 
    216     delete_data_from_link(&pNode, 100);
    217     printf("删除100后
    ");
    218     print_link_node(pNode);
    219 
    220     delete_all_link_node(&pNode);
    221     printf("删除所有节点后");
    222     print_link_node(pNode);
    223 
    224     system("pause");
    225 }
    226 
    227 // run out
    228 /*
    229 测试无环有头双链表效果:
    230 无环有头双链表元素个数:10
    231 打印元素:
    232 12 23 34 45 56 67 78 89 99 100
    233 删除56后
    234 打印元素:
    235 12 23 34 45 67 78 89 99 100
    236 删除所有节点后打印元素:
    237 
    238 测试无环无头双链表效果:
    239 无环无头双链表元素个数:10
    240 打印元素:
    241 11 22 33 44 55 66 77 88 99 100
    242 删除55后
    243 打印元素:
    244 11 22 33 44 66 77 88 99 100
    245 删除11后
    246 打印元素:
    247 22 33 44 66 77 88 99 100
    248 删除100后
    249 打印元素:
    250 22 33 44 66 77 88 99
    251 删除所有节点后打印元素:
    252 
    253 请按任意键继续. . .
    254 */

    2、循环双链表。实现部分代码如下:

      1 // C语言实现循环双链表
      2 #include <stdio.h>
      3 #include <malloc.h>
      4 #include <stdlib.h>
      5 #include <assert.h>
      6 
      7 typedef int Elemtype;
      8  
      9 // 双链表节点结构定义
     10 typedef struct dNode 
     11 {
     12     Elemtype data; /*数据域*/
     13     struct dNode *prev;  /*指向前驱节点的指针域*/
     14     struct dNode *next;  /*指向后继节点的指针域*/
     15 }*pDLinkNode, *DLinkList;
     16  
     17 // 有头节点的空循环双链表
     18 DLinkList GetEmptyDLink() 
     19 {
     20     DLinkList head = (pDLinkNode)malloc(sizeof(struct dNode));
     21     head->data = 0;
     22     head->prev = head;
     23     head->next = head;
     24     return head;
     25 }
     26 
     27 // 由用户输入数据建立循环双链表
     28 void DLink_create(DLinkList head, int n) 
     29 {
     30     pDLinkNode p = head, r = head;
     31     for (int i = 0; i < n; ++i) 
     32     {
     33         p->next = (pDLinkNode)malloc(sizeof(dNode));/*为一个新节点分配空间*/
     34         scanf("%d", &p->next->data); /*从键盘输入值,并保存在新节点数据域中*/
     35         p = p->next; // p指向新节点
     36         p->prev = r;// 新节点的prev指向上一个节点
     37         r = p; // 上一个节点前进到新节点
     38     }
     39     p->next = head; // 指向头节点
     40     head->prev = p; // head的prev指向最后的节点
     41 }
     42 
     43 // 由数组创建双链表
     44 void DLink_createByArray(DLinkList head, int* arrName, int n) 
     45 {
     46     pDLinkNode p = head, r = head;
     47     for (int i = 0; i < n; ++i)
     48     {
     49         p->next = (pDLinkNode)malloc(sizeof(dNode));/*为一个新节点分配空间*/
     50         assert(NULL != p->next);
     51         p->next->data = arrName[i]; /*数据域*/
     52         p = p->next; /*p指向新节点*/
     53         p->prev = r; /*新节点的前驱指针域prev指向上一个节点*/
     54         r = p;       /*r保存新节点为下次添加做准备*/
     55     }
     56     // 处理循环条件
     57     p->next = head; /*最后节点的后驱指针域next指向头节点head*/
     58     head->prev = p; /*头结点head的前驱指针域prev指向最后节点*/
     59 }
     60 
     61 // 正向显示双链表数据
     62 void Show(DLinkList head) 
     63 { 
     64     pDLinkNode p = head->next;
     65     while (p != head) 
     66     {
     67         printf("%d ",p->data);
     68         p = p->next;
     69     }
     70     printf("
    ");
     71 }
     72 
     73 // 反向显示双链表数据
     74 void ShowR(DLinkList head) 
     75 {
     76     pDLinkNode p = head->prev;
     77     while (p != head) 
     78     {
     79         printf("%d ",p->data);
     80         p = p->prev;
     81     }
     82     printf("
    ");
     83 }
     84  
     85 // 删除循环双链表所有数据节点
     86 void FreeList(DLinkList head) 
     87 { 
     88     pDLinkNode p = head->next;
     89     while (p != head) 
     90     {
     91         pDLinkNode pTemp = p;
     92         p = p->next;
     93         free(pTemp);
     94     }
     95 
     96     head->prev = head->next = head;
     97 }
     98 
     99 // 循环双链表中查找数据
    100 pDLinkNode Find(DLinkList head, int nData)
    101 {
    102     if (NULL == head || NULL == head->next)
    103         return NULL;
    104 
    105     pDLinkNode p = head->next;
    106     while (p != head) 
    107     {
    108         if (nData == p->data)
    109             return p;
    110         p = p->next;
    111     }
    112 
    113     return NULL;
    114 }
    115 
    116 // 从循环双链表中删除数据
    117 void DeleteListData(DLinkList head, int nValue)
    118 {
    119     if (NULL == head || NULL == head->next)
    120         return;
    121 
    122     pDLinkNode pNode = Find(head, nValue);
    123     if (NULL != pNode)
    124     {
    125         pNode->next->prev = pNode->prev;
    126         pNode->prev->next = pNode->next;
    127         free(pNode);
    128         pNode = NULL;
    129     }
    130 }
    131 
    132 // 在循环双链表中插入一个数据
    133 void InsertListData(pDLinkNode pNode, int nValue)
    134 {
    135     pDLinkNode pNewNode = (pDLinkNode)malloc(sizeof(dNode));
    136     assert(NULL != pNewNode);
    137     pNewNode->data = nValue;
    138     pNewNode->prev = pNode;
    139     pNewNode->next = pNode->next;
    140     pNode->next->prev = pNewNode;
    141     pNode->next = pNewNode;
    142 }
    143 
    144 void main() 
    145 {
    146     printf("请输入10个整型数据:
    ");
    147     DLinkList head = GetEmptyDLink();
    148     DLink_create(head, 10);
    149     printf("输入数据创建双链表后,正向显示:
    ");
    150     Show(head);
    151     printf("反向显示:
    ");
    152     ShowR(head);
    153 
    154     printf("
    由数组创建双链表:
    ");
    155     int nArray[10] = {12, 23, 34, 45, 56, 67, 78, 89, 99, 100};
    156     DLinkList head2 = GetEmptyDLink();
    157     DLink_createByArray(head2, nArray, 10);
    158     printf("正向显示:
    ");
    159     Show(head2);
    160     printf("反向显示:
    ");
    161     ShowR(head2);
    162 
    163     printf("删除45后,正向显示:
    ");
    164     DeleteListData(head2, 45);
    165     Show(head2);
    166 
    167     printf("插入666、888后,正向显示:
    ");
    168     InsertListData(head2, 666);
    169     InsertListData(head2, 888);
    170     Show(head2);
    171 
    172     printf("数据释放后,正向显示:
    ");
    173     FreeList(head2);
    174     Show(head2);
    175 
    176     system("pause");
    177 }
    178 // run out
    179 /*
    180 请输入10个整型数据:
    181 1
    182 2
    183 3
    184 4
    185 5
    186 6
    187 7
    188 8
    189 9
    190 10
    191 输入数据创建双链表后,正向显示:
    192 1 2 3 4 5 6 7 8 9 10
    193 反向显示:
    194 10 9 8 7 6 5 4 3 2 1
    195 
    196 由数组创建双链表:
    197 正向显示:
    198 12 23 34 45 56 67 78 89 99 100
    199 反向显示:
    200 100 99 89 78 67 56 45 34 23 12
    201 删除45后,正向显示:
    202 12 23 34 56 67 78 89 99 100
    203 插入666、888后,正向显示:
    204 888 666 12 23 34 56 67 78 89 99 100
    205 数据释放后,正向显示:
    206 
    207 请按任意键继续. . .
    208 */

    注意:双链表循环与无环的区别。

    【3】C++版双链表

    1、循环双链表,实现部分功能函数代码如下:

      1 #pragma once
      2 #include <iostream>
      3 #include <assert.h>
      4 
      5 template<class _Ty> class Iterator;
      6 template<class _Ty> class List;
      7 
      8 // 双链表节点结构
      9 template<class _Ty>
     10 class Node
     11 {
     12     friend class List<_Ty>;
     13     friend class Iterator<_Ty>;
     14 private:
     15     _Ty data;
     16     Node<_Ty>  *prev, *next;
     17 
     18 public:
     19     typedef _Ty          value_type;
     20     typedef _Ty &        reference;
     21     typedef const _Ty &  const_reference;
     22 
     23 public:
     24     Node(const _Ty &x=_Ty(),Node<_Ty> *p=NULL,Node<_Ty> *n=NULL);
     25     ~Node();
     26 
     27     reference Value();
     28     const_reference Value() const;
     29 
     30     Node<_Ty> *& Prev();
     31     Node<_Ty> * const & Prev() const;
     32 
     33     Node<_Ty> *& Next();
     34     Node<_Ty> * const & Next() const;
     35 }; 
     36 
     37 /////////////////////////////////////////////////////////////////
     38 template<class _Ty>
     39 Node<_Ty>::Node(const _Ty &x, Node<_Ty> *p, Node<_Ty> *n)
     40    : data(x)
     41    , prev(p)
     42    , next(n)
     43 {}
     44 
     45 template<class _Ty>
     46 Node<_Ty>::~Node()
     47 {}
     48 
     49 template<class _Ty>
     50 _Ty & Node<_Ty>::Value()
     51 {
     52     return data;
     53 }
     54 
     55 template<class _Ty>
     56 const _Ty &  Node<_Ty>::Value() const
     57 {
     58     return data;
     59 }
     60 
     61 template<class _Ty>
     62 Node<_Ty> *& Node<_Ty>::Prev()
     63 {
     64     return prev;
     65 }
     66 
     67 template<class _Ty>
     68 Node<_Ty> * const & Node<_Ty>::Prev() const
     69 {
     70     return prev;
     71 }
     72 template<class _Ty>
     73 Node<_Ty> * & Node<_Ty>::Next()
     74 {
     75     return next;
     76 }
     77 
     78 template<class _Ty>
     79 Node<_Ty> * const & Node<_Ty>::Next() const
     80 {
     81     return next;
     82 }
     83 
     84 /////////////////////////////////////////////////////////////////
     85 template<class _Ty>
     86 class List
     87 {
     88     friend class Iterator<_Ty>;
     89 private:
     90     Node<_Ty>  *_Head;
     91     size_t     _Size;
     92 
     93     Node<_Ty> * Buynode(const _Ty& x = _Ty(), Node<_Ty>* p = NULL, Node<_Ty>* n = NULL)
     94     {
     95         Node<_Ty>* s = new Node<_Ty>(x);
     96         s->next = n == NULL ? s: n;
     97         s->prev = p == NULL ? s: p;
     98         return s;
     99     }
    100 
    101 public:
    102     // 构造函数
    103     List():_Size(0), _Head(Buynode())    
    104     {}
    105     // 拷贝构造函数
    106     List(const List<_Ty> &Lt);
    107     // 赋值函数
    108     List<_Ty> & operator=(const List<_Ty> &Lt);
    109     // 析构函数    
    110     ~List(){}
    111 /*****************************************
    112 *函数名:size
    113 *参数:void
    114 *返回值类型:size_t
    115 *功能:求双链表的长度
    116 *实现思想:return _Size
    117 *******************************************/
    118 size_t  size() const 
    119 { 
    120     return _Size;
    121 }
    122 /********************************************
    123 *函数名:empty
    124 *参数:void
    125 *返回值类型:bool
    126 *功能:判空
    127 *实现思想:_Size == 0
    128 ********************************************/  
    129 bool empty() const
    130 { 
    131     return 0 == _Size;
    132 }
    133 /*******************************************
    134 *函数名:front
    135 *参数:void
    136 *返回值类型:_Ty &
    137 *功能:返回双链表中第一个数值
    138 *实现思想: 1> 判空
    139            2> 返回第一个节点的值
    140 *******************************************/
    141 _Ty & front()
    142 {
    143     assert(!empty());
    144     return _Head->next->data;
    145 }
    146 // const方法
    147 const _Ty & front() const 
    148 {
    149     assert(!empty());
    150     return _Head->next->data;
    151 }
    152 /*******************************************
    153 *函数名:back
    154 *参数:void
    155 *返回值类型:_Ty  &
    156 *功能:返回双链表最后一个节点的值
    157 *实现思想: 1> 判空
    158            2> 返回最后一个节点的值
    159 *******************************************/
    160 _Ty & back()
    161 {
    162     assert(!empty());
    163     return _Head->prev->data;
    164 }
    165 // const
    166 const _Ty & back() const 
    167 {
    168     assert(!empty());
    169     return _Head->prev->data;
    170 }
    171 /*****************************************
    172 *函数名:push_front
    173 *参数:const _Ty& x
    174 *返回值类型:void
    175 *功能:在双链表最前面插入一个数值
    176 *实现思想: 1> 构建节点
    177           2> 衔接节点
    178           3> 重定长度
    179 *****************************************/
    180 void push_front(const _Ty& x)
    181 {
    182     Node<_Ty>* s = Buynode(x, _Head, _Head->next);
    183     _Head->next = s;
    184     s->next->prev = s; 
    185     ++_Size; 
    186 }
    187 /***************************************
    188 *函数名:pop_front
    189 *参数:void
    190 *返回值类型:void
    191 *功能:弹出双链表中最前面的一个数值
    192 *实现思想: 1> 锁定(判空)第一个节点
    193            2> 移出节点
    194            3> 删除节点
    195            4> 重定长度
    196 ****************************************/
    197 void pop_front()
    198 {
    199     Node<_Ty>* s = _Head->next;
    200     if (s != NULL)
    201     {
    202         _Head->next = s->next;
    203         s->next->prev = _Head;
    204         delete s;
    205     }
    206     --_Size;
    207 }
    208 /**************************************
    209 *函数名:push_back
    210 *参数:const _Ty& x
    211 *返回值类型:void
    212 *功能:在双链表中的末尾插入一个数值
    213 *实现思想: 1> 构建一个节点
    214            2> 衔接节点
    215            3> 重定长度
    216 ***************************************/
    217 void push_back(const _Ty& x)
    218 {
    219     Node<_Ty>* s = Buynode(x, _Head->prev, _Head);
    220     _Head->prev = s;
    221     s->prev->next = s;
    222     ++_Size;
    223 }
    224 /***************************************
    225 *函数名:pop_back
    226 *参数:void
    227 *返回值类型:void
    228 *功能:弹出双链表中的最后一个数值
    229 *实现思想: 1> 锁定(判空)最后一个节点
    230            2> 移出节点
    231            3> 删除节点
    232            4> 重定长度
    233 ***************************************/
    234 void pop_back()
    235 {
    236     Node<_Ty>* s = _Head->prev;
    237     if (s != NULL)
    238     {
    239         _Head->prev = s->prev; 
    240         s->prev->next = _Head;
    241         delete s;
    242     }
    243     --_Size;
    244 
    245 }
    246 /**********************************************
    247 *函数名:findvalue
    248 *参数:const _Ty &x
    249 *返回值类型:Node<_Ty> *
    250 *功能:在双链表中找到某一个值的节点指针
    251 *实现思想: 1> 初始化
    252            2> 循环定位
    253            3> 返回值
    254 ***********************************************/
    255 Node<_Ty> * findvalue(const _Ty &x)
    256 {
    257     Node<_Ty>* p = _Head->next;
    258     while (p != _Head && p->data != x) //防止重复循环
    259     {
    260         p = p->next;
    261     }
    262     return (p == _Head) ? NULL : p;
    263 }
    264 /******************************************
    265 *函数名:prefindvalue
    266 *参数:const _Ty &x
    267 *返回值类型:Node<_Ty> *
    268 *功能:在双链表中按值查找其节点前驱
    269 *实现思想: 1> 初始化
    270            2> 循环定位
    271            3> 返回值
    272 ******************************************/
    273 Node<_Ty> * prefindvalue(const _Ty &x)
    274 {
    275     Node<_Ty>* r = findvalue(x);
    276     return (NULL == r) ? NULL : r->prev;
    277 }
    278 /*******************************************
    279 *函数名:findpos
    280 *参数:int pos
    281 *返回值类型:Node<_Ty> *
    282 *功能:在双链表中按位置求节点指针
    283 *实现思想: 1> 无效pos
    284            2> 有效pos 循环初始化
    285            3> 循环定位
    286 *******************************************/
    287 Node<_Ty>* findpos(size_t pos)
    288 {
    289     if (0 == pos) 
    290         return _Head;
    291     if (pos < 0 || pos >= _Size)
    292         return NULL;
    293 
    294     size_t j = 0;
    295     Node<_Ty>* p = _Head;
    296     while (j < pos)
    297     {
    298         ++j;
    299         p = p->next;
    300     }
    301     return p;
    302 }
    303 /*********************************************
    304 *函数名:findpos
    305 *参数:int  pos
    306 *返回值类型:Node<_Ty> *
    307 *功能:在双链表中按位置求节点指针
    308 *实现思想: 1> 无效pos
    309            2> 有效pos ,循环初始化
    310            3> 循环定位
    311 *********************************************/
    312 /*
    313 Node<_Ty>* findpos(int pos)
    314 {
    315     if (pos < -1 || pos >= _Size) 
    316         return NULL;
    317     if (-1 == pos) 
    318         return _Head;
    319 
    320     int j = 0; 
    321     Node<_Ty>* p = _Head->next;
    322     while (j < pos) 
    323     {
    324         ++j;
    325         p = p->next;
    326     }
    327     return p;
    328 }
    329 */
    330 /********************************************
    331 *函数名:insert
    332 *参数:const int pos,const _Ty &x
    333 *返回值类型:void
    334 *功能:在双链表中的指定位置插入数值
    335 *实现思想: 1> 锁定位置的前驱
    336            2> 构建节点
    337            3> 衔接节点
    338            4> 重定长度
    339 ********************************************/
    340 void insert(const int pos, const _Ty &x)
    341 {
    342     Node<_Ty>* p = findpos(pos - 1); // 前驱
    343     if (NULL == p)
    344         return;
    345 
    346     Node<_Ty>* s = Buynode(x, p, p->next);
    347     p->next = s;
    348     s->next->prev = s;
    349     ++_Size;
    350 }
    351 /*****************************************
    352 *函数名:remove
    353 *参数:const _Ty &x
    354 *返回值类型:void
    355 *功能:从单链表中删除某个值
    356 *实现思想: 1> 按值锁定节点
    357            2> 移出节点
    358            3> 删除节点
    359            4> 重定长度
    360 ******************************************/
    361 void remove(const _Ty &x)
    362 {
    363     Node<_Ty>* p = findvalue(x);
    364     if (p != NULL)
    365     {
    366         p->prev->next = p->next;
    367         p->next->prev = p->prev;
    368         delete p;
    369         --_Size;
    370     }
    371 }
    372 /******************************************
    373 *函数名:removeall
    374 *参数:const _Ty &x
    375 *返回值类型:void
    376 *功能:删除双链表中所有出现的某一值
    377 *实现思想: 1> 初始化
    378            2> 循环逐个判断
    379 *******************************************/
    380 void removeall(const _Ty &x)
    381 {
    382     Node<_Ty>* p = prefindvalue(x);
    383     if (NULL == p)
    384       return;
    385 
    386     while (p->next != _Head)
    387     {
    388         if (p->next->data == x)
    389         {
    390             remove(x);
    391         }
    392         else
    393         {
    394             p = p->next;
    395         }
    396     }
    397 }
    398 /*********************************************
    399 *函数名:erase
    400 *参数:const int pos
    401 *返回值类型:void
    402 *功能:从双链表中按位置删除
    403 *实现思想: 1> 锁定该位置的节点
    404            2> 移出节点
    405            3> 删除节点
    406            4> 重定长度
    407 **********************************************/
    408 void erase(const int pos)
    409 {
    410     Node<_Ty>* p = findpos(pos);
    411     if (NULL != p && p != _Head)
    412     {
    413         p->prev->next = p->next;
    414         p->next->prev = p->prev;
    415         delete p;
    416         --_Size;
    417     }
    418 }
    419 /***********************************/
    420 // 清空链表
    421 void clear()
    422 {
    423     _Head->next = _Head;
    424     _Head->prev = _Head;
    425 }
    426 /***********************************
    427 *函数名:sort
    428 *参数:void
    429 *返回值类型:void
    430 *功能:对双链表中的值进行排序
    431 *实现思想:快速排序
    432 ***********************************/
    433 void sort()
    434 {   
    435     Node<_Ty> *s = NULL, *p = NULL, *min = NULL;
    436     _Ty temp;
    437     s = _Head->next;
    438     while (s != _Head)
    439     {
    440         min = s;
    441         p = s->next;
    442         while (p != _Head)
    443         {
    444             if (min->data > p->data)
    445             {
    446                 temp = min->data;
    447                 min->data = p->data;
    448                 p->data = temp;
    449             }
    450             p = p->next ;
    451         }
    452         s = s->next;
    453     }
    454 }
    455 /************************************
    456 *函数名:print
    457 *参数:void
    458 *返回值类型:void
    459 *功能:输出链表中每个结点数据
    460 *实现思想:循环输出
    461 ************************************/
    462 void print()
    463 {
    464     Node<_Ty> *p = _Head->next;
    465     while (p != _Head)
    466     {
    467         cout << p->data << " ";
    468         p = p->next;
    469     }
    470     cout << endl;
    471 }
    472 /************************************
    473 *函数名:reverse
    474 *参数:void
    475 *返回值类型:void
    476 *功能:重置链表数据
    477 *实现思想:调换每个节点的prev和next
    478 ************************************/
    479 void reverse()
    480 {
    481     Node<_Ty> *r = NULL, *p = _Head;
    482     for (size_t i = 0; i <= _Size; ++i)
    483     {
    484         p = p->next;
    485         r = p->next;
    486         p->next = p->prev;
    487         p->prev = r;
    488     }
    489 }
    490 };
    491 //////////////////////////////////////////////////////////////
    492 template<class _Ty> class Iterator
    493 {
    494 private:
    495     List<_Ty> &list;
    496     Node<_Ty> *Ptr;
    497 public:
    498     Iterator(List<_Ty> &Lt): list(Lt), Ptr(NULL)
    499     {}
    500 
    501     ~Iterator()
    502     {}
    503 
    504     void First()
    505     {
    506         Ptr = list._Head->next;
    507     }
    508 
    509     bool IsDone()  const
    510     {
    511         return Ptr == list._Head;
    512     }
    513 
    514     _Ty & operator*()
    515     {
    516         return Ptr->data;
    517     }
    518 
    519     _Ty * operator->()
    520     {
    521         return &(Ptr->data);
    522     }
    523 
    524     Iterator & operator++()
    525     {
    526         Ptr = Ptr->next;
    527         return *this;
    528     }
    529 
    530     Iterator & operator--()
    531     {
    532         Ptr = Ptr->prev;
    533         return *this;
    534     }
    535 };

    2、测试程序如下:

     1 #include <iostream>
     2 #include "List.h"
     3 using namespace std;
     4 
     5 int sum(List<int> &Lt)
     6 {
     7     Iterator<int> it(Lt);
     8     int ret = 0;
     9     it.First();
    10     while (!it.IsDone())
    11     {
    12         ret += *it;
    13         ++it;
    14     }
    15     return ret;
    16 }
    17 
    18 void main()
    19 {
    20     List<int> mylist;
    21     int i = 0;
    22     for (i = 12; i > 0; --i)
    23     {
    24         mylist.push_back(i); // 方法1
    25     }
    26     cout << sum(mylist) <<endl;
    27 
    28     mylist.push_back(2);   // 方法1
    29     mylist.print();   // 方法2
    30 
    31     mylist.sort();    // 方法3
    32     mylist.print();
    33 
    34     mylist.reverse();   // 方法4
    35     mylist.print();
    36     
    37     mylist.insert(2, 30); // 方法5
    38     mylist.insert(4, 30);
    39     mylist.insert(5, 30);
    40     mylist.insert(8, 30);
    41     mylist.print();
    42 
    43     mylist.push_front(11); // 方法6
    44     mylist.print();
    45 
    46     mylist.remove(3); // 方法7
    47     mylist.print();
    48     
    49     mylist.removeall(30); // 方法8
    50     mylist.print();
    51 
    52     mylist.erase(7);// 方法9
    53     mylist.print();
    54 
    55     cout << mylist.size() << endl; // 方法10
    56 
    57     mylist.clear();   // 方法11
    58     mylist.print();
    59     system("pause");
    60 }
    61 
    62 // 备注:
    63 // 数据结构双链表实现代码
    64 // 整理于2013-11-27
    65 // 双链表的节点结构为:前驱~数据~后驱 (三部分)
    66 // 该双链表是有头结点的
    67 // 该双链表的头结点索引为0,第一个数据节点为1,以此类推。
    68 // 尤其注意findpos函数的pos为size_t类型
    69 // 认真琢磨双链表的功能实现函数

    循环双链表的应用很广,此例测试程序很简单。

    【4】双链表的分类

    1、不带头节点的循环非空双链表

    2、带头节点的循环双链表

    示例1:

    示例2:

    示例3:

    示例4:

     

    3、带头节点的无环双链表

    示例1:

    示例2:

     

    4、无环与循环双链表的区别

    5、双链表分类

    6、各种表的对比图

    【5】双链表中插入节点

    (1)插入节点代码描述:

     1 // 在循环双链表中插入一个数据
     2 void InsertListData(pDLinkNode pNode, int nValue)
     3 {
     4     pDLinkNode pNewNode = (pDLinkNode)malloc(sizeof(dNode));
     5     assert(NULL != pNewNode);
     6 
     7     pNewNode->data = nValue;
     8     pNewNode->prev = pNode;
     9     pNewNode->next = pNode->next;
    10     pNode->next->prev = pNewNode;
    11     pNode->next = pNewNode;
    12 }

    (2)思路分析:

    步骤1、新节点的前驱

    步骤2、新节点的后驱

    步骤3、新节点后一个节点的前驱

    步骤4、新节点前一个节点的后驱

    (3)为了更形象的理解这个过程,搜集如下逻辑结构示意图:

    图1:

    图2:

    图3:

    图4:

    图5:

    图6:

    【6】双链表中删除节点

    (1)双链表删除节点代码:

     1 // 从循环双链表中删除数据
     2 void DeleteListData(DLinkList head, int nValue)
     3 {
     4     if (NULL == head || NULL == head->next)
     5         return;
     6 
     7     pDLinkNode pNode = Find(head, nValue);
     8     if (NULL != pNode)
     9     {
    10         pNode->next->prev = pNode->prev;
    11         pNode->prev->next = pNode->next;
    12         free(pNode);
    13         pNode = NULL;
    14     }
    15 }

    (2)删除节点的思路分析:

    步骤1、找到即将被删除的节点 pNode

    步骤2、将 pNode 的后继的前驱指向 pNode 的前驱,即 pNode->next->prev = pNode->prev;

    步骤3、将 pNode 的前驱的后继指向 pNode 的后继,即 pNode->prev->next = pNode->next;

    步骤4、删除节点 pNode, 即 free(pNode);

    (3)为了更形象的理解这个过程,搜集如下逻辑结构示意图:

    图1:

    图2:

    图3:

    图4:

    图5:

    图6:

    【7】单链表与双链表的区别

    单链表: 结构简单,存储空间小,但是只能向前访问节点,如果需要访问之前的节点,需要建立循环链表。
    双链表: 存储前一节点和后一节点地址,可以自由访问各个节点,存储空间比单链要大。

     

    Good  Good  Study,  Day  Day  Up.

    顺序  选择  循环  总结

  • 相关阅读:
    git 从远程仓库指定分支克隆代码到本地
    vue路由懒加载
    ES6中拓展运算符 ...
    Mysql 安装-windows X64
    mysql-Federated存储方式,远程表,相当于sql server的linked server
    优化临时表使用,SQL语句性能提升100倍
    MySQL行锁深入研究
    mysql 队列 实现并发读
    mysql 常用sql
    mysql分表的3种方法
  • 原文地址:https://www.cnblogs.com/Braveliu/p/6408578.html
Copyright © 2011-2022 走看看