• 简单模拟单/双链表实现 LinkedList作业


    接口

    定义MyLink接口,定义抽象方法

    1. package mylinkedlist;
    2. public interface MyLink{
    3. //返回链表的长度
    4. int size();
    5. //判断链表是否为空
    6. boolean isEmpty();
    7. //默认在链表尾部添加元素
    8. boolean add(E e);
    9. //添加到链表第一个
    10. boolean addFirst(E e);
    11. //删除链表中的某个元素
    12. boolean remove(E o);
    13. //清空链表
    14. void clear();
    15. //在链表的某个位置添加元素
    16. void add(int index, E element);
    17. //删除链表中某个位置的元素
    18. boolean remove(int index);
    19. //返回链表中某个位置的元素
    20. E get(int index);
    21. //将链表中某个位置的元素替换为新元素
    22. boolean set(int index, E element);
    23. //查找链表中的某个元素
    24. int indexOf(Object o);
    25. //返回链表的字符串表示
    26. String toString();
    27. }

    单链表实现

    1、定义属性,节点类和构造方法

    实现MyLink接口,定义一个单链表节点内部类,和私有属性。(定义为私有,只向外部暴露方法即可)带头节点head和尾节点last。

    1. public class MySingleLinkedList implements MyLink{
    2. int size = 0;
    3. private MyNode head;
    4. private MyNode last;
    5. private class MyNode{
    6. E item;
    7. MyNode next;
    8. public MyNode(E element, MyNode next) {
    9. this.item = element;
    10. this.next = next;
    11. }
    12. }
    13. public MySingleLinkedList() {
    14. head = new MyNode<>(null,null);
    15. head.next = last;
    16. }
    17. }

    2、重写抽象方法

    1. @Override
    2. public int size() {
    3. return size;
    4. }
    5. @Override
    6. public boolean isEmpty() {
    7. return head.next == last;
    8. }
    9. //添加到链表尾部
    10. @Override
    11. public boolean add(Object o) {
    12. MyNode preMyNode = head;
    13. MyNode newNode = new MyNode(o,last);
    14. while (preMyNode.next != last){
    15. preMyNode = preMyNode.next;
    16. }
    17. preMyNode.next = newNode;
    18. size++;
    19. return true;
    20. }
    21. @Override
    22. public boolean addFirst(Object o) {
    23. MyNode nextMyNode = head.next;
    24. MyNode newNode = new MyNode(o,nextMyNode);
    25. head.next = newNode;
    26. size++;
    27. return true;
    28. }
    29. @Override
    30. public boolean remove(Object o) {
    31. MyNode a = head;
    32. MyNode b = a.next;
    33. if(indexOf(o) == -1){
    34. return false;
    35. }else{
    36. for(;b != last;a = a.next){
    37. if(b.item.equals(o)){
    38. break;
    39. }
    40. }
    41. a.next = b.next;
    42. size--;
    43. return true;
    44. }
    45. }
    46. @Override
    47. public void clear() {
    48. head.next = last;
    49. size = 0;
    50. }
    51. //添加到链表的某个位置
    52. @Override
    53. public void add(int index, Object element) {
    54. if (index < 0 || index > size) {
    55. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: "+index+", Size: "+size);
    56. } else if (index == size-1) {
    57. add(element);
    58. } else if (index ==0) {
    59. addFirst(element);
    60. } else {
    61. MyNode preMyNode = head;
    62. for (int i = 0; i < index; i++) {
    63. preMyNode = preMyNode.next;
    64. }
    65. MyNode nextMyNode = preMyNode.next;
    66. MyNode newNode = new MyNode(element, nextMyNode);
    67. preMyNode.next = newNode;
    68. size++;
    69. }
    70. }
    71. @Override
    72. public boolean remove(int index) {
    73. if (index < 0 || index >= size) {
    74. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: " + index + ", Size: " + size);
    75. }else {
    76. MyNode preMyNode = head;
    77. for (int i = 0; i < index; i++) {
    78. preMyNode = preMyNode.next;
    79. }
    80. MyNode nextMyNode = preMyNode.next.next;
    81. preMyNode.next = nextMyNode;
    82. size--;
    83. return true;
    84. }
    85. }
    86. @Override
    87. public Object get(int index) {
    88. if (index < 0 || index >= size) {
    89. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: "+index+", Size: "+size);
    90. }else {
    91. MyNode preMyNode = head.next;
    92. for (int i = 0; i < index; i++) {
    93. preMyNode = preMyNode.next;
    94. }
    95. return preMyNode.item;
    96. }
    97. }
    98. @Override
    99. public boolean set(int index, Object element) {
    100. if (index < 0 || index >= size) {
    101. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: "+index+", Size: "+size);
    102. }else {
    103. MyNode preMyNode = head.next;
    104. for (int i = 0; i < index; i++) {
    105. preMyNode = preMyNode.next;
    106. }
    107. preMyNode.item = (E) element;
    108. return true;
    109. }
    110. }
    111. @Override
    112. public int indexOf(Object o) {
    113. MyNode preMyNode = head.next;
    114. for (int i = 0; i < size; i++) {
    115. if (preMyNode.item.equals(o)) {
    116. return i;
    117. }
    118. preMyNode = preMyNode.next;
    119. }
    120. return -1;
    121. }
    122. @Override
    123. public String toString() {
    124. StringBuilder sb = new StringBuilder();
    125. sb.append("[");
    126. MyNode preMyNode = head.next;
    127. for (int i = 0; i < size; i++) {
    128. if (i == size - 1) {
    129. sb.append(preMyNode.item);
    130. } else {
    131. sb.append(preMyNode.item + ",");
    132. }
    133. preMyNode = preMyNode.next;
    134. }
    135. sb.append("]");
    136. return sb.toString();
    137. }

    单链表测试

    测试类

    1. package mylinkedlist;
    2. public class MySingleLinkedTest {
    3. public static void main(String[] args) {
    4. MySingleLinkedList mySingleLinkedList = new MySingleLinkedList<>();
    5. mySingleLinkedList.add(1);
    6. mySingleLinkedList.add(2);
    7. mySingleLinkedList.add(3);
    8. mySingleLinkedList.add(4);
    9. mySingleLinkedList.add(5);
    10. mySingleLinkedList.add(6);
    11. System.out.println("=======Test add(E e)=======");
    12. System.out.println(mySingleLinkedList.toString());
    13. System.out.println("=======Test size()=======");
    14. System.out.println("size="+mySingleLinkedList.size());
    15. System.out.println("=======Test remove(E o) index= 2 =======");
    16. mySingleLinkedList.remove(2);
    17. System.out.println(mySingleLinkedList.toString());
    18. System.out.println("=======Test add(int index, E element) index= 3 value = 66=======");
    19. mySingleLinkedList.add(3,66);
    20. System.out.println(mySingleLinkedList.toString());
    21. System.out.println("=======Test remove(int index) index= 3=======");
    22. mySingleLinkedList.remove(3);
    23. System.out.println(mySingleLinkedList.toString());
    24. System.out.println("=======Test get(int index) index= 3=======");
    25. System.out.println(mySingleLinkedList.get(3));
    26. System.out.println("=======Test set(int index, E element)index= 3 value = 88=======");
    27. mySingleLinkedList.set(3,88);
    28. System.out.println(mySingleLinkedList.toString());
    29. System.out.println("=======Test indexOf(Object o)index= 3 value = 88=======");
    30. System.out.println(mySingleLinkedList.indexOf(88));
    31. System.out.println("=======Test clear()=======");
    32. mySingleLinkedList.clear();
    33. System.out.println(mySingleLinkedList.toString());
    34. }
    35. }

    双链表实现

    1、定义属性,节点类和构造方法

    实现MyLink接口,定义一个双链表节点内部类,和私有属性。(定义为私有,只向外部暴露方法即可),带头节点first和尾节点last。

    1. public class MyLinkedList implements MyLink{
    2. //头节点和为节点不计入链表的长度,也不计入下标!!!!
    3. private int size = 0;
    4. private MyNode first;
    5. private MyNode last;
    6. public MyLinkedList() {
    7. first = new MyNode<>(null,null,null);
    8. last = new MyNode<>(first,null,null);
    9. first.next = last;
    10. }
    11. private class MyNode{
    12. E item;
    13. MyNode next;
    14. MyNode prev;
    15. public MyNode(MyNode prev, E element, MyNode next) {
    16. this.item = element;
    17. this.next = next;
    18. this.prev = prev;
    19. }
    20. }
    21. }

    2、重写抽象方法

    1. @Override
    2. public int size() {
    3. return size;
    4. }
    5. @Override
    6. public boolean isEmpty() {
    7. return first.next == last ;
    8. }
    9. @Override
    10. public boolean addFirst(E e) {
    11. MyNode nextMyNode = first.next;
    12. MyNode newNode = new MyNode(first,e,nextMyNode);
    13. first.next = newNode;
    14. nextMyNode.prev = newNode;
    15. size++;
    16. return true;
    17. }
    18. //添加到链表尾部
    19. @Override
    20. public boolean add(Object e) {
    21. MyNode preMyNode = last.prev;
    22. MyNode newNode = new MyNode(preMyNode,e,last);
    23. last.prev = newNode;
    24. preMyNode.next = newNode;
    25. size++;
    26. return true;
    27. }
    28. @Override
    29. public boolean remove(E o) {
    30. MyNode n = first;
    31. if(indexOf(o) == -1){
    32. return false;
    33. }else{
    34. for(int i = 0;i
    35. n = n.next;
    36. }
    37. MyNode preMyNode = n.prev;
    38. MyNode nextMyNode = n.next;
    39. preMyNode.next = nextMyNode;
    40. nextMyNode.prev = preMyNode;
    41. size--;
    42. return true;
    43. }
    44. }
    45. @Override
    46. public void clear() {
    47. first.next = last;
    48. last.prev = first;
    49. size = 0;
    50. }
    51. //添加到链表的某个位置
    52. @Override
    53. public void add(int index, E element) {
    54. if (index < 0 || index >= size) {
    55. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: " + index + ", Size: " + size);
    56. } else if (index == 0) {
    57. addFirst(element);
    58. } else if (index == size - 1) {
    59. add(element);
    60. } else if (index <= size / 2) {
    61. MyNode n = first;
    62. for (int i = 0; i <= index; i++) {
    63. n = n.next;
    64. }
    65. MyNode preMyNode = n.prev;
    66. MyNode newNode = new MyNode(preMyNode, element, n);
    67. preMyNode.next = newNode;
    68. n.prev = newNode;
    69. size++;
    70. } else if (index > size / 2) {
    71. MyNode n = last;
    72. for (int i = size; i > index; i--) {
    73. n = n.prev;
    74. }
    75. MyNode preMyNode = n.prev;
    76. MyNode newNode = new MyNode(preMyNode, element, n);
    77. preMyNode.next = newNode;
    78. n.prev = newNode;
    79. size++;
    80. }
    81. }
    82. @Override
    83. public boolean remove(int index) {
    84. if (index < 0 || index >= size) {
    85. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: " + index + ", Size: " + size);
    86. }else {
    87. MyNode n = first;
    88. for(int i = 0;i<=index;i++){
    89. n = n.next;
    90. }
    91. MyNode preMyNode = n.prev;
    92. MyNode nextMyNode = n.next;
    93. preMyNode.next = nextMyNode;
    94. nextMyNode.prev = preMyNode;
    95. size--;
    96. return true;
    97. }
    98. }
    99. @Override
    100. public E get(int index) {
    101. if (index < 0 || index >= size) {
    102. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: " + index + ", Size: " + size);
    103. }else if(index <= size/2){
    104. MyNode n = first;
    105. for(int i = 0;i<=index;i++){
    106. n = n.next;
    107. }
    108. return (E) n.item;
    109. } else if (index > size/2){
    110. MyNode n = last;
    111. for(int i = size;i>index;i--){
    112. n = n.prev;
    113. }
    114. return (E) n.item;
    115. }
    116. return null;
    117. }
    118. @Override
    119. public boolean set(int index, E element) {
    120. if (index < 0 || index >= size) {
    121. throw new IndexOutOfBoundsException("IndexOutOfBounds!!!! Index: " + index + ", Size: " + size);
    122. }else if(index <= size/2){
    123. MyNode n = first;
    124. for(int i = 0;i<=index;i++){
    125. n = n.next;
    126. }
    127. n.item = element;
    128. return true;
    129. } else if (index > size/2){
    130. MyNode n = last;
    131. for(int i = size;i>index;i--){
    132. n = n.prev;
    133. }
    134. n.item = element;
    135. return true;
    136. }
    137. return false;
    138. }
    139. @Override
    140. public int indexOf(Object o) {
    141. MyNode n = first.next;
    142. int index = 0;
    143. while(n.next != null){
    144. if(n.item.equals(o)){
    145. return index;
    146. }
    147. n = n.next;
    148. index++;
    149. }
    150. return -1;
    151. }
    152. @Override
    153. public String toString() {
    154. MyNode n = first.next;
    155. String str = "[";
    156. if(first.next == last){
    157. return "[]";
    158. }
    159. for (int i = 1;i
    160. str += n.item + ",";
    161. n = n.next;
    162. }
    163. str += n.item + "]";
    164. return str;
    165. }

    双链表测试

    测试类

    1. package mylinkedlist;
    2. import org.junit.jupiter.api.Test;
    3. public class MyLinnkedListTest {
    4. public static void main(String[] args) {
    5. MyLinkedList myLinnkedListTest = new MyLinkedList<>();
    6. myLinnkedListTest.add(1);
    7. myLinnkedListTest.add(2);
    8. myLinnkedListTest.add(3);
    9. myLinnkedListTest.add(4);
    10. myLinnkedListTest.add(5);
    11. myLinnkedListTest.add(6);
    12. System.out.println("=======Test add(E e)=======");
    13. System.out.println(myLinnkedListTest.toString());
    14. System.out.println("=======Test size()=======");
    15. System.out.println("size="+myLinnkedListTest.size());
    16. System.out.println("=======Test remove(E o) index= 2 =======");
    17. myLinnkedListTest.remove(2);
    18. System.out.println(myLinnkedListTest.toString());
    19. System.out.println("=======Test add(int index, E element) index= 3 value = 66=======");
    20. myLinnkedListTest.add(3,66);
    21. System.out.println(myLinnkedListTest.toString());
    22. System.out.println("=======Test remove(int index) index= 3=======");
    23. myLinnkedListTest.remove(3);
    24. System.out.println(myLinnkedListTest.toString());
    25. System.out.println("=======Test get(int index) index= 3=======");
    26. System.out.println(myLinnkedListTest.get(3));
    27. System.out.println("=======Test set(int index, E element)index= 3 value = 88=======");
    28. myLinnkedListTest.set(3,88);
    29. System.out.println(myLinnkedListTest.toString());
    30. System.out.println("=======Test indexOf(Object o)index= 3 value = 88=======");
    31. System.out.println(myLinnkedListTest.indexOf(88));
    32. System.out.println("=======Test clear()=======");
    33. myLinnkedListTest.clear();
    34. System.out.println(myLinnkedListTest.toString());
    35. }
    36. }

    作业

    作业一

    第一题

    有一个整数顺序表L。设计一个尽可能高效的算法删除其中所有值为负整数的元素(假设L中值为负整数的元素可能有多个),删除后元素的相对次序不改变。并给出算法的时间和空间复杂度。例如,L=(1,2,-1,-2,3,-3),删除后L=(1,2,3)。

    代码实现
    1. @Test
    2. public void workOne (){
    3. MyLinkedList integerMyLinkedList = new MyLinkedList<>();
    4. integerMyLinkedList.add(1);
    5. integerMyLinkedList.add(2);
    6. integerMyLinkedList.add(-1);
    7. integerMyLinkedList.add(-2);
    8. integerMyLinkedList.add(3);
    9. integerMyLinkedList.add(-3);
    10. System.out.println("=======before=======");
    11. System.out.println(integerMyLinkedList);
    12. System.out.println("=======after=======");
    13. System.out.println(deleteNegative(integerMyLinkedList));
    14. }
    15. public MyLinkedList deleteNegative(MyLinkedList integerMyLinkedList){
    16. MyLinkedList integerMyLinkedList1 = new MyLinkedList<>();
    17. for (int i = 0; i < integerMyLinkedList.size(); i++) {
    18. if (integerMyLinkedList.get(i) >= 0) {
    19. integerMyLinkedList1.add(integerMyLinkedList.get(i));
    20. }
    21. }
    22. return integerMyLinkedList1;
    23. }
    复杂度分析

    时间复杂度:add方法为O(1),get方法为O(n),所以整体为O(n^n)

    空间复杂度O(n)

    第二题

    有一个整数顺序表L。设计一个尽可能高效的算法删除表中值大于等于x且小于等于y的所有元素(x≤y),删除后元素的相对次序不改变。并给出算法的时间和空间复杂度。例如,L=(4,2,1,5,3,6,4),x=2,y=4,删除后L=(1,5,6)。

    代码实现
    1. @Test
    2. public void workTwo (){
    3. MyLinkedList integerMyLinkedList = new MyLinkedList<>();
    4. integerMyLinkedList.add(4);
    5. integerMyLinkedList.add(2);
    6. integerMyLinkedList.add(1);
    7. integerMyLinkedList.add(5);
    8. integerMyLinkedList.add(3);
    9. integerMyLinkedList.add(6);
    10. integerMyLinkedList.add(4);
    11. System.out.println("=======before=======");
    12. System.out.println(integerMyLinkedList);
    13. System.out.println("=======after=======");
    14. System.out.println(deleteOnCondition(integerMyLinkedList,2,4));
    15. }
    16. public MyLinkedList deleteOnCondition(MyLinkedList integerMyLinkedList,int min,int max){
    17. MyLinkedList integerMyLinkedList1 = new MyLinkedList<>();
    18. for (int i = 0; i < integerMyLinkedList.size(); i++) {
    19. if (integerMyLinkedList.get(i) < min || integerMyLinkedList.get(i) > max) {
    20. integerMyLinkedList1.add(integerMyLinkedList.get(i));
    21. }
    22. }
    23. return integerMyLinkedList1;
    24. }
    复杂度分析

    时间复杂度:get方法为O(n),所以整体为O(n^n)

    空间复杂度O(n)

    作业二

    第一题

    有一个整数单链表L,设计一个尽可能高效算法将所有负整数的元素移到其他元素的前面。例如,L=(1,2,-1,-2,3,-3,4),移动后L=(-1,-2,-3,1,2,3,4)。

    代码实现
    1. @Test
    2. public void workOne (){
    3. MySingleLinkedList integerMyLinkedList = new MySingleLinkedList<>();
    4. integerMyLinkedList.add(1);
    5. integerMyLinkedList.add(2);
    6. integerMyLinkedList.add(-1);
    7. integerMyLinkedList.add(-2);
    8. integerMyLinkedList.add(3);
    9. integerMyLinkedList.add(-3);
    10. integerMyLinkedList.add(4);
    11. System.out.println("=======before=======");
    12. System.out.println(integerMyLinkedList);
    13. System.out.println("=======after=======");
    14. System.out.println(moveNegativeFoward(integerMyLinkedList));
    15. }
    16. private MySingleLinkedList moveNegativeFoward(MySingleLinkedList integerMyLinkedList) {
    17. MySingleLinkedList mySingleLinkedList = new MySingleLinkedList();
    18. for (int i = 0; i < integerMyLinkedList.size(); i++) {
    19. if ((int)integerMyLinkedList.get(i) < 0) {
    20. mySingleLinkedList.addFirst(integerMyLinkedList.get(i));
    21. }else {
    22. mySingleLinkedList.add(integerMyLinkedList.get(i));
    23. }
    24. }
    25. return mySingleLinkedList;
    26. }
    复杂度分析

    时间复杂度:addFirst方法为O(1),add方法为O(n),get方法为O(n),所以整体为O(n^n)

    空间复杂度O(n)

    第二题

    有两个集合采用整数单链表A、B存储,设计一个算法求两个集合的差集C,C仍然用单链表存储。并给出算法的时间和空间复杂度。例如A=(1,3,2),B=(5,1,4,2),差集C=(3)。

    代码实现
    1. @Test
    2. public void workTwo (){
    3. MySingleLinkedList integerMyLinkedList1 = new MySingleLinkedList<>();
    4. MySingleLinkedList integerMyLinkedList2 = new MySingleLinkedList<>();
    5. integerMyLinkedList1.add(1);
    6. integerMyLinkedList1.add(3);
    7. integerMyLinkedList1.add(2);
    8. integerMyLinkedList2.add(5);
    9. integerMyLinkedList2.add(1);
    10. integerMyLinkedList2.add(4);
    11. integerMyLinkedList2.add(2);
    12. System.out.println("=======before=======");
    13. System.out.println(integerMyLinkedList1);
    14. System.out.println(integerMyLinkedList2);
    15. System.out.println("=======result=======");
    16. System.out.println(deferenceSet(integerMyLinkedList1,integerMyLinkedList2));
    17. }
    18. private MySingleLinkedList deferenceSet(MySingleLinkedList integerMyLinkedList1, MySingleLinkedList integerMyLinkedList2) {
    19. MySingleLinkedList mySingleLinkedList = new MySingleLinkedList();
    20. for (int i = 0;i < integerMyLinkedList1.size;i++){
    21. for (int j = 0;j < integerMyLinkedList2.size;j++) {
    22. if (integerMyLinkedList1.get(i) == integerMyLinkedList2.get(j)) {
    23. break;
    24. } else if (j == integerMyLinkedList2.size - 1) {
    25. mySingleLinkedList.add(integerMyLinkedList1.get(i));
    26. }
    27. }
    28. }
    29. return mySingleLinkedList;
    30. }
    复杂度分析

    时间复杂度:add方法为O(n),get方法为O(n),所以整体为O(n^n^n)

    空间复杂度O(n)

    仓库

    https://gitee.com/BenChuat/algorithm-exercise.git

  • 相关阅读:
    精英反向黄金正弦鲸鱼算法-附代码
    日均请求量1.6万亿次背后,DNSPod的秘密-国密DoH篇
    java学习之包
    数值常量如何转化为内存地址?
    第七章物理层
    网易数帆自主创新再获认可:轻舟微服务入选信创技术图谱
    计算机网络:帧中继的概念
    4.2.3 安装Windows操作系统步骤
    前端基础入门之JS的call、apply和argument
    嵌入式C语言自我修养《内存堆栈管理》学习笔记
  • 原文地址:https://blog.csdn.net/m0_73065928/article/details/133244898