04 链表

  链表是真正的动态数据结构,其数据存储在“结点(Node)”中,它不需要处理固定容量的问题。其缺点在于丧失了随机访问的能力,不支持快速查询,而数组是支持快速查询的。

1.链表接口的实现

  1 /**
  2  * @author 阿遠
  3  * Date: 2019/1/15
  4  * Time: 11:08
  5  */
  6 public class LinkedList<E> {
  7 
  8 
  9     private Node dummyhead; // 链表头
 10     private int size; // 链表容量
 11     private class Node{
 12         public E e;  // 元素
 13         public Node next;   // 结点
 14 
 15         private Node(E e, Node next) {
 16             this.e = e;
 17             this.next = next;
 18         }
 19 
 20         public Node(E e) {
 21             this(e, null);
 22         }
 23 
 24         public Node() {
 25             this(null, null);
 26         }
 27 
 28         @Override
 29         public String toString() {
 30             return e.toString();
 31         }
 32     }
 33 
 34     public LinkedList() {
 35         dummyhead = new Node(null, null);
 36         size = 0;
 37     }
 38 
 39     // 获取列表中的元素个数
 40     public int getSize() {
 41         return size;
 42     }
 43 
 44     // 返回链表是否为空
 45     public boolean isEmpty() {
 46         return size == 0;
 47     }
 48 
 49     //在链表的index(0-based)位置添加新的元素e
 50     public void add(int index, E e) {
 51         if (index < 0 || index > size) {
 52             throw new IllegalArgumentException("Add failed.Illegal index.");
 53         }
 54         Node pre = dummyhead;
 55         for (int i = 0; i < index; i ++) {
 56             pre = pre.next;
 57         }
 58 //            Node node = new Node(e);
 59 //            node.next = pre.next;
 60 //            pre.next = node;
 61         pre.next = new Node(e, pre.next);
 62         size ++;
 63     }
 64     //在链表头添加新的元素
 65     public void addFirst(E e) {
 66         add(0, e);
 67     }
 68     // 在链表的末尾添加新的元素
 69     public void addLast(E e) {
 70         add(size, e);
 71     }
 72 
 73     // 获得链表的第index个位置的元素
 74     public E get(int index) {
 75         if (index < 0 || index >= size)
 76             throw new IllegalArgumentException("Get failed.Illegal index.");
 77         Node cur = dummyhead.next;
 78         for (int i = 0; i < index; i++) {
 79             cur = cur.next; // 遍历找到index处的Node
 80         }
 81         return cur.e;
 82     }
 83     // 获得列表的第一个元素
 84     public E getFirst() {
 85         return get(0);
 86     }
 87     // 获得链表中最后一个元素
 88     public E getLast() {
 89         return get(size - 1);
 90     }
 91 
 92     // 修改列表中第index个位置的元素为e
 93     public void set(int index, E e) {
 94         if (index < 0 || index >= size)
 95             throw new IllegalArgumentException("Update failed.Illegal index.");
 96         Node cur = dummyhead.next;
 97         for (int i = 0; i < index; i++) {
 98             cur = cur.next;
 99         }
100         cur.e = e;
101     }
102 
103     // 查找链表中是否有元素e
104     public boolean contains(E e) {
105         Node cur = dummyhead.next;
106         while(cur != null) {
107             if (cur.e.equals(e)) {
108                 return true;
109             }
110             cur = cur.next;
111         }
112         return false;
113     }
114     // 从列表中删除index位置处的元素,返回删除的元素
115     public E remove(int index) {
116         if (index < 0 || index >= size)
117             throw new IllegalArgumentException("Remove failed.Illegal index.");
118         Node prev = dummyhead;
119         for (int i = 0; i < index; i ++) {
120             prev = prev.next;
121         }
122         Node retNode = prev.next;
123         prev.next = retNode.next;
124         retNode.next = null;
125         size --;
126 
127         return retNode.e;
128     }
129     // 从链表中删除第一个元素,返回删除的元素
130     public E removeFirst() {
131         return remove(0);
132     }
133     // 从链表中删除最后一个元素
134     public E removeLast() {
135         return remove(size - 1);
136     }
137 
138     @Override
139     public String toString() {
140         StringBuilder res = new StringBuilder();
141 //        Node cur = dummyhead.next;
142 //        while(cur != null) {
143 //            res.append(cur + "->");
144 //            cur = cur.next;
145 //        }
146         for (Node cur = dummyhead.next; cur != null; cur = cur.next)
147             res.append(cur + "->");
148         res.append("NULL");
149         return res.toString();
150     }
151 }

2. 链表接口的测试

 1 public class Main {
 2 
 3     public static void main(String[] args) {
 4 
 5         LinkedList<Integer> linkedList = new LinkedList<Integer>();
 6         for (int i = 0; i < 5; i ++) {
 7             linkedList.addFirst(i);
 8             System.out.println(linkedList);
 9         }
10         System.out.println("在索引为2的位置插入元素: 666");
11         linkedList.add(2, 666);
12         System.out.println(linkedList);
13 
14         System.out.println("移除索引为2的位置的元素: 666");
15         linkedList.remove(2);
16         System.out.println(linkedList);
17 
18         System.out.println("移除链表头的元素:4");
19         linkedList.removeFirst();
20         System.out.println(linkedList);
21 
22         System.out.println("移除链表尾的元素:0");
23         linkedList.removeLast();
24         System.out.println(linkedList);
25     }
26 }

  测试结果:

0->NULL
1->0->NULL
2->1->0->NULL
3->2->1->0->NULL
4->3->2->1->0->NULL
在索引为2的位置插入元素: 666
4->3->666->2->1->0->NULL
移除索引为2的位置的元素: 666
4->3->2->1->0->NULL
移除链表头的元素:4
3->2->1->0->NULL
移除链表尾的元素:0
3->2->1->NULL

3.链表的复杂度分析

添加操作
    addLast(e)          O(n)     //从链表头开始遍历
    addFirst(e)         O(1)
    add(index, e)       O(n/2) = O(n)      //从链表头开始遍历
    删除操作
    removeLast(e)       O(n)    //从链表头开始遍历
    removeFirst(e)      O(1)
    remove(index, e)    O(n/2) = O(n)      //从链表头开始遍历
    修改操作
    set(index)          O(n)
    contains(e)         O(n)
    总结:
    增 : O(n)     删 : O(n)    改 : O(n)    查 : O(n)
    适合只操作链表头:O(1)

猜你喜欢

转载自www.cnblogs.com/a-yuan/p/10287724.html
04