单链表:

链表是以节点的方式来存储数据的,是链式存储结构

每个节点包含datanextnext域指向下一个节点

链表的各个节点在内存中不一定是连续存储的

链表分为带头节点的链表和不带头节点的链表,根据实际需求来确定。

单链表图示:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_链式存储结构

 代码实现:

package dataStructureAtShangGuiGu;

public class LinkedListDemo {
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        LinkedNode linkedNode1 = new LinkedNode(1,"小明");
        LinkedNode linkedNode2 = new LinkedNode(2,"小李");
        LinkedNode linkedNode3 = new LinkedNode(3,"小王");
        myLinkedList.add(linkedNode1);
        myLinkedList.add(linkedNode2);
        myLinkedList.add(linkedNode3);
        myLinkedList.list();
    }
}
class MyLinkedList{
    private LinkedNode headNode = new LinkedNode(0,""); //头节点
    public void add(LinkedNode linkedNode) {
        LinkedNode tmp = headNode;
        while(null!=tmp.getNext()) { //遍历节点,若该节点的next若为null,则说明该节点是链表最后一个节点
            tmp = tmp.getNext(); //
        }
        tmp.setNext(linkedNode);//将该节点连接到链表尾部
    }
    public void list() {
        if(null==headNode.getNext()) {
            System.err.println("链表为空");
            return;
        }
        LinkedNode tmp = this.headNode.getNext();
        while(null!=tmp) { 
            System.out.println(tmp);
            tmp = tmp.getNext(); 
        }
    }
}
class LinkedNode {
    private int no;
    private String name;
    private LinkedNode next;
    
    public LinkedNode(int no, String name) {
        this.no = no;
        this.name = name;
    }
    public LinkedNode getNext() {
        return next;
    }
    public void setNext(LinkedNode next) {
        this.next = next;
    }
    public int getNo() {
        return no;
    }
    public void setNo(int no) {
        this.no = no;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "LinkedNode [no=" + no + ", name=" + name +"]";
    }
    
}

运行测试:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_edn_02

 添加元素的时候希望按元素的no属性从小到大排序:

    public void addByOrder(LinkedNode linkedNode) {
        LinkedNode tmp = this.headNode;
        while(null!=tmp.getNext()) {
            if(linkedNode.getNo()==tmp.getNo()) {  //编号已经存在的情况
                System.err.println("链表已经存在[no=:"+linkedNode.getNo()+","+linkedNode.getName()+"]的元素");
                return;
            }
            if(linkedNode.getNo()<tmp.getNext().getNo()) break; //找到了
            tmp = tmp.getNext();
        }
        linkedNode.setNext(tmp.getNext()); //将添加的节点的next指向指针的下一个节点
        tmp.setNext(linkedNode); //将指针的next指向添加的节点
    }

这里我将元素顺序打乱后再添加,并添加相同的元素:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_链表_03

 运行测试:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_链表_04

 可以很直接地看到,元素存入单链表的时候是按照no属性排好序存放的,并且重复的元素不让其存入。

根据no属性查找节点并修改节点name属性

    public void update(LinkedNode linkedNode) { //根据编号查找节点并修改节点名称
        LinkedNode tmp = this.headNode.getNext();
        while(null!=tmp) { //遍历链表
            if(linkedNode.getNo()==tmp.getNo()) { //查找对应编号的元素
                tmp.setName(linkedNode.getName());
                return;
            }
            tmp = tmp.getNext();
        }
        System.err.println("没有找到编号为:"+linkedNode.getNo()+"的节点!");
    }

这里我修改no为2的节点的name属性:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_链表_05

 运行测试:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_运行测试_06

 可以看到,修改成功!

删除单链表中的某个节点

    public void delete(int no) {
        LinkedNode tmp = this.headNode;
        while(null!=tmp.getNext()) {
            if(tmp.getNext().getNo()==no) {
                tmp.setNext(tmp.getNext().getNext()); //关键点,让删除目标节点的前一个节点的next指向删除目标节点的next
                return;
            }
            tmp = tmp.getNext();
        }
        System.err.println("没有找到编号为:"+no+"的节点!");
    }

这里我删除几个节点:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_链式存储结构_07

 运行测试:

数据结构与算法(Java版)_05_单链表及其增、删、改、查_运行测试_08

完美删除!