• 数组、单链表和双链表介绍以及双向链表的C/C++实现


    数组

    数组有上界和下界,数组的元素在上下界内是连续的。

    存储10,20,30,40,50的数组的示意图如下:


    数组的特点是:数据是连续的;随机访问速度快。
    数组中稍微复杂一点的是多维数组和动态数组。对于C语言而言,多维数组本质上也是通过一维数组实现的。至于动态数组,是指数组的容量能动态增长的数组;对于C语言而言,若要提供动态数组,需要手动实现;而对于C++而言,STL提供了Vector;对于Java而言,Collection集合中提供了ArrayList和Vector。

    单向链表

    单向链表(单链表)是链表的一种,它由节点组成,每个节点都包含下一个节点的指针。

    单链表的示意图如下:

    表头为空,表头的后继节点是"节点10"(数据为10的节点),"节点10"的后继节点是"节点20"(数据为10的节点),...

    单链表删除节点

    删除"节点30"
    删除之前:"节点20" 的后继节点为"节点30",而"节点30" 的后继节点为"节点40"。
    删除之后:"节点20" 的后继节点为"节点40"。

    单链表添加节点

    在"节点10"与"节点20"之间添加"节点15"
    添加之前:"节点10" 的后继节点为"节点20"。
    添加之后:"节点10" 的后继节点为"节点15",而"节点15" 的后继节点为"节点20"。

    单链表的特点是:节点的链接方向是单向的;相对于数组来说,单链表的的随机访问速度较慢,但是单链表删除/添加数据的效率很高。

    双向链表

    双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

    双链表的示意图如下:

    表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。

    双链表删除节点

    删除"节点30"
    删除之前:"节点20"的后继节点为"节点30","节点30" 的前继节点为"节点20"。"节点30"的后继节点为"节点40","节点40" 的前继节点为"节点30"。
    删除之后:"节点20"的后继节点为"节点40","节点40" 的前继节点为"节点20"。

    双链表添加节点

    在"节点10"与"节点20"之间添加"节点15"
    添加之前:"节点10"的后继节点为"节点20","节点20" 的前继节点为"节点10"。
    添加之后:"节点10"的后继节点为"节点15","节点15" 的前继节点为"节点10"。"节点15"的后继节点为"节点20","节点20" 的前继节点为"节点15"。

    下面介绍双链表的实现,分别介绍C/C++/Java三种实现。

    1. C实现双链表

    实现代码

    1. #include
    2. #include "double_link.h"
    3. void int_test()
    4. {
    5. int iarr[4] = {10, 20, 30, 40};
    6. printf("\n----%s----\n", __func__);
    7. create_dlink(); // 创建双向链表
    8. dlink_insert(0, &iarr[0]); // 向双向链表的表头插入数据
    9. dlink_insert(0, &iarr[1]); // 向双向链表的表头插入数据
    10. dlink_insert(0, &iarr[2]); // 向双向链表的表头插入数据
    11. printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 双向链表是否为空
    12. printf("dlink_size()=%d\n", dlink_size()); // 双向链表的大小
    13. // 打印双向链表中的全部数据
    14. int i;
    15. int *p;
    16. int sz = dlink_size();
    17. for (i=0; i
    18. {
    19. p = (int *)dlink_get(i);
    20. printf("dlink_get(%d)=%d\n", i, *p);
    21. }
    22. destroy_dlink();
    23. }
    24. void string_test()
    25. {
    26. char* sarr[4] = {"ten", "twenty", "thirty", "forty"};
    27. printf("\n----%s----\n", __func__);
    28. create_dlink(); // 创建双向链表
    29. dlink_insert(0, sarr[0]); // 向双向链表的表头插入数据
    30. dlink_insert(0, sarr[1]); // 向双向链表的表头插入数据
    31. dlink_insert(0, sarr[2]); // 向双向链表的表头插入数据
    32. printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 双向链表是否为空
    33. printf("dlink_size()=%d\n", dlink_size()); // 双向链表的大小
    34. // 打印双向链表中的全部数据
    35. int i;
    36. char *p;
    37. int sz = dlink_size();
    38. for (i=0; i
    39. {
    40. p = (char *)dlink_get(i);
    41. printf("dlink_get(%d)=%s\n", i, p);
    42. }
    43. destroy_dlink();
    44. }
    45. typedef struct tag_stu
    46. {
    47. int id;
    48. char name[20];
    49. }stu;
    50. static stu arr_stu[] =
    51. {
    52. {10, "sky"},
    53. {20, "jody"},
    54. {30, "vic"},
    55. {40, "dan"},
    56. };
    57. #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) )
    58. void object_test()
    59. {
    60. printf("\n----%s----\n", __func__);
    61. create_dlink(); // 创建双向链表
    62. dlink_insert(0, &arr_stu[0]); // 向双向链表的表头插入数据
    63. dlink_insert(0, &arr_stu[1]); // 向双向链表的表头插入数据
    64. dlink_insert(0, &arr_stu[2]); // 向双向链表的表头插入数据
    65. printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 双向链表是否为空
    66. printf("dlink_size()=%d\n", dlink_size()); // 双向链表的大小
    67. // 打印双向链表中的全部数据
    68. int i;
    69. int sz = dlink_size();
    70. stu *p;
    71. for (i=0; i
    72. {
    73. p = (stu *)dlink_get(i);
    74. printf("dlink_get(%d)=[%d, %s]\n", i, p->id, p->name);
    75. }
    76. destroy_dlink();
    77. }
    78. int main()
    79. {
    80. int_test(); // 演示向双向链表操作“int数据”。
    81. string_test(); // 演示向双向链表操作“字符串数据”。
    82. object_test(); // 演示向双向链表操作“对象”。
    83. return 0;
    84. }

    2c++实现双链表

    实现代码

     

    1. #ifndef DOUBLE_LINK_HXX
    2. #define DOUBLE_LINK_HXX
    3. #include
    4. using namespace std;
    5. template<class T>
    6. struct DNode
    7. {
    8. public:
    9. T value;
    10. DNode *prev;
    11. DNode *next;
    12. public:
    13. DNode() { }
    14. DNode(T t, DNode *prev, DNode *next) {
    15. this->value = t;
    16. this->prev = prev;
    17. this->next = next;
    18. }
    19. };
    20. template<class T>
    21. class DoubleLink
    22. {
    23. public:
    24. DoubleLink();
    25. ~DoubleLink();
    26. int size();
    27. int is_empty();
    28. T get(int index);
    29. T get_first();
    30. T get_last();
    31. int insert(int index, T t);
    32. int insert_first(T t);
    33. int append_last(T t);
    34. int del(int index);
    35. int delete_first();
    36. int delete_last();
    37. private:
    38. int count;
    39. DNode *phead;
    40. private:
    41. DNode *get_node(int index);
    42. };
    43. template<class T>
    44. DoubleLink::DoubleLink() : count(0)
    45. {
    46. // 创建“表头”。注意:表头没有存储数据!
    47. phead = new DNode();
    48. phead->prev = phead->next = phead;
    49. // 设置链表计数为0
    50. //count = 0;
    51. }
    52. // 析构函数
    53. template<class T>
    54. DoubleLink::~DoubleLink()
    55. {
    56. // 删除所有的节点
    57. DNode* ptmp;
    58. DNode* pnode = phead->next;
    59. while (pnode != phead)
    60. {
    61. ptmp = pnode;
    62. pnode=pnode->next;
    63. delete ptmp;
    64. }
    65. // 删除"表头"
    66. delete phead;
    67. phead = NULL;
    68. }
    69. // 返回节点数目
    70. template<class T>
    71. int DoubleLink::size()
    72. {
    73. return count;
    74. }
    75. // 返回链表是否为空
    76. template<class T>
    77. int DoubleLink::is_empty()
    78. {
    79. return count==0;
    80. }
    81. // 获取第index位置的节点
    82. template<class T>
    83. DNode* DoubleLink::get_node(int index)
    84. {
    85. // 判断参数有效性
    86. if (index<0 || index>=count)
    87. {
    88. cout << "get node failed! the index in out of bound!" << endl;
    89. return NULL;
    90. }
    91. // 正向查找
    92. if (index <= count/2)
    93. {
    94. int i=0;
    95. DNode* pindex = phead->next;
    96. while (i++ < index) {
    97. pindex = pindex->next;
    98. }
    99. return pindex;
    100. }
    101. // 反向查找
    102. int j=0;
    103. int rindex = count - index -1;
    104. DNode* prindex = phead->prev;
    105. while (j++ < rindex) {
    106. prindex = prindex->prev;
    107. }
    108. return prindex;
    109. }
    110. // 获取第index位置的节点的值
    111. template<class T>
    112. T DoubleLink::get(int index)
    113. {
    114. return get_node(index)->value;
    115. }
    116. // 获取第1个节点的值
    117. template<class T>
    118. T DoubleLink::get_first()
    119. {
    120. return get_node(0)->value;
    121. }
    122. // 获取最后一个节点的值
    123. template<class T>
    124. T DoubleLink::get_last()
    125. {
    126. return get_node(count-1)->value;
    127. }
    128. // 将节点插入到第index位置之前
    129. template<class T>
    130. int DoubleLink::insert(int index, T t)
    131. {
    132. if (index == 0)
    133. return insert_first(t);
    134. DNode* pindex = get_node(index);
    135. DNode* pnode = new DNode(t, pindex->prev, pindex);
    136. pindex->prev->next = pnode;
    137. pindex->prev = pnode;
    138. count++;
    139. return 0;
    140. }
    141. // 将节点插入第一个节点处。
    142. template<class T>
    143. int DoubleLink::insert_first(T t)
    144. {
    145. DNode* pnode = new DNode(t, phead, phead->next);
    146. phead->next->prev = pnode;
    147. phead->next = pnode;
    148. count++;
    149. return 0;
    150. }
    151. // 将节点追加到链表的末尾
    152. template<class T>
    153. int DoubleLink::append_last(T t)
    154. {
    155. DNode* pnode = new DNode(t, phead->prev, phead);
    156. phead->prev->next = pnode;
    157. phead->prev = pnode;
    158. count++;
    159. return 0;
    160. }
    161. // 删除index位置的节点
    162. template<class T>
    163. int DoubleLink::del(int index)
    164. {
    165. DNode* pindex = get_node(index);
    166. pindex->next->prev = pindex->prev;
    167. pindex->prev->next = pindex->next;
    168. delete pindex;
    169. count--;
    170. return 0;
    171. }
    172. // 删除第一个节点
    173. template<class T>
    174. int DoubleLink::delete_first()
    175. {
    176. return del(0);
    177. }
    178. // 删除最后一个节点
    179. template<class T>
    180. int DoubleLink::delete_last()
    181. {
    182. return del(count-1);
    183. }
    184. #endif

  • 相关阅读:
    java计算机毕业设计基于安卓Android的订餐系统APP
    Java中枚举类(enum)的实用小技巧
    光储直流微电网MATLAB/Simulink仿真
    手写rollup
    第7讲:v-bind属性绑定,v-model双向绑定,v-on事件监听使用
    搞懂fastjson 对泛型的反序列化原理
    商品推荐_后端的一些操作
    可靠的自托管「GitHub 热点速览 v.22.37」
    【NoSQL】redis之持久化(RDB、AOF)
    HTML总结
  • 原文地址:https://blog.csdn.net/SB202211/article/details/125865336