单链表无头非循环与双链表无头循环Java实现

这篇博客详细介绍了链表数据结构的两种常见实现——无头非循环单链表和无头双向循环链表。内容包括它们的节点定义、头结点处理、插入、删除、查找等基本操作。通过示例代码展示了如何在不同位置插入元素、删除特定关键字的节点以及清空链表等功能。此外,还提供了头插法、尾插法以及任意位置插入的实现方法。
摘要由CSDN通过智能技术生成

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。

单链表无头非循环

// 1、无头单向非循环链表实现
public class SingleLinkedList {
//打印链表
 public void display();
     //头插法
     public void addFirst(int data);
     //尾插法
     public void addLast(int data);
     //任意位置插入,第一个数据节点为0号下标
     public boolean addIndex(int index,int data);
     //查找是否包含关键字key是否在单链表当中
     public boolean contains(int key);
     //删除第一次出现关键字为key的节点
     public void remove(int key);
     //删除所有值为key的节点
     public void removeAllKey(int key);
     //得到单链表的长度
     public int size();
    //清空链表
     public void clear();
 }

定义一个节点,一个放值,一个放他指向下一个节点的地址
在这里插入图片描述大致就是这样子的一种链表,一个指一个
在这里插入图片描述

把第一个定义为头结点
在这里插入图片描述

注意,头不能移动,所以我们遍历要重新给头定义一个变量

class ListNode{  //定义一个节点
    public int val; //
    public ListNode next; //指向后一个节点

    public ListNode(int val){  //构造方法
        this.val = val;
    }
}


public class MyLinkedList{

    public ListNode head; //定义一个头结点

    //打印链表
public void display(){
    ListNode cur = this.head; //重新定义一个头结点,让源头节点不动
    while(cur != null){   //遍历链表
        System.out.print(cur.val+" ");  //打印链表
        cur = cur.next; //走向下一个节点
    }
    System.out.println(); // 换行
}

//获得链表长度
public int size(){
    ListNode cur = this.head;
    int count = 0;  //定义一个计数量
    while(cur != null){
        count++; //遍历一个加一个
        cur = cur.next;
    }
    return count; //返回遍历的长度
}

//判断链表中是否含有关键字key
    public boolean contains(int key){
    ListNode cur = this.head;
    while(cur != null){
        if(cur.val == key){  //如果等于要找的关键字
            return true; //返回正确
        }
        cur = cur.next;
    }
    return false;  //遍历完都没有找到,返回false
    }

    //头插法
    public void addFirst(int data){
    ListNode node = new ListNode(data);  //定义要插的节点
    node.next = this.head;  //要插的节点的下一个节点地址先指向头
    this.head = node;       //要插节点变成新头
    }

    //尾插法
    public void addLast(int data){

    ListNode node = new ListNode(data);
    if(this.head == null){   //头结点为空
        this.head = node;    //直接变成头插进去
    }else{
        ListNode cur = this.head;
        while(cur.next != null){   //遍历到最后一个节点,因为最后一个节点的下一个指向是空
            cur = cur.next;
        }
        cur.next = node; //最后节点下一个指向变成node,让node变成最后一个节点
    }
    }

    /**
     * 找到增加元素的前一个节点
     * @param index
     * @return
     */
    public ListNode findIndex(int index){
    ListNode cur = this.head;
    while(index - 1 != 0){  //找到要增加位置前一个节点
        cur = cur.next;
        index--;
    }
    return cur;      //返回找到的节点
    }

    //在任意位置增加元素,初始元素为0下标
    public void addIndex(int index,int data){
        if(index < 0 || index > size()){  
            System.out.println("index 位置不合法!");
            return;
        }
        if(index == 0){  //头插法
addFirst(data);
return;
        }
        if(index == size()){  //尾插法
            addLast(data);
            return;
        }
        ListNode cur = findIndex(index);  //找到的节点
    ListNode node = new ListNode(data);   //要插的节点
node.next = cur.next;    //前一个节点下一个地址给现在插进去的节点的下一个地址
cur.next = node;        //让前一个节点下一个地址变为现在插的节点地址
    }

    /**
     * 找到要删除关键字的前驱
     * @param key
     * @return
     */
    public ListNode search(int key){
        ListNode cur = this.head;
        while(cur.next != null){    
            if(cur.next.val == key){   //cur的下一个节点的值跟要删的一样
                return cur;    //返回cur
            }
            cur = cur.next;
        }
        return null;  //没有要删的关键字
    }

    //删除第一次出现的关键字key
    public void remove(int key){
        if(this.head == null){
            System.out.println("单链表为空,不能删除!");
            return;
        }
        if(this.head.val == key){  //头结点是要删的
            this.head = this.head.next;  //头结点变为下一个
            return;
        }
        ListNode cur = search(key);
        if(cur == null){  //没找到
            System.out.println("没有你要删的数!");
            return;
        }
            ListNode del = cur.next;  //要删的节点
            cur.next = del.next;    //让要删的前一个节点指向要删的后一个节点,这要要删的节点就没人引用,就删除了,被jvm回收
    }

    //删除所有关键字key
    public ListNode removeAllKey(int key){
        if(this.head == null){
            return null;
        }
        ListNode prev = this.head;  //定义头结点
        ListNode cur = this.head.next;  //定义头结点的下一个节点
        while(cur != null){ //遍历
            if(cur.val == key){  //找到要删的key
                prev.next = cur.next; //直接让前一个节点指向后一个节点
                cur = cur.next; //cur跳到后一个节点
            }else{
                prev = cur;  //前一个不删,prev跳过去
                cur = cur.next; //cur跟着跳
            }
        }
        if(this.head.val == key){   //特殊情况,头结点是要删的,特殊处理
            this.head = this.head.next;
        }
        return this.head;
    }

    //清空链表
    public void clear(){
        while(this.head != null){
            ListNode curNext = this.head.next;  
            this.head.next = null;
            this.head = curNext;
        }
    }
}

双链表无头循环

跟单链表差不多

// 2、无头双向链表实现
public class DoubleLinkedList {
     //头插法
     public void addFirst(int data);
     //尾插法
     public void addLast(int data);
     //任意位置插入,第一个数据节点为0号下标
     public boolean addIndex(int index,int data);
     //查找是否包含关键字key是否在单链表当中
     public boolean contains(int key);
     //删除第一次出现关键字为key的节点
     public void remove(int key);
     //删除所有值为key的节点
     public void removeAllKey(int key);
     //得到单链表的长度
     public int size();
     public void display();
     public void clear();
 }

在这里插入图片描述

class ListNode{  //定义一个节点
    public int val; //
    public ListNode prev; //指向前一个节点  
    public ListNode next; //指向后一个节点

    public ListNode(int val){  //构造方法
        this.val = val;
    }
}


public class MyDoubleLinkedList {

    public ListNode head;
    public ListNode last;  //定义尾结点

    //打印链表
    public void display() {
        ListNode cur = this.head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    //获得链表长度
    public int size() {
        ListNode cur = this.head;
        int count = 0;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    //判断链表中是否含有key
    public boolean contains(int key) {
        ListNode cur = this.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);   
        if (this.head == null) { //防止prev为空,造成空指针异常
            this.head = node;
            this.last = node;
        } else {
            node.next = this.head;
            this.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 {
            this.last.next = node;
            node.prev = this.last;
            this.last = node;
        }
    }

    //找到要插的位置上的节点
    public ListNode findIndex(int index) {
        ListNode cur = this.head;
        while (index != 0) {
            cur = cur.next;
            index--;
        }
        return cur;
    }

    //任意位置插入key,第一个数据节点为0下标
    public void addIndex(int index, int data) {
        if (index < 0 || index > size()) {
            System.out.println("index 位置不合法!");
            return;
        }
        if (index == 0) {
            addFirst(data);
            return;
        }
        if (index == size()) {
            addLast(data);
            return;
        }
        ListNode cur = findIndex(index);
        ListNode node = new ListNode(data);
        node.next = cur;
        node.prev = cur.prev;
        cur.prev.next = node;
        cur.prev = node;
    }

    //删除第一次出现的key
    public void remove(int key) {
        ListNode cur = this.head;
        while (cur != null) {
            if (cur.val == key) {
                if (cur == this.head) {
                    this.head = this.head.next;
                }
                if (this.head != null) {
                    this.head.prev = null;
                } else {
                    this.last = null;
                }
            } else {
                cur.prev.next = cur.next;
                if (cur.next != null) {
                
                    cur.next.prev = cur.prev;
                } else {
                    this.last = this.last.prev;
                }
            }
            return;
        }
        cur = cur.next;
    }

    //删除所有出现的key
    public void removeAllKey(int key) {
        ListNode cur = this.head;
        while (cur != null) {
            if (cur.val == key) {
                if (cur == head) {
                    head = head.next;
                    if (head != null) {
                        head.prev = null;
                    } else {
                        last = null;
                    }
                } else {
                    cur.prev.next = cur.next;
                    if (cur.next != null) {
                        //中间位置
                        cur.next.prev = cur.prev;
                    } else {
                        last = last.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }

    //清空链表
    public void clear (){
        while(this.head != null){
            ListNode curNext = head.next;
            head.next = null;
            head.prev = null;
            head = curNext;
        }
        last = null;
    }
}

自用!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

粉色的志明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值