JAVA数据结构——单链表

链表:

一、 顺序存储结构虽然是一种很有用的存储结构,但是他有如下几点局限性:

1. 因为创造线性表的时候已经固定了空间,所以当需要扩充空间时,就需要重新创建一个地址连续的更大的存储空间。并把原有的数据元素复制进新的存储空间。

2. 因为顺序表要求数据的存储位置不仅是逻辑上相邻而且物理存储上也要相邻,所以当对数据进行增删操作的时候则会引起平均一半的数据元素移动。

综上所述:适合静态存储、对数据元素很少增删操作,则优先选择顺序表,对需要对数据频繁执行插入和删除操作,则选择动态的线性表-链表,链式存储不需要逻辑上相邻的元素物理上也相邻,所以链表也带来了一定的局限性,失去了随机存取的特点。所以根据需求进行选择。

二、使用JAVA实现单链表:

接口同顺序表:

package com.usts.edu.list;

/**
 * Created by Guanzhong Hu
 * Date :2019/12/27
 * Description : 线性表
 * Version :1.0
 */
public interface Ilist {
 
//    将已存在的线性表置空
    public void clear();

//    判断是否为空
    public boolean isEmpty();

//    求线性表中数据元素个数并返回其值
    public int length();

//    读取第i个元素的值 区间:[0,length()-1]
    public Object get(int i) throws Exception;

//    插入元素,i表示插入的地址取值 区间:[0,length()-1],当为length()-1时,表示在表尾插入x
    public void insert(int i,Object x) throws Exception;

//    删除位于第i个的元素
    public void remove(int i) throws Exception;

//    返回线性表中元素第一次出现的index
    public int indexOf(Object x) throws Exception;

//    输出线性表中各个数据元素的值
    public void display();


}
package com.usts.edu.list;

/**
 * Created by Guanzhong Hu
 * Date :2019/12/27
 * Description :单链表
 * Version :1.0
 */
public class Node {
    /**
     * 采用链式存储方式存储的线性表成为单链表
     * 1. 链表中每一个结点包含存放数据元素值的数据域和存放指向逻辑上相邻结点的指针域
     * 2. 若节点中只包含一个指针域,则称此链表为单链表
     */
    public Object data;//存放结点值

    public Node next; // 存放逻辑指针

    public Node(){
        this(null,null);// 置空
    }
//  两个参数的单链表
    public Node(Object data, Node next) {
        this.data = data;
        this.next = next;
    }

    // 带一个参数的单链表
    public Node(Object data){
        this(data,null);
    }
}
package com.usts.edu.list;

import java.math.BigInteger;
import java.util.Scanner;

/**
 * Created by Guanzhong Hu
 * Date :2019/12/27
 * Description :实现单链表
 * Version :1.0
 */
public class LinkList implements Ilist {

    private  Node head;

    public LinkList() {
        head = new Node();// 生成空的单链表
    }

//  置空
    @Override
    public void clear() {
        head.data = null;
        head.next = null;
    }

    @Override
    public boolean isEmpty() {
        return head.next==null; // 头指针为null,则空
    }

    @Override
    public int length() {
        int length = 0;// 初始化length
        Node n = head.next; // 初始化头指针,进行遍历
        while (n != null){
            n = n.next; // 迭代遍历
            length++;
        }
        return length;
    }

    @Override
    public Object get(int i) throws Exception {
        Node n = head.next;
        int flag = 0;// 初始化查找参数,依次遍历寻找,当存在下一个头指针且flag = i时,则返回当前指针指向的下一个元素
        while (n != null && i > flag){
            n = n.next;
            flag++;
        }
        if (n==null|| i<flag){
            throw  new Exception("查找的第"+i+"个元素不存在!");
        }
        return n.data;
    }

    @Override
    public void insert(int i, Object x) throws Exception {
        Node p = head;
        int flag = -1; // 定义计数器,从-1开始,因为第一个元素的头指针是-1;
        while (p!=null&&flag<i-1){ //寻找第i个结点的前驱,如果前驱小于则可以插入,否则当前元素位置已经占
            p = p.next;// 已经指向当前结点的位置,需要后期插入成功后,指向下一个结点位置
            flag++;
        }
        if (p==null&&flag>i-1) throw new Exception("插入位置不合法");
        Node newNode = new Node(x);
        newNode.next = p.next; // 指向下一个结点位置
        p.next = newNode;// 将当前生成的结点(下一个结点指针,当前节点元素)存入p的上一个结点的下一个结点的指针中
    }

    @Override
    public void remove(int i) throws Exception {
        Node p = head;
        int flag = -1; // 同上
        while (p!=null&&flag<i-1){
            p = p.next;
            flag ++;
        }
        if (p==null&&flag>i-1) throw new Exception("删除位置不合法");
        p.next = p.next.next;// 将此节点的上一个节点的指针指向当前删除节点的下一个结点
    }

    @Override
    public int indexOf(Object x) throws Exception {
        Node p = head;
        int flag = -1;
        while (p!=null&&p.data.equals(x)){
            p = p.next;
            flag ++;
        }
        if (p!=null) return flag;
        return -1;

    }

    @Override
    public void display() {
        Node p = head.next;
//        如果指针含有下一个元素,则输出,并替换查询指针
        while (p!=null){
            System.out.print(p.data);
            p = p.next;
        }
        System.out.println();
    }
    //创建链表,测试使用
    public void createLinkList(int len) throws Exception{ // 头插法,创建len长度的链表
        Scanner scanner = new Scanner(System.in);
        for (int i = 0; i < len ; i++) {
            insert(0,scanner.next());
        }
    }
}
package com.usts.edu.list;

import java.util.Scanner;

/**
 * Created by Guanzhong Hu
 * Date :2019/12/27
 * Description : 测试单链表
 * Version :1.0
 */
public class ExampleLinkListTest {

    public static void main(String[] args) throws Exception {
        int len = 10;
        LinkList linkList = new LinkList();
//        利用for生成链表
        for (int i = 0; i < len ; i++) {
            linkList.insert(i,i);
        }
        System.out.println("请输入查找的值");
        int i = new Scanner(System.in).nextInt();
        if (i>0&&i<=len) System.out.println("第"+i+"个元素的直接前驱"+linkList.get(i-1));
        linkList.display();
        linkList.clear();
        linkList.display();
        linkList.insert(0,1);
        linkList.insert(1,21);
        linkList.display();
        linkList.remove(0);
        linkList.display();
    }
}

gitee源码地址:

https://gitee.com/jockhome/data_structure

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值