双向链表

http://www.cprogramming.com/snippets/source-code/double-linked-list-cplusplus


This snippet submitted by Ali Murad on 2012-03-10. It has been viewed 3838 times.
Rating of 9 with 20 votes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//An example of a simple double linked list using OOP techniques
#include <iostream>
using namespace std;
 
struct Node
{
   double value;
   Node *N,*P;
   Node( double y)
   {
       value = y;
       N = P = NULL;
   }
};
 
class doubleLinkedList
{
   Node *front;
   Node *back;
   public :
   doubleLinkedList()
   {  front = NULL; back = NULL; }
   ~doubleLinkedList(){ destroyList();}
   void appendNodeFront( double x);
   void appendNodeBack( double x);
   void dispNodesForward();
   void dispNodesReverse();
   void destroyList();
};
 
void doubleLinkedList::appendNodeFront( double x)
   {
         Node *n = new Node(x);
         if ( front == NULL)
         {
             front = n;
             back = n;
         }
         else
         {
             front->P = n;
             n->N = front;
             front = n;
         }
   }
   void doubleLinkedList::appendNodeBack( double x)
   {
         Node *n = new Node(x);
         if ( back == NULL)
         {
             front = n;
             back = n;
         }
         else
         {
             back->N = n;
             n->P = back;
             back = n;
         }
 
   }
 
   void doubleLinkedList::dispNodesForward()
   {
       Node *temp = front;
       cout << "\n\nNodes in forward order:" << endl;
       while (temp != NULL)
       {
          cout << temp->value << "   " ;
          temp = temp->N;
       }
   }
   void doubleLinkedList::dispNodesReverse()
   {
       Node *temp = back;
       cout << "\n\nNodes in reverse order :" << endl;
       while (temp != NULL)
       {
          cout << temp->value << "   " ;
          temp = temp->P;
       }
   }
void doubleLinkedList::destroyList()
{
     Node *T = back;
     while (T != NULL)
     {
         Node *T2 = T;
         T = T->P;
         delete T2;
     }
     front = NULL;
     back = NULL;
}
int main()
{
     doubleLinkedList *list = new doubleLinkedList();
     //append nodes to front of the list
     for ( int i = 1 ; i < 4 ; i++)
     list->appendNodeFront(i*1.1);
 
     list->dispNodesForward();
     list->dispNodesReverse();
 
     //append nodes to back of the list
     for ( int i = 1 ; i < 4 ; i++)
     list->appendNodeBack(11.0 - (1.1 * i));
     cout << endl << endl;
     list->dispNodesForward();
     list->dispNodesReverse();
 
     cout << endl << endl;
     delete list;
     return 0;
}
 
/* Program's output
Nodes in forward order:
3.3   2.2   1.1
 
Nodes in reverse order :
1.1   2.2   3.3
 
 
 
Nodes in forward order:
3.3   2.2   1.1   9.9   8.8   7.7
 
Nodes in reverse order :
7.7   8.8   9.9   1.1   2.2   3.3
*/






转自:

http://blog.csdn.net/feixiaoxing/article/details/6849457


【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    前面的博客我们介绍了单向链表。那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针。双向链表相比较单向链表,主要有下面几个特点:

    (1)在数据结构中具有双向指针

    (2)插入数据的时候需要考虑前后的方向的操作

    (3)同样,删除数据的是有也需要考虑前后方向的操作

    那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下:

    (1)定义双向链表的基本结构

  1. typedef struct _DOUBLE_LINK_NODE  
  2. {  
  3.     int data;  
  4.     struct _DOUBLE_LINK_NODE* prev;  
  5.     struct _DOUBLE_LINK_NODE* next;  
  6. }DOUBLE_LINK_NODE;  
     (2)创建双向链表节点
  1. DOUBLE_LINK_NODE* create_double_link_node(int value)  
  2. {  
  3.     DOUBLE_LINK_NODE* pDLinkNode = NULL;  
  4.     pDLinkNode = (DOUBLE_LINK_NODE*)malloc(sizeof(DOUBLE_LINK_NODE));  
  5.     assert(NULL != pDLinkNode);  
  6.   
  7.     memset(pDLinkNode, 0, sizeof(DOUBLE_LINK_NODE));  
  8.     pDLinkNode->data = value;  
  9.     return pDLinkNode;  
  10. }  
     (3)删除双向链表
  1. void delete_all_double_link_node(DOUBLE_LINK_NODE** pDLinkNode)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode;  
  4.     if(NULL == *pDLinkNode)  
  5.         return ;  
  6.   
  7.     pNode = *pDLinkNode;  
  8.     *pDLinkNode = pNode->next;  
  9.     free(pNode);  
  10.     delete_all_double_link_node(pDLinkNode);  
  11. }  
     (4)在双向链表中查找数据
  1. DOUBLE_LINK_NODE* find_data_in_double_link(const DOUBLE_LINK_NODE* pDLinkNode, int data)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode = NULL;  
  4.     if(NULL == pDLinkNode)  
  5.         return NULL;  
  6.   
  7.     pNode = (DOUBLE_LINK_NODE*)pDLinkNode;  
  8.     while(NULL != pNode){  
  9.         if(data == pNode->data)  
  10.             return pNode;  
  11.         pNode = pNode ->next;  
  12.     }  
  13.       
  14.     return NULL;  
  15. }  
     (5)双向链表中插入数据
  1. STATUS insert_data_into_double_link(DOUBLE_LINK_NODE** ppDLinkNode, int data)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode;  
  4.     DOUBLE_LINK_NODE* pIndex;  
  5.   
  6.     if(NULL == ppDLinkNode)  
  7.         return FALSE;  
  8.   
  9.     if(NULL == *ppDLinkNode){  
  10.         pNode = create_double_link_node(data);  
  11.         assert(NULL != pNode);  
  12.         *ppDLinkNode = pNode;  
  13.         (*ppDLinkNode)->prev = (*ppDLinkNode)->next = NULL;  
  14.         return TRUE;  
  15.     }  
  16.   
  17.     if(NULL != find_data_in_double_link(*ppDLinkNode, data))  
  18.         return FALSE;  
  19.   
  20.     pNode = create_double_link_node(data);  
  21.     assert(NULL != pNode);  
  22.   
  23.     pIndex = *ppDLinkNode;  
  24.     while(NULL != pIndex->next)  
  25.         pIndex = pIndex->next;  
  26.   
  27.     pNode->prev = pIndex;  
  28.     pNode->next = pIndex->next;  
  29.     pIndex->next = pNode;  
  30.     return TRUE;  
  31. }  
     (6)双向链表中删除数据
  1. STATUS delete_data_from_double_link(DOUBLE_LINK_NODE** ppDLinkNode, int data)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode;  
  4.     if(NULL == ppDLinkNode || NULL == *ppDLinkNode)  
  5.         return FALSE;  
  6.   
  7.     pNode = find_data_in_double_link(*ppDLinkNode, data);  
  8.     if(NULL == pNode)  
  9.         return FALSE;  
  10.   
  11.     if(pNode == *ppDLinkNode){  
  12.         if(NULL == (*ppDLinkNode)->next){  
  13.             *ppDLinkNode = NULL;  
  14.         }else{  
  15.             *ppDLinkNode = pNode->next;  
  16.             (*ppDLinkNode)->prev = NULL;  
  17.         }  
  18.   
  19.     }else{  
  20.         if(pNode->next)  
  21.             pNode->next->prev = pNode->prev;  
  22.         pNode->prev->next = pNode->next;  
  23.     }  
  24.   
  25.     free(pNode);  
  26.     return TRUE;  
  27. }  
     (7)统计双向链表中数据的个数
  1. int count_number_in_double_link(const DOUBLE_LINK_NODE* pDLinkNode)  
  2. {  
  3.     int count = 0;  
  4.     DOUBLE_LINK_NODE* pNode = (DOUBLE_LINK_NODE*)pDLinkNode;  
  5.   
  6.     while(NULL != pNode){  
  7.         count ++;  
  8.         pNode = pNode->next;  
  9.     }  
  10.     return count;  
  11. }  
     (8)打印双向链表中数据
  1. void print_double_link_node(const DOUBLE_LINK_NODE* pDLinkNode)  
  2. {  
  3.     DOUBLE_LINK_NODE* pNode = (DOUBLE_LINK_NODE*)pDLinkNode;  
  4.   
  5.     while(NULL != pNode){  
  6.         printf("%d\n", pNode->data);  
  7.         pNode = pNode ->next;  
  8.     }  
  9. }  
    注意:

        今天我们讨论的双向链表是非循环的,大家可以考虑一下如果改成循环双向链表,应该怎么写?如果是有序的循环双向链表,又该怎么写?


转自:

http://jpkc.xaau.edu.cn/sjjg/datastru/zxxx/two%20lesson/233.html

双向链表

    向链表是链式存储结构的另一种表示形式。在双向链表中,结点的结构如图2-13所示。

1

图2-13 双向链表结点结构示意

    从图2-13可以看到,双向链表中每个结点包括三个域:数据域(data),前趋指针域(prior),后继指针域(next)。数据域(data)用来存放该结点的数据元素信息;前趋指针域(prior)用来存放指示该结点的直接前趋的地址信息,即前趋指针;后继指针域(next)用来存放指示该结点的直接后继的地址信息,即后继指针。前趋指针同后继指针分别构成两个不同方向的链。若每条链构成一个环,就称为双向循环链表,如图2-14所示。

1

图2-14  双向循环链表

    在单链表或单向循环链表中,若指针指向某结点后,要通过该结点访问其直接后继很方便,而要通过该结点求其直接前趋,则需从头指针出发,这是由它们的单向性决定的。有了双向链表后,这个问题就变得相当容易了,因为每个结点直接前趋的地址就包含在其前趋指针域中。 双向链表的类C语言可描述如下:

结构2-3 双向链表

struct dubnode

 { Datatype data;

   struct dubnode *prior;

   struct dubnode *next;

}

typedef  struct  dubnode  DuLinkList;

    双向链表的某些操作将涉及到两个方向的指针修改,操作时应特别注意。图2-15是在双向链表中插入一个结点的示意图。

1

图2-15 在双向链表中插入一个结点

    针修改操作为:

                s->prior = p->prior;

                s->next = p;

                p->prior->next = s;

                p->prior = s;

    以上操作的语句顺序可以改变,但要注意p的前趋指针的修改一定要在p的前趋结点的后继指针修改之后方可修改,否则不能正确插入。

同样,在双向链表中删除一个结点时,也需要修改两个方向的指针,其指针变化如图2-16所示。

1

图2-16 在双向链表中删除一个结点

指针修改操作为:

               p->prior->next = p->next;

               p->next->prior = p->prior; 请考虑以上操作的语句顺序是否可以改变。

在双向链表中,若p为指向表中某一结点的指针,则有:

               p->next->prior = p;

               p->prior->next = p;

这正好反映了双向链表的结构特性。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值