(四)线性表 ---→ 链表 ---→ 单链表

女爷i 2021-12-10 04:05 513阅读 0赞

文章目录

    • 概念
    • 特点
    • 复杂度
    • `java` 代码实现

概念

摘抄自 维基百科

链表中最简单的一种是单向链表,它包含两个域,一个 信息域 和一个 指针域 。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。

在这里插入图片描述

  1. 一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接
  2. 一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。

单链表是链表最基本的结构

一般在在每个节点保存数据和到下一个节点的地址,在最后一个节点保存一个特殊的结束标记,另外在一个固定的位置保存指向第一个节点的指针,有的时候也会同时储存指向最后一个节点的指针。


特点

单向链表(又名单链表、线性链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过从头部开始,依序往下读取。


复杂度

  1. 插入、删除,复杂度都是 O(1) 级别
  2. 存、取 的复杂度都是 0(n) 级别

java 代码实现

  1. /* * listEmpty() 判断线性表是否为空,为空返回 true ,否则返回 false * clearList()将线性表清空,置为空表 * getElem(index)返回线性表中的第 index+1 元素 * setElem(index,elem) 设置线性表中角标为 index 的元素为 elem * getElemIndex(elem) 返回线性表中元素 elem 的下标 index ,返回 -1 代表线性表中没有该元素。 * insertElem(int index,elem) 在线性表的 index 下标处,插入元素 elem * delete(index) 删除并返回线性表中下标为 index 的元素 * length() 返回线性表的长度 * size() 返回线性表中元素的个数 */
  2. /** * @author yiaz * @date 2019/7/15 * @description 单链表 */
  3. public class SingleLinkedList<E> {
  4. /** * 是否是插入 */
  5. private static final boolean IS_INSERT = true;
  6. private int length;
  7. private Node head;
  8. /** * 链表节点 */
  9. private class Node {
  10. E elem;
  11. Node next;
  12. public Node() {
  13. elem = null;
  14. next = null;
  15. }
  16. }
  17. public SingleLinkedList() {
  18. // 初始化头结点
  19. head = new Node();
  20. length = 0;
  21. }
  22. public boolean listEmpty() {
  23. return length == 0;
  24. }
  25. public void clearList() {
  26. length = 0;
  27. head.next = null;
  28. }
  29. /** * getElem(index)返回线性表中的第 index+1 元素 */
  30. public E getElem(int index) {
  31. Node temp = head;
  32. for (int i = 0; i <= index; i++) {
  33. temp = temp.next;
  34. }
  35. return temp.elem;
  36. }
  37. /** * setElem(index,elem) 设置线性表中角标为 index 的元素为 elem */
  38. public E setElem(int index, E elem) {
  39. boolean flag = validateIndex(index, !IS_INSERT);
  40. if (!flag) {
  41. throw new RuntimeException("下标越界");
  42. }
  43. Node temp = head;
  44. for (int i = 0; i <= index; i++) {
  45. temp = temp.next;
  46. }
  47. E originalValue = temp.elem;
  48. temp.elem = elem;
  49. return originalValue;
  50. }
  51. /** * getElemIndex(elem) 返回线性表中元素 elem 的下标 index ,返回 -1 代表线性表中没有该元素。 */
  52. public int getElemIndex(E elem) {
  53. Node temp = head;
  54. int index = 0;
  55. while (temp.next != null) {
  56. temp = temp.next;
  57. if (temp.elem.equals(elem)) {
  58. return index;
  59. }
  60. index++;
  61. }
  62. return -1;
  63. }
  64. /** * insertElem(int index,elem) 在线性表的 index 下标处,插入元素 elem */
  65. public void insertElem(int index, E elem) {
  66. boolean flag = validateIndex(index, IS_INSERT);
  67. if (!flag) {
  68. throw new RuntimeException("角标越界");
  69. }
  70. if (elem == null) {
  71. throw new RuntimeException("不可以插入 null 对象");
  72. }
  73. Node temp = head;
  74. for (int i = 0; i < index; i++) {
  75. temp = temp.next;
  76. }
  77. Node node = new Node();
  78. node.elem = elem;
  79. node.next = temp.next;
  80. temp.next = node;
  81. length++;
  82. }
  83. /** * delete(index) 删除并返回线性表中下标为 index 的元素 */
  84. public E delete(int index) {
  85. boolean flag = validateIndex(index, !IS_INSERT);
  86. Node temp = head;
  87. for (int i = 0; i < index; i++) {
  88. temp = temp.next;
  89. }
  90. E elem = temp.next.elem;
  91. temp.next = temp.next.next;
  92. length--;
  93. return elem;
  94. }
  95. /** * length() 返回线性表的长度 */
  96. public int getLength() {
  97. return length;
  98. }
  99. /** * 验证 index 是否合法 * * @param index 角标 * @param flag true 表示插入、false 表示 删除、查询、更新 * @return true 代表 校验通过 */
  100. private boolean validateIndex(int index, boolean flag) {
  101. if (flag) {
  102. if (!(index >= 0 && index <= length)) {
  103. return false;
  104. }
  105. } else {
  106. if (!(index >= 0 && index < length)) {
  107. return false;
  108. }
  109. }
  110. return true;
  111. }
  112. }

Junit 测试代码

  1. import org.junit.Before;
  2. import org.junit.Test;
  3. import static org.hamcrest.CoreMatchers.is;
  4. import static org.junit.Assert.assertThat;
  5. /** * @author yiaz * @date 2019/7/16 * @description */
  6. public class SingleLinkedListTest {
  7. private SingleLinkedList<String> list;
  8. @Before
  9. public void setUp() throws Exception {
  10. // 初始化单链表
  11. list = new SingleLinkedList<>();
  12. }
  13. @Test
  14. public void listEmpty() throws Exception {
  15. assertThat(true, is(list.listEmpty()));
  16. list.insertElem(0, "first");
  17. assertThat(false, is(list.listEmpty()));
  18. }
  19. @Test
  20. public void clearList() throws Exception {
  21. list.insertElem(0, "first");
  22. assertThat(false, is(list.listEmpty()));
  23. list.clearList();
  24. assertThat(0, is(list.getLength()));
  25. }
  26. @Test
  27. public void getElem() throws Exception {
  28. list.insertElem(0, "first");
  29. list.insertElem(1, "secend");
  30. list.insertElem(2, "third");
  31. assertThat("secend", is(list.getElem(1)));
  32. }
  33. @Test(expected = RuntimeException.class)
  34. public void setElem() throws Exception {
  35. list.insertElem(0, "first");
  36. assertThat("first", is(list.getElem(0)));
  37. list.setElem(2, "sasa");
  38. list.setElem(0, "sasa");
  39. assertThat("sasa", is(list.getElem(0)));
  40. }
  41. @Test
  42. public void getElemIndex() throws Exception {
  43. list.insertElem(0, "first");
  44. list.insertElem(1, "1");
  45. list.insertElem(2, "2");
  46. assertThat(-1, is(list.getElemIndex("yiaz")));
  47. assertThat(0, is(list.getElemIndex("first")));
  48. assertThat(2, is(list.getElemIndex("2")));
  49. assertThat(1, is(list.getElemIndex("1")));
  50. }
  51. @Test(expected = RuntimeException.class)
  52. public void insertElem() throws Exception {
  53. assertThat(true, is(list.listEmpty()));
  54. list.insertElem(2, "haha");
  55. list.insertElem(0, "haha");
  56. assertThat(false, is(list.listEmpty()));
  57. }
  58. @Test
  59. public void delete() throws Exception {
  60. list.insertElem(0, "first");
  61. list.insertElem(1, "1");
  62. list.insertElem(2, "2");
  63. assertThat(3, is(list.getLength()));
  64. assertThat("1", is(list.delete(1)));
  65. assertThat("2", is(list.delete(1)));
  66. assertThat(1, is(list.getLength()));
  67. }
  68. @Test
  69. public void length() throws Exception {
  70. assertThat(0, is(list.getLength()));
  71. list.insertElem(0, "first");
  72. assertThat(1, is(list.getLength()));
  73. list.insertElem(1, "1");
  74. list.insertElem(2, "2");
  75. assertThat(3, is(list.getLength()));
  76. }
  77. }

发表评论

表情:
评论列表 (有 0 条评论,513人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线性

    线性表的链式存储结构 链式存储定义:为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息。 ![SouthEas

    相关 线性 — 双向

    循环链表:特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。从表中任一结点出发均可找到表中其他结点。 双向链表:特点是结点有两个指针域(一个指向直接前驱,一个指向

    相关 线性

    线性链表存储结构的特点:用一组任意的存储单元存储线性表的数据元素(存储单元可以是连续的,也可以是不连续的) 数据元素a与其直接后继a+1之间的逻辑关系,对数据元素a来说,除了