数据结构单链表的算法描述_数据结构创建单链表及其实现

数据结构单链表的算法描述_数据结构创建单链表及其实现一、什么是链表链表是一种数据结构,跟数组不同,链表不需要连续的内存空间,而是通过指针将零散的内存块连接起来。因此,链表的查找需要通过节点按顺序遍历,而增加与删除通过只需要操作指针指向,这也造成了相

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一、什么是链表

链表是一种数据结构,跟数组不同,链表不需要连续的内存空间,而是通过指针将零散的内存块连接起来。

因此,链表的查找需要通过节点按顺序遍历,而增加与删除通过只需要操作指针指向,这也造成了相比数组,链表的查找性能消耗大增加和删除消耗小的特点。

链表由节点组成,一般每个节点最少包含用于储存数据的data区和用于指向下一个节点的指针next,有的链表可能会有头结点或尾结点用于存储链表长度等信息。

数据结构单链表的算法描述_数据结构创建单链表及其实现

二、链表的简单实现

先来实现一个简单的节点类:

/**
 * @Author:huang
 * @Date:2020-06-20 10:19
 * @Description:节点类
 */
public class Node {

    //节点序号
    int num;

    //数据
    Object data;

    //下一个节点
    Node next;

    public Node(int num, Object data) {
        this.num = num;
        this.data = data;
    }
    
    public int getNum() {
        return num;
    }

    public Object getData() {
        return data;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void setData(Object data) {
        this.data = data;
    }
    
    @Override
    public String toString() {
        return "Node{" +
            "num=" + num +
            ", data=" + data +
            '}';
    }
}

1.插入节点

1.1不按照排序的插入

/**
 * @Author:huang
 * @Date:2020-06-20 10:19
 * @Description:单链表
 */
public class SingleLinkList {
	//默认初始化一个头节点
    private Node head = new Node(0, "我是头结点");

    /**
     * 添加节点到链表
     * @param node
     */
    public void add(Node node) {
        Node temp = head;
        //遍历链表
        while (true) {
            if (temp.next == null) {
                break;
            }
            //不是尾节点就继续遍历下一个节点
            temp = temp.next;
        }
        //将尾节点指向即将插入的新节点
        temp.next = node;
    }
}

1.2按照排序插入

数据结构单链表的算法描述_数据结构创建单链表及其实现

要想按顺序插入节点,需要确定节点的位置,也就是确定新节点的大小,以图为例:

遍历链表,我们把遍历到的节点叫A,A之前的节点叫A-1,A之后的节点叫A+1,要插入的节点叫B,有以下几种情况:

  1. 当A的序号大于B时,就把B插到A前,也就是原本的A和A-1之间
  2. 当A的序号等于B时,抛出异常禁止插入
  3. 当A的序号小于B时,就跳过这个节点,继续遍历,然后对比A+1和B的大小
  4. 当A就是链表最后一个节点时,A还是小于B,那就直接让B插到A后,变成链表的尾节点

按这个思路,我们在原来的类里新增一个方法:

/**
 * 按顺序添加节点到链表
 * @param node 要插入的节点
 */
public void addByOrder(Node node) {
    Node temp = head;
    //遍历链表
    while (true) {
        //如果链表到底了就直接插入
        if (temp.next == null) {
            temp.next = node;
            return;
        }else if (temp.next.num > node.num){
            //如果当前节点比当要插入的节点大,就把新节点插到当前节点之前
            node.next = temp.next;
            temp.next = node;
            return;
        }else if (temp.next.num == node.num){
            //如果有节点序号和要插入的节点重复就抛异常
            throw new RuntimeException("插入节点与已有节点序号重复!");
        }
        //如果当前节点比当要插入的节点小,就继续遍历
        temp = temp.next;
    }
}

2.查找节点

/**
 * 展示链表全部节点
 */
public void show() {
    //判断链表是否为空
    if (head.next == null) {
        throw new RuntimeException("链表为空!");
    }
    Node temp = head.next;
    //遍历链表
    while (true) {
        if (temp == null) {
            break;
        }
        System.out.println(temp.toString());
        temp = temp.next;
    }
}

/**
 * 根据序号获取节点
 * @param num 要获取的节点序号
 * @return
 */
public Node get(int num){
    //判断链表是否为空
    if (head.next == null) {
        throw new RuntimeException("链表为空!");
    }
    Node temp = head.next;
    //遍历链表
    while (true) {
        if (temp == null) {
            throw new RuntimeException("编号为" + num + "的节点不存在!");
        }
        //如果是要获取的节点
        if (temp.num == num) {
            return temp;
        }
        temp = temp.next;
    }
}

3.修改节点

修改节点与按顺序插入逻辑相似,需要先遍历并找到要修改的节点,然后用新节点去替换旧节点,或者干脆直接修改节点内的信息

数据结构单链表的算法描述_数据结构创建单链表及其实现

/**
 * 修改节点
 * @param node 要更新的节点
 */
public void update(Node node) {
    Node temp = head;
    //判断链表是否为空
    if (temp.next == null) {
        throw new RuntimeException("链表为空!");
    }
    //获取要更新的节点序号
    int nodeNum = node.num;
    //遍历链表
    while (true) {
        //如果已经遍历完链表
        if (temp == null) {
            throw new RuntimeException("编号为" + temp.num + "的节点不存在!");
        }
        //如果找到了该节点
        if (temp.num == nodeNum) {
            temp.data = node.data;
            return;
        }
        //继续遍历下一节点
        temp = temp.next;
    }
}

4.删除节点

数据结构单链表的算法描述_数据结构创建单链表及其实现

因为在单向链表中,节点无法知道自己前一个节点的情况,以图为例:

如果我们想要删除节点A,那么就要找到A的前一个节点A-1,根据是否存在A后的节点A+1有以下几种情况:

  1. A节点就是链表尾节点,此时只需让A-1节点的next指向null即可

    nodeA-1.next = null

  2. A节点后有A+1,此时让A-1节点指向A+1节点

    nodeA-1.next = nodeA-1.next.next

按这个思路,在类里新加一个方法:

/**
 * 删除节点
 * @param num 要删除的节点编号
 */
public void delete(int num) {
    Node temp = head;
    //判断链表是否为空
    if (temp.next == null) {
        throw new RuntimeException("链表为空!");
    }
    //遍历链表
    while (true) {
        //如果链表到底了
        if (temp.next == null) {
            throw new RuntimeException("编号为" + num + "的节点不存在!");
        }
        //如果找到了待删除节点的前一个节点
        if (temp.next.num == num) {
            //判断待删除节点是否为尾节点
            if (temp.next.next == null){
                temp.next = null;
            }else {
                temp.next = temp.next.next;
            }
            return;
        }
        //继续遍历下一节点
        temp = temp.next;
    }
}

三、完整实现代码

/**
 * @Author:huang
 * @Date:2020-06-20 10:19
 * @Description:单链表
 */
public class SingleLinkList {

    private Node head = new Node(0, "我是头结点");

    /**
     * 添加节点到链表
     * @param node 要插入的节点
     */
    public void add(Node node) {
        Node temp = head;
        //遍历链表
        while (true) {
            if (temp.next == null) {
                break;
            }
            //不是尾节点就继续遍历下一个节点
            temp = temp.next;
        }
        //将尾节点指向即将插入的新节点
        temp.next = node;
    }

    /**
     * 展示链表
     */
    public void show() {
        //判断链表是否为空
        if (head.next == null) {
            throw new RuntimeException("链表为空!");
        }
        Node temp = head.next;
        //遍历链表
        while (true) {
            if (temp == null) {
                break;
            }
            System.out.println(temp.toString());
            temp = temp.next;
        }
    }

    /**
     * 根据序号获取节点
     * @param num 要获取的节点序号
     * @return
     */
    public Node get(int num){
        //判断链表是否为空
        if (head.next == null) {
            throw new RuntimeException("链表为空!");
        }
        Node temp = head.next;
        //遍历链表
        while (true) {
            if (temp == null) {
                throw new RuntimeException("编号为" + num + "的节点不存在!");
            }
            if (temp.num == num) {
                return temp;
            }
            temp = temp.next;
        }
    }

    /**
     * 按顺序添加节点到链表
     * @param node 要插入的节点
     */
    public void addByOrder(Node node) {
        Node temp = head;
        //遍历链表
        while (true) {
            //如果链表到底了就直接插入
            if (temp.next == null) {
                temp.next = node;
                return;
            }
            else if (temp.next.num > node.num){
                //如果后一节点比当新节点大,就插入当前节点
                node.next = temp.next;
                temp.next = node;
                return;
            }else if (temp.next.num == node.num){
                //如果后一节点等于新节点,抛异常
                throw new RuntimeException("插入节点与已有节点序号重复!");
            }
            //如果后一节点比当前节点小,就继续遍历
            temp = temp.next;
        }
    }

    /**
     * 修改节点
     * @param node 要更新的节点
     */
    public void update(Node node) {
        Node temp = head;
        //判断链表是否为空
        if (temp.next == null) {
            throw new RuntimeException("链表为空!");
        }
        //获取要更新的节点序号
        int nodeNum = node.num;
        //遍历链表
        while (true) {
            //如果已经遍历完链表
            if (temp == null) {
                throw new RuntimeException("编号为" + temp.num + "的节点不存在!");
            }
            //如果找到了该节点
            if (temp.num == nodeNum) {
                temp.data = node.data;
                return;
            }
            //继续遍历下一节点
            temp = temp.next;
        }
    }

    /**
     * 删除节点
     * @param num 要删除的节点编号
     */
    public void delete(int num) {
        Node temp = head;
        //判断链表是否为空
        if (temp.next == null) {
            throw new RuntimeException("链表为空!");
        }
        //遍历链表
        while (true) {
            //如果链表到底了
            if (temp.next == null) {
                throw new RuntimeException("编号为" + num + "的节点不存在!");
            }
            //如果找到了待删除节点的前一个节点
            if (temp.next.num == num) {
                //判断待删除节点是否为尾节点
                if (temp.next.next == null){
                    temp.next = null;
                }else {
                    temp.next = temp.next.next;
                }
                return;
            }
            //继续遍历下一节点
            temp = temp.next;
        }
    }
}

四、环形链表

循环链表是一种特殊单链表,他跟单链表的区别在于尾节点的尾指针指向了链表的头结点,也就是相当于将链表连接成了一个环形。

环形链表可以用于处理能描述为环形的数据,典型的比如约瑟夫问题。

数据结构单链表的算法描述_数据结构创建单链表及其实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/170818.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • getElementById的用法

    getElementById的用法    getElementById是通过Id来设置/返回HTML标签的属性及调用其事件与方法。用这个方法基本上可以控制页面所有标签,条件很简单,就是给每个标签分配一个ID号。    返回具有指定ID属性值的第一个对象的一个引用。    语法:    Element=document.getElementByIdx_x_x(“id”)    …

    2022年7月15日
    19
  • idea202112激活码永久【在线注册码/序列号/破解码】

    idea202112激活码永久【在线注册码/序列号/破解码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
    35
  • java 仓库管理系统源码[通俗易懂]

    java 仓库管理系统源码[通俗易懂]系统操作权限管理。系统提供基本的登入登出功能,同时系统包含两个角色:系统超级管理员和普通管理员,超级管理员具有最高的操作权限,而普通管理员仅具有最基本的操作权限,而且仅能操作自己被指派的仓库。 请求URL鉴权。对于系统使用者登陆后进行操作发送请求的URL,后台会根据当前用户的角色判断是否拥有请求该URL的权限。 基础数据信息管理。对包括:货物信息、供应商信息、客户信息、仓库信息在内的基础数据信…

    2022年9月23日
    0
  • APP性能测试工具——GT 使用方法

    APP性能测试工具——GT 使用方法参考链接:https://www.cnblogs.com/syw20170419/p/7228145.html?utm_source=itdadao&utm_medium=referralGT官方使用介绍文档地址:https://gt.qq.comGT(随身调)是APP的随身调测平台,它是直接运行在手机上的“集成调测环境”(IDTE,IntegratedDebugEnvi…

    2022年6月28日
    52
  • BEC translation exercise 7

    BEC translation exercise 7

    2022年3月12日
    35
  • spring boot 系列之二:spring boot 如何修改默认端口号和contextpath「建议收藏」

    上一篇文件我们通过一个实例进行了springboot入门,我们发现tomcat端口号和上下文(contextpath)都是默认的,如果我们对于这两个值有特殊需要的话,需要自己制定的时候怎么办呢

    2022年2月16日
    29

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号