链表 SingleList
ArrayList的缺陷
在熟悉并且自己写了一个 ArrayList顺序表 的底层架构的时候 发现 ArrayList是利用数组来存储数据的
效率比较低:这里说两个例子
- 在插入以及删除的时候 ArrayList都需要移动剩余的元素
- 在开始的时候设置了初始的内存 后续需要扩容 这里也是效率低的表现
所以 ArrayList 不适合做任意位置插入以及删除比较多的场景
这里就引入链表结构
链表
链表的概念以及结构
定义:链表是一种 物理存储结构上非连续的存储结构 ,数据元素的逻辑顺序是通过链表中的引用链接次序来实现的
首先在程序中定义链表需要定义两个属性 分别是 链表所带的值 以及下一个链表的地址
如图
链表是通过下一个链表的地址来进行逻辑上的链接
所以
注意:
- 链式结构在逻辑上是连续的,但是在物理上不一定是连续的
- 显示中的节点一般都是从堆上申请出来的
- 从堆申请的空间,是按照一定的策略来分配的,两次申请的空间,可能连续也可能不连续
//链表中的一个字节 类
class ListNode{
public int val;//链表所带的值
public ListNode next;//下一个链表的地址
//有参构造
public ListNode(int val){this.val = val}
}
实际的链表结构非常多样 有以下8中
- 单向或者双向
- 带头或者不带头
- 循环或者非循环
将以上三种排列组合 可以得到8种链表结构 比如 单向带头不循环链表 也是我们目前学习的
链表的实现
class MySingleList{
public ListNode head;//头节点
//打印遍历
public void display(){
ListNode cur = head;
while(cur!=null){
System.out.print(cur.val+" ");
cur = cur.next;
}
System.out.println();
}
//从指定位置打印
public void display(ListNode newHead){
ListNode cur = newHead;
while(cur!=null){
System.out.print(cur.val+" ");
cur = cur.next;
}
System.out.println();
}
//size()
public int size(){
ListNode cur = head;
int count = 0;
while(cur!=null){
cur = cur.next;
count++;
}
return count;
}
//判断是否有key
public boolean contains(int key){
ListNode cur = head;
while(cur!=null){
if(cur.val==key){
return true;
}
cur = cur.next
}
return false;
}
//头插法
public void addFirst(int data){
ListNode node = new ListNode(data);
node.next = head;
head = node;
}
//尾插法
public void addList(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;
}
//寻找index下标的上一个位置 方便插入
private ListNode findIndexSubOne(int index){
ListNode cur = head;
while(index-1!=0){
cur=cur.next;
index--;
}
return cur;
}
//从index下标插入
public void addIndex(int index,int data){
if(index<0||index>size()){
SyStem.out.print("index不合法");
return;
}
if(index == 0){
addFirst(data);
return;
}
if(index==size()){
addList(data);
return;
}
ListNode cur = findIndexSubOne(int index);
ListNode node = new ListNode(data);
node.next = cur.next;
cur.next = node;
}
private ListNode seachPrev(int index){
ListNode cur = head;
while(cur.next != null){
if(cur.next.val == index){
return cur;
}
cur = cur.next;
}
return null;
}
//删除链表中第一个出现的key
public void remove(int key){
if(head==null){
return null;
}
if(head.val == key){
head = head.next;
return;
}
ListNode cur = seachPrev(key);
if(cur==null){
return;
}
cur.next = cur.next.next
}
//删除所有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 void clear(){this.head = null};
}
链表面试题 详见 IDEA
LinkedList的模拟实现
//单头双向无循环
public class MyLinkedList {
static class ListNode{
private int val;
private ListNode prev;
private ListNode next;
public ListNode(int val) {
this.val = val;
}
}
public ListNode head;
public ListNode last;
//头插法
public void addFirst(int data){
ListNode node = new ListNode(data);
if(head==null){
this.head = node;
this.last = node;
}else{
node.next = head;
head.prev = node;
head = node;
}
}
//尾插法
public void addLast(int data){
ListNode node = new ListNode(data);
if(head==null){
this.head = node;
this.last = node;
}else{
last.next = node;
node.prev = last;
last = node;
}
}
public void cheakIndex(int index){
if(index<0||index>size()){
throw new indexOutOfException("index 不合法");
}
}
private ListNode seachIndex(int index){
ListNode cur = head;
while(index!=0){
cur=cur.next;
index--;
}
return cur;
}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){
cheakIndex(index);
if(index == 0){
addFirst(data);
return;
}
if(index==size()){
addLast(data);
return;
}
ListNode node = new ListNode(data);
ListNode cur = seachIndex(index);
for (int i = 0; i < index; i++) {
cur = cur.next;
}
cur.prev.next = node;
node.prev = cur.prev;
node.next = cur;
cur.prev = node;
}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){
ListNode cur = head;
while(cur!=null){
if(cur.val == key){
return true;
}
cur = cur.next;
}
return false;
}
private ListNode findKeySubOne(int key){
ListNode cur = head;
while(cur!=null){
if(cur.val == key){
return cur;
}
cur = cur.next;
}
return null;
}
//删除第一次出现关键字为key的节点
public void remove(int key){
if(head==null){
return;
}
if(head.val == key){
head = head.next;
head.prev = null;
return;
}
if(last.val == key){
last = last.prev;
last.next = null;
}
ListNode cur = findKeySubOne(key);
cur.next.prev = cur.prev;
cur.prev.next = cur.next;
}
//删除所有值为key的节点
public void removeAllKey(int key){
ListNode cur = head;
while(cur!=null){
if(cur.val == key){
if(cur == head){
head = head.next;
if(head != null){
head.prev = null;
}else{
last = null;
}
}else{
if(cur.next != null){
cur.next.prev = cur.prev;
cur.prev.next = cur.next;
}else{
last = last.prev;
last.next = null;
}
}
cur = cur.next;
}
}
}
//得到单链表的长度
public int size(){
ListNode cur = head;
int count = 0;
while(cur!=null){
cur = cur.next;
count++;
}
return count;
}
public void display(){
ListNode cur = head;
while(cur!=null){
System.out.println(cur.val+" ");
cur = cur.next;
}
System.out.println();
}
public void clear(){
ListNode cur = head;
while(cur!=null){
ListNode newHead = cur.next;
cur.val = 0;
cur.prev = null;
cur.next = null;
cur = newHead;
}
head = null;
last = null;
}
}
标签:head,ListNode,cur,int,next,链表,null
From: https://www.cnblogs.com/ljy2003/p/18435114