八、DoubleLinkedList模拟实现(简单)
无头双向链表实现
//双向链表
class ListNode {
public int val;//值
public ListNode next;//后继信息
public ListNode prev;//前驱信息
public ListNode(int val) {
this.val = val;
}
}
public class DoubleLinkedList {
public ListNode head;//标记双向链表的头节点
public ListNode last;//标记双向链表的尾巴
//方法的模拟实现
}
- 头插法
//头插法
public void addFirst(int data){
ListNode node=new ListNode(data);
if(this.head==null){
this.head=node;
this.last=node;
}else{
node.next=this.head;
head.prev=node;
this.head=node;
}
}
- 尾插法
//尾插法
public void addLast(int data){
ListNode node=new ListNode(data);
if(this.head==null){
this.head=node;
this.last=node;
}else{
last.next=node;
node.prev=last;
this.last=node;
}
}
- 任意位置插入,第一个数据节点为0号下标
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
if(index<0||index>size()){
throw new RuntimeException("index不合法!");
}
if(index==0){
addFirst(data);
return;
}
if(index==size()){
addLast(data);
return;
}
ListNode node=new ListNode(data);
ListNode cur=this.head;
for(int i=0;i<index-1;i++){
cur=cur.next;
}
node.prev=cur;
node.next=cur.next;
cur.next.prev=node;
cur.next=node;
}
- 查找是否包含关键字key是否在单链表当中
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
ListNode cur = this.head;
while (cur != null) {
if(cur.val == key) {
return true;
}
cur = cur.next;
}
return false;
}
- 删除第一次出现关键字为key的节点
//删除第一次出现关键字为key的节点
public void remove(int key){
ListNode cur = this.head;
while (cur != null) {
if(cur.val == key) {
//判断是不是头节点
if(cur == head) {
head = head.next;
//判断是不是只有1个节点
if(head != null) {
head.prev = null;
}
}else {
//两种情况:1、是中间节点 2、是尾巴节点
cur.prev.next = cur.next;
if(cur.next != null) {
//中间节点
cur.next.prev = cur.prev;
}else {
//尾巴节点
last = last.prev;
}
}
return;//删除结束,return
}else {
cur = cur.next;
}
}
}
- 删除所有值为key的节点
//删除所有值为key的节点
public void removeAllKey(int key){
ListNode cur = this.head;
while (cur != null) {
if(cur.val == key) {
//判断是不是头节点
if(cur == head) {
head = head.next;
//判断是不是只有1个节点
if(head != null) {
head.prev = null;
}
}else {
//两种情况:1、是中间节点 2、是尾巴节点
cur.prev.next = cur.next;
if(cur.next != null) {
//中间节点
cur.next.prev = cur.prev;
}else {
//尾巴节点
last = last.prev;
}
}
}
cur = cur.next;
}
}
- 得到单链表的长度
//得到单链表的长度
public int size(){
int count = 0;
ListNode cur = this.head;
while (cur != null) {
count++;
cur = cur.next;
}
return count;
}
- 打印链表里面的元素
//打印链表里面的元素
public void display() {
ListNode cur = this.head;
while (cur != null) {
System.out.print(cur.val+" ");
cur = cur.next;
}
}
- 清空列表
//清空列表
public void clear(){
ListNode cur = head;
while (cur != null) {
ListNode curNext = cur.next;
//cur.val = null;
cur.prev = null;
cur.next = null;
cur = curNext;
}
head = null;
last = null;
}
}
- 测试及运行结果
public static void main(String[] args) {
Test20220315 doubleLinkedList = new Test20220315();
doubleLinkedList.addLast(1);
doubleLinkedList.addLast(2);
doubleLinkedList.addLast(3);
doubleLinkedList.addLast(4);
doubleLinkedList.addLast(5);
doubleLinkedList.display();//12345
System.out.println();
System.out.println(doubleLinkedList.size());//5
System.out.println(doubleLinkedList.contains(3));//true
System.out.println(doubleLinkedList.contains(9));//false
doubleLinkedList.addFirst(6);//612345
doubleLinkedList.display();
System.out.println();
doubleLinkedList.addLast(7);//6123457
doubleLinkedList.display();
System.out.println();
doubleLinkedList.addIndex(3, 5);//61253457
doubleLinkedList.display();
System.out.println();
doubleLinkedList.remove(2);//6153457
doubleLinkedList.display();
System.out.println();
doubleLinkedList.removeAllKey(5);//61347
doubleLinkedList.display();
System.out.println();
doubleLinkedList.clear();
doubleLinkedList.display();
}
九、ArrayList和LinkedList的区别
不同点 | ArrayList | LinkedList |
---|---|---|
存储空间上 | 物理上一定连续 | 逻辑上连续,但物理上不一定连续 |
随机访问 | 支持O(1) | 不支持:O(N) |
头插 | 需要搬移元素,效率低O(N) | 只需修改引用的指向,时间复杂度为O(1) |
插入 | 空间不够时需要扩容 | 没有容量的概念 |
应用场景 | 元素高效存储+频繁访问 | 任意位置插入和删除频繁 |