概要

线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列。本章先介绍线性表的几个基本组成部分:数组、单向链表、双向链表。

数组

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

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

img

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

单向链表

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

单链表的示意图如下:
img

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

单链表删除节点

img

删除”节点30”

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

删除之后:”节点20” 的后继节点为”节点40”。

单链表添加节点

img

在”节点10”与”节点20”之间添加”节点15”

添加之前:”节点10” 的后继节点为”节点20”。

添加之后:”节点10” 的后继节点为”节点15”,而”节点15” 的后继节点为”节点20”。

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

双向链表

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

双链表的示意图如下:

img

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

双链表删除节点

img

删除”节点30”

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

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

双链表添加节点

img

在”节点10”与”节点20”之间添加”节点15”

添加之前:”节点10”的后继节点为”节点20”,”节点20” 的前继节点为”节点10”。

添加之后:”节点10”的后继节点为”节点15”,”节点15” 的前继节点为”节点10”。”节点15”的后继节点为”节点20”,”节点20” 的前继节点为”节点15”。

双链表的Java实现

  1. /**
  2. * Java 实现的双向链表。
  3. * 注:java自带的集合包中有实现双向链表,路径是:java.util.LinkedList
  4. *
  5. * @author skywang
  6. * @date 2013/11/07
  7. */
  8. public class DoubleLink<T> {
  9. // 表头
  10. private DNode<T> mHead;
  11. // 节点个数
  12. private int mCount;
  13. // 双向链表“节点”对应的结构体
  14. private class DNode<T> {
  15. public DNode prev;
  16. public DNode next;
  17. public T value;
  18. public DNode(T value, DNode prev, DNode next) {
  19. this.value = value;
  20. this.prev = prev;
  21. this.next = next;
  22. }
  23. }
  24. // 构造函数
  25. public DoubleLink() {
  26. // 创建“表头”。注意:表头没有存储数据!
  27. mHead = new DNode<T>(null, null, null);
  28. mHead.prev = mHead.next = mHead;
  29. // 初始化“节点个数”为0
  30. mCount = 0;
  31. }
  32. // 返回节点数目
  33. public int size() {
  34. return mCount;
  35. }
  36. // 返回链表是否为空
  37. public boolean isEmpty() {
  38. return mCount==0;
  39. }
  40. // 获取第index位置的节点
  41. private DNode<T> getNode(int index) {
  42. if (index<0 || index>=mCount)
  43. throw new IndexOutOfBoundsException();
  44. // 正向查找
  45. if (index <= mCount/2) {
  46. DNode<T> node = mHead.next;
  47. for (int i=0; i<index; i++)
  48. node = node.next;
  49. return node;
  50. }
  51. // 反向查找
  52. DNode<T> rnode = mHead.prev;
  53. int rindex = mCount - index -1;
  54. for (int j=0; j<rindex; j++)
  55. rnode = rnode.prev;
  56. return rnode;
  57. }
  58. // 获取第index位置的节点的值
  59. public T get(int index) {
  60. return getNode(index).value;
  61. }
  62. // 获取第1个节点的值
  63. public T getFirst() {
  64. return getNode(0).value;
  65. }
  66. // 获取最后一个节点的值
  67. public T getLast() {
  68. return getNode(mCount-1).value;
  69. }
  70. // 将节点插入到第index位置之前
  71. public void insert(int index, T t) {
  72. if (index==0) {
  73. DNode<T> node = new DNode<T>(t, mHead, mHead.next);
  74. mHead.next.prev = node;
  75. mHead.next = node;
  76. mCount++;
  77. return ;
  78. }
  79. DNode<T> inode = getNode(index);
  80. DNode<T> tnode = new DNode<T>(t, inode.prev, inode);
  81. inode.prev.next = tnode;
  82. inode.prev = tnode;
  83. mCount++;
  84. return ;
  85. }
  86. // 将节点插入第一个节点处。
  87. public void insertFirst(T t) {
  88. insert(0, t);
  89. }
  90. // 将节点追加到链表的末尾
  91. public void appendLast(T t) {
  92. DNode<T> node = new DNode<T>(t, mHead.prev, mHead);
  93. mHead.prev.next = node;
  94. mHead.prev = node;
  95. mCount++;
  96. }
  97. // 删除index位置的节点
  98. public void del(int index) {
  99. DNode<T> inode = getNode(index);
  100. inode.prev.next = inode.next;
  101. inode.next.prev = inode.prev;
  102. inode = null;
  103. mCount--;
  104. }
  105. // 删除第一个节点
  106. public void deleteFirst() {
  107. del(0);
  108. }
  109. // 删除最后一个节点
  110. public void deleteLast() {
  111. del(mCount-1);
  112. }
  113. }