当前位置:   article > 正文

数据结构— —双向链表

双向链表

双向链表的算法实现

单链表中每个结点除了存储自身数据之后,还存储了下一个结点的地址,因此可以轻松访问下一个结点,以及后面的后继结点,但是如果想访问前面的结点就不行了,再也回不去了。例如删除结点 p 时,要先找到它的前一个结点 q,然后才能删掉 p 结点,单向链表只能往后走,不能向前走。如果需要向前走,怎么办呢?

可以在单链表的基础上给每个元素附加两个指针域,一个存储前一个元素的地址,一个存储下一个元素的地址。这种链表称为双向链表.

 

其结构体定义:

typedef struct _LinkNode {

int data; //结点的数据域 struct _LinkNode *next; //下一个节点的指针域

struct _LinkNode *prev; //上一个结点的指针域

}LinkNode, LinkList; //LinkList 为指向结构体 LNode 的指针类型

双向链表的初始

//前插法

bool DbListInsert_front(DbLinkList* &L, DbLinkNode *node){ if(!L || !node) return false;

//1.只有头节点

if(L->next==NULL){

typedef struct _DoubleLinkNode { int data; //结点的数据域

struct _DoubleLinkNode *next; //下一个节点的指针域 struct _DoubleLinkNode *prev; //上一个结点的指针域

}DbLinkNode, DbLinkList; //LinkList为指向结构体LNode的指针类型

bool DbInit_List(DbLinkList* &L)//构造一个空的双向链表L

{

L=new DbLinkNode; //生成新结点作为头结点,用头指针L指向头结点 if(!L)return false; //生成结点失败

L->next=NULL; //头结点的next指针域置空

L->prev=NULL; //头结点的指针域置空 L->data = -1; return true;

}

双向链表增加元素前插法

                  node->next=NULL;                           11

node->prev=L; //新节点prev 指针指向头节点 L->next=node; //头节点next 指针指向新节点

}else {

L->next->prev=node;  //第二个节点的prev 指向新节点 node->next = L->next; //新节点next指针指向第二个节点 node->prev=L;    //新节点prev 指针指向头节点

                  L->next=node;            //头节点next 指针指向新节点,完成插入

}

return true;

}

 尾插法

//尾插法

bool DbListInsert_back(DbLinkList* &L, DbLinkNode *node){ DbLinkNode *last = NULL; if(!L || !node) return false;

last = L;

while(last->next) last = last->next;

node->next = NULL;

last->next = node;

node->prev = last; return true; }

 

任意位置插入

//指定位置插入

bool DbLink_Insert(DbLinkList* &L, int i, int &e){ if(!L||!L->next) return false; if(i<1) return false;

int j =0;

DbLinkList *p, *s;

p = L;

while(p && j<i){//查找位置为i的结点,p指向该结点 p = p->next;

j++;

}

if(!p || j!=i){ cout<<"不存在节点:"<<i<<endl;

return false;

} cout<<"p: "<<p<<endl;

s=new DbLinkNode;//生成新节点

s->data = e;

s->next = p;

s->prev = p->prev;

p->prev->next = s;

p->prev = s;

return true;

}

双向链表的遍历

//双向链表的遍历输出

void DbLink_Print(DbLinkList* &L ){

DbLinkNode *p = NULL;

if(!L){

cout<<"链表为空."<<endl; return ;

}

p = L;

while(p->next){

cout<<p->next->data<<"\t";

p = p->next;

}

//逆向打印

cout<<endl<<"逆向打印"<<endl;

while(p){

cout<<p->data<<"\t";

p = p->prev;

}

cout<<endl;

}

双向链表获取元素

bool DbLink_GetElem(DbLinkList* &L, int i, int &e)//双向链表的取值

{

//在带头结点的双向链表L中查找第i个元素

//用e记录L中第i个数据元素的值

int index;

DbLinkList *p;

if(!L || !L->next) return false;

p = L->next;

index = 1;

while(p && index<i){//顺链表向后扫描,直到p指向第i个元素或p为空

p = p->next;

index++;

}

if(!p || index>i){ return false//i值不合法,i>n或i<=0

}

e=p->data; return true;

}

11

双向链表删除元素

//任意位置删除

bool DbLink_Delete(DbLinkList* &L, int i) //双向链表的删除

{

DbLinkList *p;

int index = 0;

if(!L || !L->next){

cout<<"双向链表为空!"<<endl;

return false;

}

if(i<1) return false; //不能删除头节点

p=L;

while(p && index<i){

p = p->next;

index++;

}

if(!p){ //当节点不存在时,返回失败 return false;

}

p->prev->next=p->next; //改变删除结点前驱结点的next 指针域 if(p->next){

p->next->prev = p->prev; //改变删除节点后继节点的prev 指针域

}

delete p;         //释放被删除结点的空间

return true;

}

11

双向链表销毁

void DbLink_Destroy(DbLinkList* &L) //双向链表的销毁

{

//定义临时节点p指向头节点

DbLinkList *p = L;

cout<<"销毁链表!"<<endl;

while(p){

L=L->next;//L指向下一个节点 cout<<"删除元素: "<<p->data<<endl; delete p; //删除当前节点

p = L;   //p 移向下一个节点

}

}

完整代码实现

  1. #include <iostream>
  2. #include <Windows.h>
  3. using namespace std;
  4. typedef struct _DbLinkList
  5. {
  6. int data;//数据域
  7. struct _DbLinkList* prev;//前驱结点
  8. struct _DbLinkList* next;//后继结点
  9. }DbLinkList, DbLinkNode;
  10. bool DbLinkList_Init(DbLinkList*& L)
  11. {
  12. //分配头结点
  13. L = new DbLinkNode;
  14. if (!L)
  15. {
  16. return false;
  17. }
  18. L->next = NULL;
  19. L->prev = NULL;
  20. L->data = -1;
  21. return true;
  22. }
  23. //头插
  24. bool InsertDbLink_front(DbLinkList*& L, DbLinkList* node)
  25. {
  26. if (!L || !node)
  27. {
  28. return false;
  29. }
  30. if (L->next == NULL)
  31. {
  32. node->next = NULL;
  33. node->prev = L;
  34. L->next = node;
  35. }
  36. else
  37. {
  38. L->next->prev = node;
  39. node->next = L->next;
  40. node->prev = L;
  41. L->next = node;
  42. //L->next->prev = node; //第二个节点的 prev 指向新节点
  43. //node->next = L->next; //新节点 next 指针指向第二个节点
  44. //node->prev = L; //新节点 prev 指针指向头节点
  45. //L->next = node;
  46. }
  47. return true;
  48. }
  49. //尾插
  50. bool InsertDbLink_back(DbLinkList* &L, DbLinkNode* node)
  51. {
  52. if (!L || !node)
  53. {
  54. return false;
  55. }
  56. DbLinkList* q;
  57. q = L;
  58. while (q->next)
  59. {
  60. q = q->next;
  61. }
  62. q->next = node;
  63. node->prev = node;
  64. return true;
  65. }
  66. //任意位置插入
  67. bool DbLink_Insert(DbLinkList*& L,int i,int &e)
  68. {
  69. DbLinkList* q, * s;
  70. int j = 1;
  71. q = L->next;
  72. if (!L || !L->next)
  73. {
  74. return false;
  75. }
  76. while (!q || j < i)
  77. {
  78. q = q->next;
  79. j++;
  80. }
  81. if (!q || i != j)
  82. {
  83. return false;
  84. }
  85. s = new DbLinkNode;
  86. s->data = e;
  87. q->prev->next = s;
  88. s->prev = q->prev;
  89. s->next = q;
  90. q->prev = s;
  91. return true;
  92. }
  93. //按指定位置查找元素
  94. bool seekElem(DbLinkList*& L, int i, int& e)
  95. {
  96. DbLinkList* p;
  97. int j = 1;
  98. p = L->next;
  99. if (!L || !L->next)
  100. {
  101. return false;
  102. }
  103. while (p && j < i)
  104. {
  105. p = p->next;
  106. j++;
  107. }
  108. if (!p || j > i)
  109. {
  110. return false;
  111. }
  112. e = p->data;
  113. return true;
  114. }
  115. bool DbLink_Delete(DbLinkList*& L, int i)
  116. {
  117. DbLinkNode* pos;
  118. int j = 1;
  119. pos = L->next;
  120. if (!L || !L->next)
  121. {
  122. return false;
  123. }
  124. if (i < 1)
  125. {
  126. return false;
  127. }
  128. while (!pos ||j<i)
  129. {
  130. pos = pos->next;
  131. j++;
  132. }
  133. if (!pos)
  134. {
  135. return false;
  136. }
  137. pos->prev->next = pos->next;
  138. pos->next->prev = pos->prev;
  139. delete pos;
  140. return true;
  141. }
  142. //链表的销毁
  143. void DestroyLink(DbLinkList* &L)
  144. {
  145. DbLinkNode* q = L;
  146. if (!L)
  147. {
  148. cout << "链表为空" << endl;
  149. }
  150. while (q)
  151. {
  152. L = L->next;
  153. delete q;
  154. q = L;
  155. }
  156. cout << "链表销毁了" << endl;
  157. }
  158. void DbLink_Print(DbLinkList*& L)
  159. {
  160. DbLinkNode* s = NULL;
  161. s = L;
  162. if (!L)
  163. {
  164. cout << "链表为空." << endl;
  165. return;
  166. }
  167. while (s->next)
  168. {
  169. s = s->next;
  170. cout << s->data << "\t";
  171. }
  172. cout << endl;
  173. while (s!=L)
  174. {
  175. cout << s->data << "\t";
  176. s = s->prev;
  177. }
  178. cout << endl;
  179. }
  180. int main(void)
  181. {
  182. DbLinkList* L, * s, * a;
  183. //双向链表初始化
  184. if (DbLinkList_Init(L))
  185. {
  186. cout << "初始化循环链表成功" << endl;
  187. }
  188. else
  189. {
  190. cout << "初始化循环链表失败" << endl;
  191. }
  192. //前插
  193. int j;
  194. cout << "请输入你要插入的个数:";
  195. cin >> j;
  196. for (int i = 0; i < j; i++)
  197. {
  198. s = new DbLinkNode;
  199. cin >> s->data;
  200. InsertDbLink_front(L, s);
  201. }
  202. DbLink_Print(L);
  203. //尾插
  204. int z;
  205. cout << "请输入你要插入的个数:";
  206. cin >> z;
  207. for (int i = 0; i < z; i++)
  208. {
  209. a = new DbLinkNode;
  210. cin >> a->data;
  211. InsertDbLink_front(L, a);
  212. }
  213. DbLink_Print(L);
  214. //任意位置插入
  215. int element, w;
  216. cout << "请输入你要插入的数:";
  217. cin >> w;
  218. cout << "请输入你要插入的位置:";
  219. cin >> element;
  220. DbLink_Insert(L, element, w);
  221. DbLink_Print(L);
  222. //查找元素
  223. int b;
  224. cout << "请输入你要查找元素的位置:";
  225. cin >> b;
  226. seekElem(L, b, element);
  227. cout << element << endl;
  228. //删除指定位置的元素
  229. DbLink_Delete(L, 3);
  230. DbLink_Print(L);
  231. //销毁链表
  232. DestroyLink(L);
  233. DbLink_Print(L);
  234. system("pause");
  235. return 0;
  236. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/655442
推荐阅读
相关标签
  

闽ICP备14008679号