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)定义双向链表的基本结构
- typedef struct _DOUBLE_LINK_NODE
- {
- int data;
- struct _DOUBLE_LINK_NODE* prev;
- struct _DOUBLE_LINK_NODE* next;
- }DOUBLE_LINK_NODE;
- DOUBLE_LINK_NODE* create_double_link_node(int value)
- {
- DOUBLE_LINK_NODE* pDLinkNode = NULL;
- pDLinkNode = (DOUBLE_LINK_NODE*)malloc(sizeof(DOUBLE_LINK_NODE));
- assert(NULL != pDLinkNode);
- memset(pDLinkNode, 0, sizeof(DOUBLE_LINK_NODE));
- pDLinkNode->data = value;
- return pDLinkNode;
- }
- void delete_all_double_link_node(DOUBLE_LINK_NODE** pDLinkNode)
- {
- DOUBLE_LINK_NODE* pNode;
- if(NULL == *pDLinkNode)
- return ;
- pNode = *pDLinkNode;
- *pDLinkNode = pNode->next;
- free(pNode);
- delete_all_double_link_node(pDLinkNode);
- }
- DOUBLE_LINK_NODE* find_data_in_double_link(const DOUBLE_LINK_NODE* pDLinkNode, int data)
- {
- DOUBLE_LINK_NODE* pNode = NULL;
- if(NULL == pDLinkNode)
- return NULL;
- pNode = (DOUBLE_LINK_NODE*)pDLinkNode;
- while(NULL != pNode){
- if(data == pNode->data)
- return pNode;
- pNode = pNode ->next;
- }
- return NULL;
- }
- STATUS insert_data_into_double_link(DOUBLE_LINK_NODE** ppDLinkNode, int data)
- {
- DOUBLE_LINK_NODE* pNode;
- DOUBLE_LINK_NODE* pIndex;
- if(NULL == ppDLinkNode)
- return FALSE;
- if(NULL == *ppDLinkNode){
- pNode = create_double_link_node(data);
- assert(NULL != pNode);
- *ppDLinkNode = pNode;
- (*ppDLinkNode)->prev = (*ppDLinkNode)->next = NULL;
- return TRUE;
- }
- if(NULL != find_data_in_double_link(*ppDLinkNode, data))
- return FALSE;
- pNode = create_double_link_node(data);
- assert(NULL != pNode);
- pIndex = *ppDLinkNode;
- while(NULL != pIndex->next)
- pIndex = pIndex->next;
- pNode->prev = pIndex;
- pNode->next = pIndex->next;
- pIndex->next = pNode;
- return TRUE;
- }
- STATUS delete_data_from_double_link(DOUBLE_LINK_NODE** ppDLinkNode, int data)
- {
- DOUBLE_LINK_NODE* pNode;
- if(NULL == ppDLinkNode || NULL == *ppDLinkNode)
- return FALSE;
- pNode = find_data_in_double_link(*ppDLinkNode, data);
- if(NULL == pNode)
- return FALSE;
- if(pNode == *ppDLinkNode){
- if(NULL == (*ppDLinkNode)->next){
- *ppDLinkNode = NULL;
- }else{
- *ppDLinkNode = pNode->next;
- (*ppDLinkNode)->prev = NULL;
- }
- }else{
- if(pNode->next)
- pNode->next->prev = pNode->prev;
- pNode->prev->next = pNode->next;
- }
- free(pNode);
- return TRUE;
- }
- int count_number_in_double_link(const DOUBLE_LINK_NODE* pDLinkNode)
- {
- int count = 0;
- DOUBLE_LINK_NODE* pNode = (DOUBLE_LINK_NODE*)pDLinkNode;
- while(NULL != pNode){
- count ++;
- pNode = pNode->next;
- }
- return count;
- }
- void print_double_link_node(const DOUBLE_LINK_NODE* pDLinkNode)
- {
- DOUBLE_LINK_NODE* pNode = (DOUBLE_LINK_NODE*)pDLinkNode;
- while(NULL != pNode){
- printf("%d\n", pNode->data);
- pNode = pNode ->next;
- }
- }
今天我们讨论的双向链表是非循环的,大家可以考虑一下如果改成循环双向链表,应该怎么写?如果是有序的循环双向链表,又该怎么写?
转自:
http://jpkc.xaau.edu.cn/sjjg/datastru/zxxx/two%20lesson/233.html
双向链表
双向链表是链式存储结构的另一种表示形式。在双向链表中,结点的结构如图2-13所示。
图2-13 双向链表结点结构示意
从图2-13可以看到,双向链表中每个结点包括三个域:数据域(data),前趋指针域(prior),后继指针域(next)。数据域(data)用来存放该结点的数据元素信息;前趋指针域(prior)用来存放指示该结点的直接前趋的地址信息,即前趋指针;后继指针域(next)用来存放指示该结点的直接后继的地址信息,即后继指针。前趋指针同后继指针分别构成两个不同方向的链。若每条链构成一个环,就称为双向循环链表,如图2-14所示。
图2-14 双向循环链表
在单链表或单向循环链表中,若指针指向某结点后,要通过该结点访问其直接后继很方便,而要通过该结点求其直接前趋,则需从头指针出发,这是由它们的单向性决定的。有了双向链表后,这个问题就变得相当容易了,因为每个结点直接前趋的地址就包含在其前趋指针域中。 双向链表的类C语言可描述如下:
结构2-3 双向链表
struct dubnode
{ Datatype data;
struct dubnode *prior;
struct dubnode *next;
}
typedef struct dubnode DuLinkList;
双向链表的某些操作将涉及到两个方向的指针修改,操作时应特别注意。图2-15是在双向链表中插入一个结点的示意图。
图2-15 在双向链表中插入一个结点
针修改操作为:
s->prior = p->prior;
s->next = p;
p->prior->next = s;
p->prior = s;
以上操作的语句顺序可以改变,但要注意p的前趋指针的修改一定要在p的前趋结点的后继指针修改之后方可修改,否则不能正确插入。
同样,在双向链表中删除一个结点时,也需要修改两个方向的指针,其指针变化如图2-16所示。
图2-16 在双向链表中删除一个结点
指针修改操作为:
p->prior->next = p->next;
p->next->prior = p->prior; 请考虑以上操作的语句顺序是否可以改变。
在双向链表中,若p为指向表中某一结点的指针,则有:
p->next->prior = p;
p->prior->next = p;
这正好反映了双向链表的结构特性。