链表结束——单链表的插入和删除
链表的插入:
1.我们把链表的插入分为三种情况头插,尾插和中间插
2.我们定义两个指针head和rear
3.刚开始当链表的size=0时我们head=rear指向一个无意义的节点作为表头
4.插入时我们按照索引进行插入:
分为三种情况:
1.当index=0时我们进行头插
头插时我们的逻辑很简单我们让要插入的节点node.next=head.next,head.next=node就可以了
这里当size=0时
我们插入一个节点rear要后移
rear=head.next;
2.当index==size时我们尾插
尾插很简单两步走我们直接让rear.next=node,rear=node;
3.当index不为负数的其他情况进行中间插入
最后一种情况中间插入首先我们需要找到要插入节点的前驱(使用for循环循环index-1下就可以找到前驱)我们把前驱给一个变量node1
接下来我们开始插入node.next=node1.next,node1.next=node,
之后无论任何插入size++,
上代码:
public void add(int index, E e) {
Node n=new Node(e);
//链表一般来说是不会满的
if(index==0){
//头插法
n.next=head.next;
head.next=n;
if(size==0){
rear=n;
}
}else if(index==size-1){
//尾插法
rear.next=n;
rear=n;
}else{
Node p=find(index);
n.next=p.next;//把原来位置上的节点拼到下一个
p.next=n;//把n拼到此位置
}
size++;
}
//辅助函数寻找前驱这里从head开始有个空节点所以循环index次
public Node find(int index){
Node p=head;//从角标0开始遍历
for(int i=0;i<index;i++){
p=p.next;
}
return p;
}
链表的删除分为两种
1.按值删
删除呢就非常的简单我们只需要找到要删除节点的val的前驱然后p.next=p.next.next,就行了如果没找到则链表不动(了解一下没有考虑size==1时删除rear的移动)
上代码:
@Override
public void removeElement(E e) {
Node p=head.next;
while(true){
if(p.next.data.equals(e)){
p.next=p.next.next;
break;
}
p=p.next;
}
}
2.按索引删
这种删除和插入一样分为头删,尾删和中间删
1.头删
当index=0时
head.next=head.next.next;
当size==1时删除
rear=head;
2.尾删
当indxe=size-1时
我们找到删除节点的前驱node
node.next=null;
rear=node;
3.中间删
同样先找到前驱node然后node.next=node.next.next
三种情况都是删别忘了size–
上代码
public E remove(int index) {
if(isEmpty()){
throw new IllegalArgumentException("链表为空");
}
E res=null;
if(index==0){
res=head.next.data;
head.next=head.next.next;
if(size==1){
rear=head;
}
}else if(index==size-1){
Node p=find(index);
res=p.next.data;
p.next=null;
rear=p;
}else{
Node p=find(index);
res=p.next.data;
p.next=p.next.next;
}
size--;
return res;
}
然后
最后为了大家能够有更深刻的理解奉上linkist的实现及其测试类
public class LinkedList<E> implements List<E>{
private Node head;//头指针
private Node rear;//尾指针
private int size;
//链表节点
class Node{
E data;
Node next;
public Node(){
this(null,null);
}
public Node(E data){
this(data,null);
}
public Node(E data, Node next) {
this.data = data;
this.next = next;
}
}
public LinkedList() {
this.head = new Node();
this.rear =this.head;
this.size =0;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return head.next==null;
}
@Override
public void add(int index, E e) {
Node n=new Node(e);
//链表一般来说是不会满的
if(index==0){
//头插法
n.next=head.next;
head.next=n;
if(size==0){
rear=n;
}
}else if(index==size-1){
//尾插法
rear.next=n;
rear=n;
}else{
Node p=find(index);
n.next=p.next;//把原来位置上的节点拼到下一个
p.next=n;//把n拼到此位置
}
size++;
}
@Override
public void addFirst(E e) {
add(0, e);
}
@Override
public void addLast(E e) {
add(size-1, e);
}
@Override
public void set(int index, E e) {
if(isEmpty()){
throw new IllegalArgumentException("链表为空");
}
Node p=find(index+1);
p.data=e;
}
@Override
public E get(int index) {
return find(index+1).data;
}
@Override
public E getFirst() {
return get(0);
}
@Override
public E getLast() {
return get(size-1);
}
@Override
public boolean contains(E e) {
if(find(e)!=-1){
return true;
}
return false;
}
@Override
public int find(E e) {
Node p=head.next;
int index=-1;
while(!p.data.equals(e)){
index++;
p=p.next;
if(index==size-1){
index=-1;
break;
}
}
return index;
}
@Override
public E remove(int index) {
if(isEmpty()){
throw new IllegalArgumentException("链表为空");
}
E res=null;
if(index==0){
res=head.next.data;
head.next=head.next.next;
if(size==1){
rear=head;
}
}else if(index==size-1){
Node p=find(index);
res=p.next.data;
p.next=null;
rear=p;
}else{
Node p=find(index);
res=p.next.data;
p.next=p.next.next;
}
size--;
return res;
}
@Override
public E removeFirst() {
return remove(0);
}
@Override
public E removeLast() {
return remove(size-1);
}
@Override
public void removeElement(E e) {
Node p=head.next;
while(true){
if(p.next.data.equals(e)){
p.next=p.next.next;
break;
}
p=p.next;
}
}
@Override
public void clear() {
head.next=null;
rear=head;
size=0;
}
public Node find(int index){
Node p=head;//从角标0开始遍历
for(int i=0;i<index;i++){
p=p.next;
}
return p;
}
public String toString(){
Node p=head.next;
StringBuilder sb=new StringBuilder();
for(int i=0;i<size;i++){
sb.append(p.data);
p=p.next;
}
return sb.toString();
}
}
测试类
import com.lipengge.list.LinkedList;
public class TestLinkList {
public static void main(String[] args) {
LinkedList<Integer> ls=new LinkedList<Integer>();
System.out.println(ls);
ls.add(0, 1);
ls.add(0, 2);
ls.add(0, 3);
ls.add(0, 4);
ls.add(0, 5);
ls.add(0, 6);
System.out.println(ls);
//System.out.println(ls.getSize()-1);
//System.out.println(ls.getLast());
ls.add(ls.getSize()-1, 1);
System.out.println(ls.getLast());
ls.add(ls.getSize()-1, 2);
ls.add(ls.getSize()-1, 3);
ls.add(ls.getSize()-1, 4);
ls.add(ls.getSize()-1, 5);
ls.add(ls.getSize()-1, 6);
System.out.println(ls.getLast());
System.out.println(ls);
System.out.println(ls.removeLast());
System.out.println(ls);
System.out.println(ls.removeFirst());
System.out.println(ls);
System.out.println(ls.remove(3));
System.out.println(ls);
ls.set(ls.getSize()-1, 10);
System.out.println(ls);
System.out.println(ls.contains(18));
System.out.println(ls.get(3));
ls.clear();
System.out.println("...."+ls);
System.out.println("...."+ls.getSize());
}
}