链表(图解)及简单实现(Java)

一、链表的概念



链表是是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表分为单链表、双链表、循环链表

二、链表的实现(以单链表为例)


1.单链表

        1.)什么是单链表:

单向链表是一种线性表,实际上是由节点(Node)组成的,一个链表拥有不定数量的节点。其数据在内存中存储是不连续的,它存储的数据分散在内存中,每个节点只能也只有它能知道下一个节点的存储位置。由N各节点(Node)组成单向链表,每一个Node记录本Node的数据及下一个Node。向外暴露的只有一个头结点(Head),我们对链表的所有操作,都是直接或者间接地通过其头结点来进行的。

        2.)单链表的图解

2.单链表的代码实现


 1).单链表及结点的定义

class SingleList{

    Node head;//定义一个头节点,头节点不动,不存放具体的值
    private int Length;//链表的长度

    public  SingleList(){
        head=null;
        Length = 0 ;
    }

    //返回链表的长度
    public int length(){
        return this.Length;
    }
    
    //判断所需要操作位置的节点是否存在
    private void outLength(int index){
        if(this.Length < index || index < 0 ){ //需要操作位置大于链表长度,则抛出错误
            throw new IndexOutOfBoundsException();
        }
    }
    
}

//定义一个Node,每个Node就是一个节点
class Node {
    private int data;
    public Node next;

    public Node(int data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Node{" +
                " data='" + data + '\'' +
                '}';
    }
}

2).链表的增删改查实现 


增加节点:a.增加头节点 ;b.在指定索引处增加节点;c.在链表尾部增加节点

    /**添加节点到单链表头节点
     * @param node
     */
    public void addHead(Node node){
        //因为Head 为 null 所有直接将 head 给 node 的指向就行
        node.next = this.head;
        this.head = node;
        this.Length++;
    }

    /**加入结点到指定位置
     *      1.首先判断索引是否越界,越界则抛出异常
     *      2.循环,到指定索引  前一个索引 所在 结点 停止
     *          1.)将停止所在当前 结点 指向的 下一个结点 指向 Node 的下一个的结点
     *          2.)再将当前所在的 结点 指向Node
     * @param index
     * @param node
     */
    public void add(int index ,Node node ){
        outLength(index);//需要操作位置大于链表长度,则抛出错误

        if(index == 0 ){ //若要添加位置再头节点,直接调用add(方法)
            addHead(node);
            return;
        }

        Node temp = head; // 辅助链表
        while (index >1 ){
            temp = temp.next; //指向下一个节点
            index --;
        }
        node.next = temp.next;//当前 节点 指向的 下一个节点 指向 Node 的下一个的节点
        temp.next = node ;
        this.Length++; //链表长度加1
    }

    /**添加节点到单链表末尾
     * @param node
     */
    public void addList(Node node){
        add(Length,node ); //index 为链表的长度
    }

删除节点:a.删除头节点;b.删除指定索引位置的节点;c.删除尾部节点

    /** 删除头节点
     *      并返回所删除的结点,链表长度减 1
     * @return
     */
    public Node removeHead(){
        //判断链表是否为空
        if(Length == 0){
            return null ;
        }
        //定义一个Node 接收原先的头节点
        Node node = head ;
        head = head.next ; //然后删掉原头节点
        node.next =null; //将原先头节点的指向改成 null
        this.Length--;
        return node;
    }

    /**删除指定位置的元素
     *      并返回所删除的节点,链表长度减 1
     * @param index
     * @return
     */
    public Node remove(int index){
        outLength(index-1);//需要操作位置大于链表长度,则抛出错误

        boolean flag = true;
        Node temp = head; // 辅助链表
        Node node = null;
        while (flag){
            if(index-1 < 1 ){
                flag = false ;
                break;
            }
            temp = temp.next; //指向下一个节点
            index --;
        }
        node = temp.next; //储存要删除的节点,便于返回
        temp.next = temp.next.next;
        node.next = null;
        this.Length--; //链表长度减1
        return node;
    }

    /**删除链表尾部节点
     *      并返回所删除的节点,链表长度减 1
     *    调用remover
     */
    public Node removeList(){
        Node node = remove(this.Length-1);
        this.Length--;
        return node;
    }

查询指定节点

    /**查询指定节点
     *
     * @param index
     * @return
     */
    public Node showNode(int index){
        outLength(index);

        boolean flag = true;
        Node temp = head; // 辅助链表

        //将指针指向指定节点
        while (flag){
            if(index < 1 ){
                flag = false ;
                break;
            }
            temp = temp.next; //指向下一个节点
            index --;
        }

        return temp;
    }

    /**
     * 遍历链表
     */
    public void showList(){
        if(head == null){
            System.out.println("此链表为空");
        }
        Node temp = head ;
        while (temp != null){
            System.out.println(temp);
            temp=temp.next; //指向下一个节点
        }
    }

修改指定节点

    /**修改指定结点信息
     * @param index
     * @return
     */
    public Node upData(int index , Node upNode){
        outLength(index);

        boolean flag = true;
        Node temp = head; // 辅助链表
        Node node = null;

        //将指针指向指定节点的前一位
        while (index == 1 ){
            temp = temp.next; //指向下一个节点
            index --;
        }

        node = temp; // 用来储存修改前的节点
        upNode.next = temp.next.next; //将修改后节点 指向 修改前 下一个节点
        temp.next = upNode; //修改节点信息
        node.next = null; // 将前节点的指向改为 null

        return node;
    }
}

3.)测试代码

    public static void main(String[] args) {
        SingleList sl1 = new SingleList();

        Node n1 = new Node(1);
        Node n2 = new Node(2);
        Node n3 = new Node(3);
        Node n4 = new Node(4);
        Node n5 = new Node(5);

        //插入头节点
        sl1.addHead(n1);
        sl1.addHead(n2);
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //插入头节点
        sl1.addHead(n3);
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //插入链表尾部
        sl1.addList(n4);
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //指定索引处加入节点
        sl1.add(2,n5);
        //打印全部节点
        sl1.showList();
        System.out.println("此时链表长度为:"+ sl1.length());
        System.out.println("--------");

        //删除头节点
        sl1.removeHead();
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //删除尾部节点
        sl1.removeList();
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //删除指定位置节点
        sl1.remove(1);
        //打印全部节点
        sl1.showList();
        System.out.println("此时链表长度为:"+ sl1.length());
        System.out.println("--------");

        //修改节点
        sl1.upData(0,new Node (8));
        //打印全部节点
        sl1.showList();
        System.out.println("此时链表长度为:"+ sl1.length());
        System.out.println("--------");

        //查询指定节点
        System.out.println(sl1.showNode(0));

    }
}

完整代码

public class SingleListDome {

    public static void main(String[] args) {
        SingleList sl1 = new SingleList();

        Node n1 = new Node(1);
        Node n2 = new Node(2);
        Node n3 = new Node(3);
        Node n4 = new Node(4);
        Node n5 = new Node(5);

        //插入头节点
        sl1.addHead(n1);
        sl1.addHead(n2);
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //插入头节点
        sl1.addHead(n3);
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //插入链表尾部
        sl1.addList(n4);
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //指定索引处加入节点
        sl1.add(2,n5);
        //打印全部节点
        sl1.showList();
        System.out.println("此时链表长度为:"+ sl1.length());
        System.out.println("--------");

        //删除头节点
        sl1.removeHead();
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //删除尾部节点
        sl1.removeList();
        //打印全部节点
        sl1.showList();
        System.out.println("--------");

        //删除指定位置节点
        sl1.remove(1);
        //打印全部节点
        sl1.showList();
        System.out.println("此时链表长度为:"+ sl1.length());
        System.out.println("--------");

        //修改节点
        sl1.upData(0,new Node (8));
        //打印全部节点
        sl1.showList();
        System.out.println("此时链表长度为:"+ sl1.length());
        System.out.println("--------");

        //查询指定节点
        System.out.println(sl1.showNode(0));

    }
}

class SingleList{

    Node head;//定义一个头节点,头节点不动,不存放具体的值
    private int Length;//链表的长度

    public  SingleList(){
        head=null;
        Length = 0 ;
    }

    /**  将链表反转
     *
     * @param head
     * @return
     */
    public static Node reverseIteratively(Node head){
        Node next = null;
        Node temp = head;  // 辅助节点
        Node reverse = null;//用来储存逆转后的链表

        while(temp == null){
        }

        return null;
    }

    //返回链表的长度
    public int length(){
        return this.Length;
    }

    //判断所需要操作位置的节点是否存在
    private void outLength(int index){
        if(this.Length < index || index < 0 ){ //需要操作位置大于链表长度,则抛出错误
            throw new IndexOutOfBoundsException();
        }
    }


    /**添加节点到单链表头节点
     * @param node
     */
    public void addHead(Node node){
        //因为Head 为 null 所有直接将 head 给 node 的指向就行
        node.next = this.head;
        this.head = node;
        this.Length++;
    }

    /**加入结点到指定位置
     *      1.首先判断索引是否越界,越界则抛出异常
     *      2.循环,到指定索引  前一个索引 所在 结点 停止
     *          1.)将停止所在当前 结点 指向的 下一个结点 指向 Node 的下一个的结点
     *          2.)再将当前所在的 结点 指向Node
     * @param index
     * @param node
     */
    public void add(int index ,Node node ){
        outLength(index);//需要操作位置大于链表长度,则抛出错误

        if(index == 0 ){ //若要添加位置再头节点,直接调用add(方法)
            addHead(node);
            return;
        }

        Node temp = head; // 辅助链表
        while (index >1 ){
            temp = temp.next; //指向下一个节点
            index --;
        }
        node.next = temp.next;//当前 节点 指向的 下一个节点 指向 Node 的下一个的节点
        temp.next = node ;
        this.Length++; //链表长度加1
    }

    /**添加节点到单链表末尾
     * @param node
     */
    public void addList(Node node){
        add(Length,node ); //index 为链表的长度
    }

    /** 删除头节点
     *      并返回所删除的结点,链表长度减 1
     * @return
     */
    public Node removeHead(){
        //判断链表是否为空
        if(Length == 0){
            return null ;
        }
        //定义一个Node 接收原先的头节点
        Node node = head ;
        head = head.next ; //然后删掉原头节点
        node.next =null; //将原先头节点的指向改成 null
        this.Length--;
        return node;
    }

    /**删除指定位置的元素
     *      并返回所删除的节点,链表长度减 1
     * @param index
     * @return
     */
    public Node remove(int index){
        outLength(index-1);//需要操作位置大于链表长度,则抛出错误

        boolean flag = true;
        Node temp = head; // 辅助链表
        Node node = null;
        while (flag){
            if(index-1 < 1 ){
                flag = false ;
                break;
            }
            temp = temp.next; //指向下一个节点
            index --;
        }
        node = temp.next; //储存要删除的节点,便于返回
        temp.next = temp.next.next;
        node.next = null;
        this.Length--; //链表长度减1
        return node;
    }

    /**删除链表尾部节点
     *      并返回所删除的节点,链表长度减 1
     *    调用remover
     */
    public Node removeList(){
        Node node = remove(this.Length-1);
        this.Length--;
        return node;
    }

    /**查询指定节点
     *
     * @param index
     * @return
     */
    public Node showNode(int index){
        outLength(index);

        boolean flag = true;
        Node temp = head; // 辅助链表

        //将指针指向指定节点
        while (flag){
            if(index < 1 ){
                flag = false ;
                break;
            }
            temp = temp.next; //指向下一个节点
            index --;
        }

        return temp;
    }

    /**
     * 遍历链表
     */
    public void showList(){
        if(head == null){
            System.out.println("此链表为空");
        }
        Node temp = head ;
        while (temp != null){
            System.out.println(temp);
            temp=temp.next; //指向下一个节点
        }
    }

    /**修改指定结点信息
     * @param index
     * @return
     */
    public Node upData(int index , Node upNode){
        outLength(index);

        boolean flag = true;
        Node temp = head; // 辅助链表
        Node node = null;

        //将指针指向指定节点的前一位
        while (index == 1 ){
            temp = temp.next; //指向下一个节点
            index --;
        }

        node = temp; // 用来储存修改前的节点
        upNode.next = temp.next.next; //将修改后节点 指向 修改前 下一个节点
        temp.next = upNode; //修改节点信息
        node.next = null; // 将前节点的指向改为 null

        return node;
    }
}

//定义一个Node,每个Node就是一个节点
class Node {
    private int data;
    public Node next;

    public Node(int data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Node{" +
                " data='" + data + '\'' +
                '}';
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值