双向循环链表

  1. //双向循环链表
  2. typedef int datatype;
  3. //方便修改
  4. //当然也可以写成模板来适应更多的数据类型
  5. struct dclink{
  6. datatype data;//数据定义
  7. struct dclink *pre;
  8. struct dclink *next;//前驱和后继指针
  9. };
  10. class DCLink
  11. {
  12. public:
  13. DCLink();//default constructor
  14. DCLink(datatype data);//单参constructor
  15. void add(datatype data);//添加data到链表中去
  16. datatype getData(int pos)const;//获得指定位置的数据
  17. int deleteData(int pos);//删除指定位置的数据
  18. int modify(int pos, datatype data);//更改指定位置的数据
  19. int insert(int pos, datatype data);//在指定位置插入数据
  20. void sort()const;//循环链表排序
  21. int rePrint()const;//双向循环链表转置没啥意义,转置输出还有那么点意义
  22. int print()const;//打印链表
  23. ~DCLink();//destructor
  24. int getLength()const;//得到链表的长度
  25. private:
  26. DCLink operator=(const DCLink &dcl){}//assignment constructor 禁止
  27. DCLink (const DCLink &dcl){}//copy constructor 禁止
  28. struct dclink *head;//头指针
  29. struct dclink *cur;//当前指针
  30. int size;//大小
  31. };
  32. #endif

DCLink.cpp

[cpp] view plain copy

  1. #include "dclink.h"
  2. #include <iostream>
  3. //default constructor
  4. DCLink::DCLink(){
  5. head = cur = NULL;//默认为空
  6. size = 0;
  7. }
  8. DCLink::DCLink(datatype data){//单参constructor
  9. head = new struct dclink[1];//申请空间
  10. cur = head;//指向当前节点
  11. head->data = data;
  12. head->next = head->pre = head;//指向自身
  13. size = 1;
  14. }
  15. void DCLink::add(datatype data){//添加data到链表中去
  16. //默认添加到表尾
  17. struct dclink *dcl = new struct dclink[1];
  18. dcl->data = data;
  19. if (NULL != head){//表非空
  20. //当前节点为第1号节点,它的后继节点为第2号节点
  21. struct dclink *temp = cur->next;//保持2号节点的位置
  22. cur->next = dcl;//1号节点的后继和新增节点相连
  23. dcl->pre = cur;//新增节点的前驱和1号节点相连
  24. dcl->next = temp;//新增节点的后继和2号节点相连
  25. temp->pre = dcl;//新增节点和2号节点的前驱相连
  26. }else {
  27. head = dcl;//新加节点成为头结点
  28. head->data = data;
  29. head->next = head->pre = head;//指向自身
  30. }//已经添加完毕,新增节点成为当前节点
  31. cur = dcl;
  32. size++;//长度+1
  33. }
  34. int DCLink::deleteData(int pos){//删除指定位置的数据
  35. if (size >= pos && pos > 0){//有数据并且没有越界才显示
  36. int count = 1;//计数
  37. struct dclink *temp = head;
  38. while (pos != count){
  39. temp = temp->next;//直到到达指定的位置
  40. count++;
  41. }//先到达指定位置
  42. //分情况是因为如果删除最后一个节点会改变cur的状态,挂空指针
  43. if (size == pos){
  44. if (1 == size){//只有一个节点的时候
  45. delete []temp;
  46. head = cur = NULL;//置空
  47. size--;//-1
  48. return 0;
  49. }else{//删除最后一个节点
  50. cur = temp->pre;//向前移动一个位置
  51. }
  52. }else{//如果删除第一个节点head会改变
  53. if (1 == pos){
  54. head = temp->next;//向后移动一个位置
  55. }
  56. }
  57. //当前节点为0号节点,后继节点为1号节点,前驱节点为-1号节点
  58. temp->pre->next = temp->next;//-1号节点的后继和1号节点相连
  59. temp->next = temp->pre;//1号节点的前驱和-1号节点相连
  60. size--;//长度-1
  61. return 0;//成功返回0
  62. }
  63. return -1;//无数据或者越界返回-1
  64. }
  65. int DCLink::modify(int pos, datatype data){//更改指定位置的数据
  66. if (size >= pos && pos > 0){//有数据并且没有越界才显示
  67. int count = 1;//计数
  68. struct dclink *temp = head;
  69. while (pos != count){
  70. temp = temp->next;
  71. count++;
  72. }
  73. temp->data = data;//更新
  74. return 0;
  75. }
  76. return -1;//无数据或者越界返回-1
  77. }
  78. int DCLink::insert(int pos, datatype data){//在指定位置插入数据
  79. if (0 == size && 1 == pos){
  80. this->add(data);//直接调用add函数
  81. return 0;
  82. }
  83. if (size >= pos && pos > 0){//有数据并且没有越界才显示
  84. int count = 1;//计数
  85. struct dclink *dcl = new struct dclink[1];
  86. dcl->data = data;
  87. struct dclink *temp = head;
  88. while (pos != count){
  89. temp = temp->next;//直到到达指定的位置
  90. count++;
  91. }//先到达指定位置
  92. //分情况是因为如果插入到第一个节点会改变head的状态
  93. if (size == pos){
  94. if (1 == size){//只有一个节点的时候
  95. head = dcl;//当前结点成为头结点
  96. head->next = temp;//新结点的后继和旧头结点相连
  97. temp->pre = head;//旧头结点的前驱和新结点相连
  98. head->pre = temp;//新结点的前驱和旧头结点相连
  99. temp->next = head;//旧头结点的后继和新结点相连
  100. }else{//插入到尾结点的前面
  101. temp->pre->next = dcl;
  102. dcl->pre = temp->pre;
  103. dcl->next = temp;
  104. temp->pre = dcl;
  105. }
  106. size++;
  107. return 0;
  108. }else{
  109. if (1 == pos){//插入到第一个位置
  110. head = dcl;//当前结点成为头结点
  111. head->next = temp;//新结点的后继和旧头结点相连
  112. temp->pre = head;//旧头结点的前驱和新结点相连
  113. head->pre = temp->pre;//新结点的前驱和旧头结点相连
  114. temp->pre->pre = head;//旧头结点的后继和新结点相连
  115. }else {//插入到中间的其它位置
  116. temp->pre->next = dcl;
  117. dcl->pre = temp->pre;
  118. dcl->next = temp;
  119. temp->pre = dcl;
  120. }
  121. size++;
  122. return 0;
  123. }
  124. }
  125. return -1;//越界返回-1
  126. }
  127. datatype DCLink::getData(int pos)const{//获得指定位置的数据
  128. if (size >= pos && pos > 0){//有数据并且没有越界才显示
  129. int count = 1;//计数
  130. struct dclink *temp = head;
  131. while (pos != count){
  132. temp = temp->next;//比插入和删除简单很多
  133. count++;//+1,第一次写的时候忘了+1,然后就固执地认为getData肯定没问题
  134. //可bug就在这里
  135. }
  136. return temp->data;
  137. }
  138. return -1;//无数据或者越界返回-1
  139. }
  140. void DCLink::sort()const{//排序
  141. if (1 < size){
  142. //快速排序
  143. int i = 1;
  144. int j = 0;
  145. struct dclink *ohead = head;
  146. while (size != i){//循环size - 1次
  147. j = 0;//重置
  148. struct dclink *temp = ohead;//辅助指针
  149. while (j != size - i){
  150. if (ohead->data > temp->next->data){//交换排序
  151. ohead->data += temp->next->data;
  152. temp->next->data = ohead->data - temp->next->data;
  153. ohead->data -= temp->next->data;
  154. }
  155. temp = temp->next;//移动
  156. j++;
  157. }
  158. ohead = ohead->next;//前面j个数据已经排好
  159. i++;
  160. }
  161. }
  162. }
  163. int DCLink::rePrint()const{//打印链表
  164. if (NULL != head){//链表非空
  165. struct dclink *temp = head;
  166. int count = 0;//计数
  167. while (size != count){
  168. temp = temp->pre;
  169. std::cout<<temp->data<<std::endl;
  170. count++;
  171. }
  172. return 0;
  173. }
  174. return -1;//空表返回-1
  175. }
  176. int DCLink::print()const{//打印链表
  177. if (NULL != head){//链表非空
  178. struct dclink *temp = head;
  179. int count = 0;//计数
  180. while (size != count){
  181. std::cout<<temp->data<<"  ";
  182. temp = temp->next;
  183. count++;
  184. }
  185. return 0;
  186. }
  187. return -1;//空表返回-1
  188. }
  189. int DCLink::getLength()const{
  190. return size;
  191. }//得到链表的长度
  192. //destructor
  193. DCLink::~DCLink()
  194. {
  195. while (0 != size){//用size来控制析构的次数
  196. struct dclink *temp = head;//辅助指针
  197. head->pre->next = head->next;//让head的前一个节点指向它的后一个节点
  198. head = head->next;//head后移动一个节点
  199. head->pre = temp->pre;//head还是指向前一个节点
  200. delete []temp;
  201. size--;
  202. }
  203. }
  204. int main(void){
  205. DCLink dcl;
  206. for (int i = 100; i > 0; i--)
  207. dcl.add(i);
  208. dcl.print();
  209. std::cout<<std::endl;
  210. dcl.sort();
  211. dcl.print();
  212. dcl.modify(1,10);
  213. dcl.modify(5,44);
  214. dcl.modify(3,33);
  215. dcl.deleteData(5);
  216. dcl.deleteData(1);
  217. dcl.deleteData(3);
  218. dcl.deleteData(6);
  219. dcl.add(5);
  220. for (i = 1; i < 7; i++)
  221. std::cout<<dcl.getData(i)<<std::endl;
  222. std::cout<<"the sizeof DCLink is "<<dcl.getLength()<<std::endl;
  223. dcl.print();
  224. return 0;
  225. }
时间: 2024-08-24 12:18:58

双向循环链表的相关文章

第33课 双向循环链表的实现

1. DTLib中双向链表的设计思路 (1)数据结点之间在逻辑上构成双向循环,这有别于Linux内核链表的实现. (2)头结点仅用于结点的定位,而Linux内核链表是将头结点作为循环的一部分. 2. 实现思路 (1)通过模板定义DualCircleList类,继承自DualLinkList类 (2)在DualCircleList内部使用Linux内核链表进行实现(另类实现) (3)使用struct list_head定义DualCircleList的头结点 (4)特殊处理:循环遍历时忽略头结点

双向循环链表 初始化 插入 删除

#include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR -1 #define TRUE 1 #define FALSE -1 #define NULL 0 #define OVERFLOW -2 #define ElemType int #define Status int typedef int ElemType typedef int Status #define LEN sizeof(DuLNode)

算法导论13:双向循环链表 2016.1.13

今天这个又打了很长时间,本来觉得数据结构就是那样,不过是一种思维,但是实际上真正自己打和想象中差距还是很大,需要考虑到各种细节. 今天这个问题有一个比较有意思的应用,就是“约瑟夫环问题”. 具体可以参见百度百科: http://baike.baidu.com/link?url=poA1Aanlptc6yzP1puYhSw_0RQjRAplhPfHwk6eoiqMNxw6WigCEbexxZ8a9SUbrMGokpPbKNzVYw308xjeEw_ 读完问题就可以发现,这个问题用链表就是一个很完美

C++__双向循环链表(练习)

双向循环链表 link.h #ifndef LINK_H_ #define LINK_H_ #define HEADER 0 #define TAIL -1 typedef int data_type; enum LINK_OP { LINK_ERR = -1, LINK_OK }; class LINK { private: LINK *last; data_type data; LINK *next; public: LINK(); LINK(data_type data); virtual

c语言编程之双向循环链表

双向循环链表就是形成两个环,注意每个环的首尾相连基本就可以了. 程序中采用尾插法进行添加节点. 1 #include<stdio.h> 2 #include<stdlib.h> 3 #define element int 4 typedef struct Node{ 5 element data; 6 struct Node *next; 7 struct Node *prior; 8 }*pNode; 9 10 //build a new double loop list 11

线性表.04.链式存储结构(双向循环链表)

以下是用双向循环链表实现的线性表 #include <stdio.h> #include <stdlib.h> #include <time.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 typedef int ElemType;//ElemType这里假设为int,可以根据需要进行更改 typedef int Status;//Status是函数的类型,其值是函数结果状态代码,如OK等 t

小猪的数据结构辅助教程——2.7 线性表中的双向循环链表

小猪的数据结构辅助教程--2.7 线性表中的双向循环链表 标签(空格分隔): 数据结构 本节学习路线图与学习要点 学习要点: 1.了解引入双向循环链表的原因 2.熟悉双向循环链表的特点以及存储结构 3.掌握双向循环链表的一些基本操作的实现逻辑 4.掌握逆序输出双向循环链表元素逻辑 1.双向循环链表的引入 2.双向循环链表的存储结构 双向循环链表的特点: 上面也说了,空间换时间,比起循环链表只是多了一个指向前驱的指针 特点的话: 判断空表:L ->next = L -> prior = L; 存

C++双向循环链表实现

双向循环链表C++实现 1.单链表: 结构图: 2.双向链表: 3.双向循环链表: 对于本程序中,则是给定一个_head  头结点,而不是指针,因为这样更加方便避免一些空判断问题 /* 版权信息:狼 文件名称:BidCirList.h 文件标识: 文件摘要: 利用C++实现简单的双向链表功能.增,删,查,改 //太烦了..我直接给个 带头结点的 表 //swap 移花接木已经是个给力的方法..just try 当前版本:1.1 作 者:狼 完成时间:2015-12-13 */ #ifndef _

C++双向循环链表

DuLink: #include<iostream> using namespace std; typedef int elemType; typedef struct DulNode { elemType data; DulNode *prior; DulNode *next; }*DuList; void InitList(DuList *L) { *L = new DulNode; (*L)->next = (*L)->prior = *L; } int LengthList