链表看这篇就够了

目录

单链表

什么是单链表

无头单链表实现

什么是头节点(head)

如何创建节点

如何找到每一个节点

找到某个索引节点

遍历整个链表: 

创建实现类 (增删改查)

代码实现

头插法

任意位置插入

尾插法

判断index合法性

查询第一个值为val的节点

查询是否包含指定值的节点

查询索引index位置的值

修改索引index的值为newVal,并返回旧值oldVal。

删除index位置的元素

删除第一个值为val的节点

 删除所有值为val的节点

有头单链表实现

创建头节点

add方法

remove方法

双向链表实现

创建节点类

创建头节点和尾节点

增加方法

头插尾插

任意位置插入

查找方法

给定索引找节点

判断index合法性

删除方法

unlink方法

删除第一次出现的val节点

删除所有val节点

完整代码

1.无头单链表

2.有头单链表

3.双向链表

单链表
什么是单链表
单链表也是顺序表的一种,但是和数组不一样,单链表在物理上是不连续的,只有逻辑上连续。

单链表是由无数个节点连接到一起的,每个节点存放一个节点值val和下一个节点的地址next

我们可以把单链表想成一列火车,每一个节点就是一节车厢。而火车,必然会有车头和车尾。

单链表分为无头单链表和有头单链表

无头单链表指:头节点为有值节点,除了头之外还负责存放节点值

有头单链表指:头节点无值,只有一个存在的意义,便是存放链表的地址,所以无论链表如何更改有头单链表的head始终不变

无头单链表实现

什么是头节点(head)

单链表的车头部分,驱动整个单链表能够运作起来,为重中之重。

如何创建节点

我们之前说,节点需要存放值和地址,所以我们可以创建一个类来存放这两个值。

class Node {
    int val;
    Node next;//存放下一个节点的地址,所以采用Node类定义
}

 

如何找到每一个节点

遍历链表,用来找到每一个节点。

找到某个索引节点

用于找节点或者节点前驱

Node prev= head;
        for (int i = 0; i < index-1; i++) {
            prev=prev.next;
        }

遍历整个链表: 

用于找到某个节点值为val的索引

for (Node x = head; x != null; x=x.next)

创建实现类 (增删改查)

一个头节点head  和 节点个数size

因为用户不需要关注这些值所以我们封装起来

public class SingleLinkerList {
    private Node head;
    private int size;
 }

代码实现

头插法

在链表最前方插入节点,并作为头节点。

我们需要判断目前链表是否为空,如果为空则是第一次插入节点。

否则便是更换头节点。

public void addFirst(int val) {
        Node newNode = new Node();
        newNode.val = val;
        if (head != null) {
            newNode.next = head;
        }
        head=newNode;
        size++;
    }

任意位置插入

需要插入位置索引index 和 插入的值val

我们需要找到index的前驱index-1

不懂就自己画个图

同时,我们需要判断index是否合法,不可以在size以外的值插入

另外,如果index为0我们可以直接引用头插入方法,而且头插入方法还包含第一次插入的情况,一举两得。

 public void addIndex(int index,int val) {
        if(index<0||index>size){
            System.err.println("illegal index!!");
            return;
        }
        if(index==0) {
            addFirst(val);
        } else {
            Node prev = head;
            Node newNode=new Node();
            newNode.val=val;
            for (int i = 0; i < index-1; i++) {
                prev=prev.next;
            }
            newNode.next=prev.next;
            prev.next=newNode;
            size++;
        }
    }

 

尾插法

属于特殊的任意位置插入,也就是size位置插入

直接调用任意位置插入方法即可。

前文提到,想查到某个节点可以遍历链表,所以以下几种查询均可遍历链表。

判断index合法性

我们不妨把判断index合法性写成一个私有方法,因为总要用。

public boolean rangerCheck(int index) {
        if(index<0||index>=size) {
            return false;
        }
        return true;
    }

查询第一个值为val的节点

public int getByValue(int val) {
        int index=0;
        for (Node x = head; x != null; x=x.next) {
            if(x.val==val) {
                return index;
            }
            index++;
        }
        return -1;
    }

查询是否包含指定值的节点

调用上个方法即可

public boolean contains(int val) {
        return getByValue(val)!=-1;
    }

查询索引index位置的值

public  int get (int index) {
       if(rangerCheck(index)==false) {
           System.err.println("illegal index!!!");
           return -1;
       }
       Node prev = head;
        for (int i = 0; i < index; i++) {
            prev=prev.next;
        }
        return prev.val;
    }

修改索引index的值为newVal,并返回旧值oldVal。

public int set(int index,int newVal) {
        if(rangerCheck(index)==false) {
            System.err.println("illegal index");
            return -1;
        }
   
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值