链表(LinkedList)
链表
链表:⼀种物理存储结构上⾮连续存储结构,数据元素的逻辑顺序是通过链表中的引⽤链接次序实现的
链表结构
LinkedList单向链表
LinkedList的创建与打印
public class MyLinkedList {static class ListNode{public int val;public ListNode next;public ListNode(int val){this.val=val;}}public ListNode head;public void creatList(){ListNode node1=new ListNode(11);ListNode node2=new ListNode(22);ListNode node3=new ListNode(33);ListNode node4=new ListNode(44);ListNode node5=new ListNode(55);node1.next=node2;node2.next=node3;node3.next=node4;node4.next=node5;this.head=node1;}public void print(){ListNode cur=head;while(cur!=null){System.out.print(cur.val+" ");cur=cur.next;}System.out.println();} }
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.creatList();myLinkedList.print();} }
LinkedList的头插法
public void addFirst(int data) {ListNode node=new ListNode(data);node.next=head;head=node; }
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.addFirst(1);myLinkedList.addFirst(2);myLinkedList.addFirst(3);myLinkedList.print();} }
LinkedList的尾插法
public void addLast(int data) {ListNode node=new ListNode(data);ListNode cur=head;if(cur==null){head=node;return;}while (cur.next!=null){cur=cur.next;}cur.next=node; } public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.addLast(10);myLinkedList.addLast(20);myLinkedList.addLast(30);myLinkedList.print();} }
LinkedList的指定位置插入法
public void addIndex(int index, int data) {
if(index<0||index>size()){
return ;
}
if (index==0){
addFirst(data);
return;
}
if(index==size()){
addLast(data);
return;
}
ListNode node=new ListNode(data);
ListNode cur=searchIndex(index);
if(cur==null){
return;
}
node.next=cur.next;
cur.next=node;
}
public ListNode searchIndex(int index){
if(index<0||index>size()){
return null;
}
ListNode cur=head;
int count=0;
while (count!=index-1){
cur=cur.next;
count++;
}
return cur;
}
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.creatList();myLinkedList.print();myLinkedList.addIndex(0,0);myLinkedList.addIndex(6,66);myLinkedList.print();} }
Linked List的contains方法
public boolean contains(int key) {ListNode cur=head;while(cur!=null){if(cur.val==key){return true;}cur=cur.next;}return false; }
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.creatList();System.out.println(myLinkedList.contains(33));System.out.println(myLinkedList.contains(66));} }
LinkedList的删除第一次出现的key关键字
public ListNode searchIndex(int index){if(index<0||index>size()){return null;}ListNode cur=head;int count=0;while (count!=index-1){cur=cur.next;count++;}return cur; }// 查找是否包含关键字 key 是否在单链表当中 public boolean contains(int key) {ListNode cur=head;while(cur!=null){if(cur.val==key){return true;}cur=cur.next;}return false; }
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.addLast(10);myLinkedList.addLast(20);myLinkedList.addLast(30);myLinkedList.addLast(40);myLinkedList.print();myLinkedList.remove(30);myLinkedList.print();} }
LinkedList的删除所有key关键字
public void removeAllKey(int key) {if (head==null){return;}ListNode prev=head;ListNode cur=head.next;while (cur!=null){if (cur.val==key){prev.next=cur.next;cur=cur.next;}else {prev=cur;cur=cur.next;}}if (head.val==key){head=head.next;} }
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.addLast(10);myLinkedList.addLast(30);myLinkedList.addLast(20);myLinkedList.addLast(30);myLinkedList.addLast(40);myLinkedList.addLast(30);myLinkedList.print();myLinkedList.removeAllKey(30);myLinkedList.print();} }
LinkedList的size()方法
public int size() {
ListNode cur=head;
int count=0;
while (cur!=null){
count++;
cur=cur.next;
}
return count;
}
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.creatList();System.out.println(myLinkedList.size());} }
LinkedList的clear方法
public void clear() {head=null; }
public class Test {public static void main(String[] args) {MyLinkedList myLinkedList=new MyLinkedList();myLinkedList.creatList();myLinkedList.print();myLinkedList.clear();System.out.println("clear之后:");myLinkedList.print();} }
LinkedList的完整实现
public class MyLinkedList {static class ListNode{public int val;public ListNode next;public ListNode(int val){this.val=val;}}public ListNode head;public ListNode last;public void creatList(){ListNode node1=new ListNode(11);ListNode node2=new ListNode(22);ListNode node3=new ListNode(33);ListNode node4=new ListNode(44);ListNode node5=new ListNode(55);node1.next=node2;node2.next=node3;node3.next=node4;node4.next=node5;this.head=node1;}public void print(){ListNode cur=head;while(cur!=null){System.out.print(cur.val+" ");cur=cur.next;}System.out.println();}// 头插法public void addFirst(int data) {ListNode node=new ListNode(data);node.next=head;head=node;}// 尾插法public void addLast(int data) {ListNode node=new ListNode(data);ListNode cur=head;if(cur==null){head=node;return;}while (cur.next!=null){cur=cur.next;}cur.next=node;}// 任意位置插入,第一个数据节点为 0 号下标public void addIndex(int index, int data) {if(index<0||index>size()){return ;}if (index==0){addFirst(data);return;}if(index==size()){addLast(data);return;}ListNode node=new ListNode(data);ListNode cur=searchIndex(index);if(cur==null){return;}node.next=cur.next;cur.next=node;}public ListNode searchIndex(int index){if(index<0||index>size()){return null;}ListNode cur=head;int count=0;while (count!=index-1){cur=cur.next;count++;}return cur;}// 查找是否包含关键字 key 是否在单链表当中public boolean contains(int key) {ListNode cur=head;while(cur!=null){if(cur.val==key){return true;}cur=cur.next;}return false;}// 删除第一次出现关键字为 key 的节点public void remove(int key) {if (head==null){return;}if (head.val==key){head=head.next;return;}ListNode pre=findKey(key);if (pre==null){return;}ListNode delete=pre.next;pre.next=delete.next;}public ListNode findKey(int key){ListNode prev=head;while (prev.next!=null){if(prev.next.val==key){return prev;}prev = prev.next;}return null;}// 删除所有值为 key 的节点public void removeAllKey(int key) {if (head==null){return;}ListNode prev=head;ListNode cur=head.next;while (cur!=null){if (cur.val==key){prev.next=cur.next;cur=cur.next;}else {prev=cur;cur=cur.next;}}if (head.val==key){head=head.next;}}// 得到单链表的长度public int size() {ListNode cur=head;int count=0;while (cur!=null){count++;cur=cur.next;}return count;}public void clear() {head=null;}}
DoubleLinked List双向链表
Double Linked List的头插法
public void addFirst(int data) {LinkedNode node=new LinkedNode(data);if(head==null){head=node;last=node;}else {node.next=head;head.prev=node;head=node;} }
DoubleLinkedList的尾插法
public void addLast(int data) {LinkedNode node=new LinkedNode(data);if (head==null){head=node;last=node;}else {last.next=node;node.prev=last;last=node;} }
DoubleLinkedList的任意位置插入的方法
public void addIndex(int index, int data) {if (index<0||index>size()){System.out.println("下标位置不合法:"+index);return;}if (index==0){addFirst(data);return;}if(index==size()){addLast(data);return;}LinkedNode node=new LinkedNode(data);LinkedNode cur=search(index);node.next=cur;cur.prev.next=node;node.prev=cur.prev;cur.prev=node; } public LinkedNode search(int index){LinkedNode cur=head;while (index!=0){cur=cur.next;index--;}return cur; }
DoubleLinkedList删除key节点的方法
// 删除第一次出现关键字为 key 的节点 public void remove(int key) {LinkedNode cur=head;while (cur!=null){if(cur.val == key) {if(cur == head) {//删除头节点head = head.next;if(head == null) {//只有一个节点的情况下last = null;}else {head.prev = null;}}else {//删除中间和尾巴if(cur.next == null) {//尾巴cur.prev.next = cur.next;last = last.prev;}else {cur.prev.next = cur.next;cur.next.prev = cur.prev;}}return;}cur = cur.next;} }// 删除所有值为 key 的节点 public void removeAllKey(int key) {LinkedNode cur = head;while (cur != null) {if(cur.val == key) {if(cur == head) {//删除头节点head = head.next;if(head == null) {//只有一个节点的情况下last = null;}else {head.prev = null;}}else {//删除中间和尾巴if(cur.next == null) {//尾巴cur.prev.next = cur.next;last = last.prev;}else {cur.prev.next = cur.next;cur.next.prev = cur.prev;}}}cur = cur.next;} }
DoubleLinkedList的contains()方法
public boolean contains(int key) {
LinkedNode cur=head;
while (cur!=null){
if (cur.val==key){
return true;
}
cur=cur.next;
}
return false;
}
Double Linked List的size()方法
public int size() {LinkedNode cur=head;int count=0;while (cur!=null){count++;cur=cur.next;}return count; }
Double Linked List的display()方法
public void display() {LinkedNode cur=head;while (cur!=null){System.out.print(cur.val+" ");cur=cur.next;}System.out.println(); }
DoubleLinkedList的clear()方法
public void clear() {LinkedNode cur = head;while (cur != null) {LinkedNode curN = cur.next;cur.prev = null;cur.next = null;cur = curN;}head = null;last = null; }

DoubleLinkedList的完整实现
public class DoubleLinkedList {static class LinkedNode{public int val;public LinkedNode next;public LinkedNode prev;public LinkedNode(int val){this.val=val;}}public LinkedNode head;public LinkedNode last;public void addFirst(int data) {LinkedNode node=new LinkedNode(data);if(head==null){head=node;last=node;}else {node.next=head;head.prev=node;head=node;}}// 尾插法public void addLast(int data) {LinkedNode node=new LinkedNode(data);if (head==null){head=node;last=node;}else {last.next=node;node.prev=last;last=node;}}// 任意位置插入,第一个数据节点为 0 号下标public void addIndex(int index, int data) {if (index<0||index>size()){System.out.println("下标位置不合法:"+index);return;}if (index==0){addFirst(data);return;}if(index==size()){addLast(data);return;}LinkedNode node=new LinkedNode(data);LinkedNode cur=search(index);node.next=cur;cur.prev.next=node;node.prev=cur.prev;cur.prev=node;}public LinkedNode search(int index){LinkedNode cur=head;while (index!=0){cur=cur.next;index--;}return cur;}// 查找是否包含关键字 key 是否在单链表当中public boolean contains(int key) {LinkedNode cur=head;while (cur!=null){if (cur.val==key){return true;}cur=cur.next;}return false;}// 删除第一次出现关键字为 key 的节点public void remove(int key) {LinkedNode cur=head;while (cur!=null){if(cur.val == key) {if(cur == head) {//删除头节点head = head.next;if(head == null) {//只有一个节点的情况下last = null;}else {head.prev = null;}}else {//删除中间和尾巴if(cur.next == null) {//尾巴cur.prev.next = cur.next;last = last.prev;}else {cur.prev.next = cur.next;cur.next.prev = cur.prev;}}return;}cur = cur.next;}}// 删除所有值为 key 的节点public void removeAllKey(int key) {LinkedNode cur = head;while (cur != null) {if(cur.val == key) {if(cur == head) {//删除头节点head = head.next;if(head == null) {//只有一个节点的情况下last = null;}else {head.prev = null;}}else {//删除中间和尾巴if(cur.next == null) {//尾巴cur.prev.next = cur.next;last = last.prev;}else {cur.prev.next = cur.next;cur.next.prev = cur.prev;}}}cur = cur.next;}}// 得到单链表的长度public int size() {LinkedNode cur=head;int count=0;while (cur!=null){count++;cur=cur.next;}return count;}// 遍历显示链表元素(假设功能),实际可根据需求定义public void display() {LinkedNode cur=head;while (cur!=null){System.out.print(cur.val+" ");cur=cur.next;}System.out.println();}// 清空链表public void clear() {LinkedNode cur = head;while (cur != null) {LinkedNode curN = cur.next;//cur.val = null;cur.prev = null;cur.next = null;cur = curN;}head = null;last = null;} }
Linked List的使用
【说明】
1. LinkedList实现了List接⼝
2. LinkedList的底层使⽤了双向链表
3. LinkedList没有实现RandomAccess接⼝,因此LinkedList不⽀持随机访问
4. LinkedList的任意位置插⼊和删除元素时效率⽐较⾼,时间复杂度为O(1)
5. LinkedList⽐较适合任意位置插⼊的场景
LinkedList的常用方法
import java.util.LinkedList;public class Test {public static void main(String[] args) {LinkedList<Integer> linkedList=new LinkedList<>();LinkedList<Integer> linkedList1=new LinkedList<>();linkedList1.add(55);linkedList1.add(66);//尾插linkedList.add(11);linkedList.add(22);linkedList.add(33);System.out.println(linkedList);//元素插入index位置linkedList.add(0,0);linkedList.add(4,44);System.out.println(linkedList);//插入其他链表的元素linkedList.addAll(linkedList1);System.out.println(linkedList);//删除元素linkedList.remove(0);linkedList.remove(4);System.out.println(linkedList);//获取下标元素System.out.println(linkedList.get(3));//设置index元素linkedList.set(1,111);System.out.println(linkedList);//判断元素是否存在System.out.println(linkedList.contains(44));System.out.println(linkedList.contains(22));//返回下标System.out.println(linkedList.indexOf(55));System.out.println(linkedList.lastIndexOf(111));//截取System.out.println(linkedList.subList(0, 4));//清空System.out.println(linkedList);linkedList.clear();System.out.println(linkedList);} }
Linked List的遍历
import java.util.LinkedList; import java.util.ListIterator; public class Test {public static void main(String[] args) {LinkedList<Integer> linkedList=new LinkedList<>();linkedList.add(1);linkedList.add(2);linkedList.add(3);//直接遍历System.out.println(linkedList);//for循环遍历for (int i = 0; i <linkedList.size() ; i++) {System.out.print(linkedList.get(i)+" ");}System.out.println();//foreach遍历for (int i:linkedList) {System.out.print(i+" ");}System.out.println();//迭代器遍历ListIterator<Integer> iterator=linkedList.listIterator();while (iterator.hasNext()){System.out.print(iterator.next()+" ");}System.out.println();ListIterator<Integer> iterator1=linkedList.listIterator(linkedList.size());while (iterator1.hasPrevious()){System.out.print(iterator1.previous()+" ");}System.out.println();}