当前位置:   article > 正文

双向链表(LinkedList)_linkelist的底层是双向链表吗

linkelist的底层是双向链表吗
什么是链表?
链表是一系列结点组成,这些结点不必再内存中相连。每一个结点均含有表元素和到包含该元素后继元素的结点的链。我们称该链为next链,最后一个结点的next链为null
链表的结构如下图所示


链表的删除和插入
删除:

插入:

从上面的图可以看出,向链表中插入或者从链表中删除某一项元素,不需要移动很多项,只需要改变常数个结点的next链即可。
所以链表的删除和添加元素操作真正耗时的部分是:找到指定索引的结点。这需要我们从第一个结点开始遍历,find(i)的时间为O(i)


双向链表
如果我们在表的第一项处插入或者删除元素该操作花费的时间为常数,但是如果我们需要在最后一项插入或者删除元素这是一个花费时间为O(N)的操作。
我们可以用双向链表来解决这个问题。双向链表的每一个结点都有一条指向其后继结点的next链和一条指向其前结点的pre链。双向链表既可以从第一项开始遍历也可以从最后一项开始往前遍历,双向链表可以用下图表示


双向链表的插入和删除
插入:

删除:

下面给出双链表的具体实现代码

  1. import java.util.Iterator;
  2. public class MyLinkedList<T> implements Iterable<T>
  3. {
  4. private int size;
  5. private Node<T> beginMarker;
  6. private Node<T> endMarker;
  7. private static class Node<T>
  8. {
  9. public T data;
  10. public Node<T> pre;
  11. public Node<T> next;
  12. public Node(T data,Node<T> pre,Node<T> next)
  13. {
  14. this.data=data;
  15. this.pre=pre;
  16. this.next=next;
  17. }
  18. }
  19. public MyLinkedList()
  20. {
  21. clear();
  22. }
  23. public void clear()
  24. {
  25. beginMarker=new Node<T>(null,null,null);
  26. endMarker=new Node<T>(null,beginMarker,null);
  27. beginMarker.next=endMarker;
  28. size=0;
  29. }
  30. public int size()
  31. {
  32. return size;
  33. }
  34. public boolean isEmpty()
  35. {
  36. return size==0;
  37. }
  38. public void add(T x)
  39. {
  40. add(size(), x);
  41. }
  42. public void add(int idx,T x)
  43. {
  44. addBefore(getNode(idx), x);
  45. }
  46. public void remove(int idx)
  47. {
  48. Node<T> p=getNode(idx);
  49. p.pre.next=p.next;
  50. p.next.pre=p.pre;
  51. size--;
  52. }
  53. public T get(int idx)
  54. {
  55. if(idx<0 || idx>=size())
  56. {
  57. throw new IndexOutOfBoundsException();
  58. }
  59. return getNode(idx).data;
  60. }
  61. public void set(int idx,T x)
  62. {
  63. getNode(idx).data=x;
  64. }
  65. private void addBefore(Node<T> p,T x)
  66. {
  67. Node<T> newNode=new Node<T>(x, p.pre, p);
  68. p.pre.next=newNode;
  69. p.pre=newNode;
  70. size++;
  71. }
  72. private Node<T> getNode(int idx)//耗时操作
  73. {
  74. Node<T> p;
  75. if(idx<0 || idx>size())
  76. {
  77. throw new IndexOutOfBoundsException();
  78. }
  79. if(idx<size/2)
  80. {
  81. p=beginMarker;
  82. for (int i = 0; i <= idx; i++)
  83. {
  84. p=p.next;
  85. }
  86. }
  87. else
  88. {
  89. p=endMarker;
  90. for (int i = size(); i >idx; i--)
  91. {
  92. p=p.pre;
  93. }
  94. }
  95. return p;
  96. }
  97. //下面的代码是为了能够遍历该链表
  98. @Override
  99. public Iterator<T> iterator()
  100. {
  101. return new MyIterator();
  102. }
  103. private class MyIterator implements Iterator<T>{
  104. private Node<T> current=beginMarker.next;
  105. @Override
  106. public boolean hasNext()
  107. {
  108. return current!=endMarker;
  109. }
  110. @Override
  111. public T next()
  112. {
  113. T nextItem=current.data;
  114. current=current.next;
  115. return nextItem;
  116. }
  117. @Override
  118. public void remove()
  119. {
  120. //我这里只需要遍历功能,remove不需要重写
  121. }
  122. }
  123. }
测试代码:
  1. public class Test2
  2. {
  3. public static void main(String[] args)
  4. {
  5. MyLinkedList<Integer> list=new MyLinkedList<Integer>();
  6. for (int i = 0; i < 10; i++)
  7. {
  8. list.add(i*i);
  9. }
  10. for(Integer data : list)
  11. {
  12. System.out.print(data+" ");
  13. }
  14. list.remove(6);
  15. System.out.println();
  16. for(Integer data : list)
  17. {
  18. System.out.print(data+" ");
  19. }
  20. list.set(7, 2015);
  21. System.out.println();
  22. for(Integer data : list)
  23. {
  24. System.out.print(data+" ");
  25. }
  26. System.out.println();
  27. System.out.println(list.get(6));
  28. }
  29. }
输出:
0 1 4 9 16 25 36 49 64 81 
0 1 4 9 16 25 49 64 81 
0 1 4 9 16 25 49 2015 81 
49


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/966337
推荐阅读
相关标签
  

闽ICP备14008679号