链表
链表:⼀种物理存储结构上⾮连续存储结构,数据元素的逻辑顺序是通过链表中的引⽤链接次序实现的
链表结构


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的使用
【说明】
-
LinkedList实现了List接⼝
-
LinkedList的底层使⽤了双向链表
-
LinkedList没有实现RandomAccess接⼝,因此LinkedList不⽀持随机访问
-
LinkedList的任意位置插⼊和删除元素时效率⽐较⾼,时间复杂度为O(1)
-
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();
}