数据结构(一):单链表(Linked List)

数据结构(一):链表(Linked List)

1.链表是以结点的方式来存储的;
2.每个结点包含①data域:存储数据 ②next域:指向下一个结点
3.链表的各个结点在内存中不一定是连续存储的,但是它存储的内容是有序的(按照你添加结点的顺序)
4.链表包块带头结点和不带头结点两种

结点形式如下:
class Node{
	int data;
	Node next = null;
	public Node(int data){
        this.data = data;
	}
}
链表在内存中存储形式(物理结构)如下:

在这里插入图片描述

单链表(带头结点)逻辑结构图如下:

在这里插入图片描述

java:单链表(不带头结点)的实现
package com.study;

//节点
class Node {
    int data;
    Node next = null;

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

//单链表
class MyLinkList {
    Node head = null;//链表头引用:作用等同于头指针
    
    /*
     * 尾插法:单链表中插入节点,在末尾位置插入
     * */
    public void addNodeTail(int data) {
        Node newNode = new Node(data);//传入数据,实例化一个节点,用于添加。
        if (head == null) {//头结点指向为空,说明该链表为空
            head = newNode;
            return;
        }
        Node temp = head;//作用等同于指针
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;//将新节点加入到链表
    }

    /*
     * 头插法:单链表插入结点,在表头插入
     * */
    public void addNodeHead(int data) {
        Node newNode = new Node(data);
        if (head == null) {//链表为空
            head = newNode;
            return;
        }
        Node temp = head;
        newNode.next = temp;
        head = newNode;
    }

    /*
     * @param index:删除第index个节点
     * */
    public boolean delete(int index) {
        if (index < 1 || index > length()) {//避免了当index=0且链表为空的情况;避免了输入index超出节点数;验证了index不能为负数;
            return false;
        }
        while (index == 1) {//不带头结点的单链表删除第一个结点的情况,要特殊处理
            head = head.next;
            return true;
        }
        Node preNode = head;
        Node curNode = preNode.next;
        int i = 1;
        while (curNode != null) {
            if (i == index) {
                preNode.next = curNode.next;
                return true;
            }
            preNode = curNode;
            curNode = preNode.next;
            i++;
        }

        return false;
    }

    /*
     * @return:返回节点的长度
     * */
    public int length() {
        int length = 0;
        Node temp = head;
        if (temp != null) {
            length++;
            temp = temp.next;
        }
        return length;
    }

    /*
     * 遍历单链表
     * */
    public void printLinkList() {
        Node temp = head;
        if(temp==null){
        	System.out.println("链表为空");
        }
        while (temp != null) {
            System.out.println(temp.data);
            temp = temp.next;
        }
    }
}

public class LinkListDemo {
    public static void main(String[] args) {
        MyLinkList myLinkList = new MyLinkList();
        myLinkList.addNodeHead(1);//头插法
        myLinkList.printLinkList();//打印
        myLinkList.addNodeTail(10);//尾插法
        myLinkList.printLinkList();//打印
        myLinkList.delete(1);//删除第一个节点
        myLinkList.printLinkList();//d打印
        System.out.println(myLinkList.length());//长度
    }
}

打印结果:

在这里插入图片描述

java:单链表(带头结点)的实现
package com.study;
//节点
class Node {
    int data;
    Node next = null;

    public Node(int data) {
        this.data = data;
    }
}
//单链表
class MyLinkList2{
    Node head = new Node(0);//头结点,数据域存储什么无所谓

    /*
     * 头插法
     * */
    public void addNodeHead(int data){
        Node newNode = new Node(data);
        Node temp = head;
        newNode.next = temp.next;
        temp.next = newNode;//这里我们和上面不带头结点的头插法比较,发现此处根本不需要考虑链表是否为空的情况。不管是否为空,写法都一样。
    }

    /*
     * 尾插法
     * */
    public void addNodeTail(int data){
        Node newNode = new Node(data);
        Node temp = head;
        while(temp.next != null){
            temp = temp.next;
        }
        temp.next = newNode;
    }

    /*
     * 删除第index个结点
     * */
    public boolean delete(int index){
        if(index < 0 || index > length()){
            return false;
        }
        Node temp = head;
        Node preNode = temp;
        Node curNode = preNode.next;
        int i = 1;
        while(temp.next != null){
            if(i == index){
                preNode.next = curNode.next;
                break;
            }
            preNode = curNode;
            curNode = preNode.next;
            i++;
        }
        return true;
    }

    /*
     * @return:单链表长度
     * */
    public int length(){
        Node temp = head;
        int length = 0;
        while(temp.next != null){
            length++;
            temp = temp.next;
        }
        return length;
    }

    /*
     * 遍历单链表
     * */
    public void printLinkList(){
        Node temp = head;
        if(temp.next==null){
        	System.out.println("链表为空");
        }
        while(temp.next != null){
            temp = temp.next;
            System.out.println(temp.data);
        }
    }

}
//===================开始测试========================================
public class LinkListDemo2 {
    public static void main(String[] args) {
        MyLinkList2 myLinkList = new MyLinkList2();
        myLinkList.addNodeHead(1);//头插法
        myLinkList.printLinkList();//打印
        myLinkList.addNodeTail(10);//尾插法
        myLinkList.printLinkList();//打印
        myLinkList.delete(1);//删除第一个节点
        myLinkList.printLinkList();//d打印
        System.out.println(myLinkList.length());//长度

    }
}

打印结果:

在这里插入图片描述

链表结点的删除讲解(后面截图里面的说明有点小问题,以下面的文字说明为准)

我们现在以删除第二个结点,(称为结点b)为例子,方法:先连后断。

步骤①:先用一个指针p指向结点a;

步骤②:再用指针q指向结点c;

步骤③:然后令p.next =q;

①②两步就是“连”,③就是“断”。

有人会问,为啥不直接head.next = head.next.next;这样的确是可以,但是假如我现在要删除的是结点m,那么我们怎么写??这个时候,我么那就没法知道要next多少次了。所以必须要有个指针p,利用while循环,用来替代head的作用,同时也是因为head是指向头结点的,不能随意变动它。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值