线性表概述及单链表的Java实现

简介: 线性表概述及单链表的Java实现一、线性表概述线性表是指一组数据元素之间具有线性关系的元素序列,它表现为:除第一个元素没有直接前驱元素、最后一个元素没有直接后继元素外,其余所有元素都有且仅有一个直接前驱元素和直接后继元素。

线性表概述及单链表的Java实现
一、线性表概述
线性表是指一组数据元素之间具有线性关系的元素序列,它表现为:除第一个元素没有直接前驱元素、最后一个元素没有直接后继元素外,其余所有元素都有且仅有一个直接前驱元素和直接后继元素。

根据存储结构的不同,线性表可以分为顺序存储和链式存储。

1、顺序存储
顺序存储结构是指用一段地址连续的存储单元依次存储线性表的数据元素。

数组就是采用顺序存储结构来存储的,数组元素的保存和读取操作的时间复杂度都是O(1),而插入和删除操作的时间复杂度为O(n),其优缺点如下:

优点 缺点
快速存取,时间复杂度O(1) 插入、删除时,时间复杂度较高为,O(n)
无需为表示元素之间的逻辑关系而增加额外的存储空间 存储空间固定,不易扩展,容易造成空间的浪费
2、链式存储
链式存储是指数据元素在内存空间中的存储地址可以是不连续的,元素之间的逻辑关系通过其附带的指示信息来进行关联。

单链表、双向链表、循环链表等都是采用链式存储结构进行存储的。

对于单链表来说,单个结点分为数据域和指针域,指针域附带的指示信息是下一个结点的存储地址。

单链表元素的读取、插入和删除的时间复杂度都是O(n),在插入和删除的操作上,如果我们不知道所要操作结点的指针,那么相比顺序存储结构的数组没有优势,在知道要操作结点的指针的情况下,对于插入或删除越频繁,单链表的效率优势就越明显。

比如插入10个元素,对于数组来说,每插入一个元素都要移动n-1个结点,每次的时间复杂度都是O(n),而对于单链表来说,只需要在第一次插入时找到目标位置结点的指针,后续插入都只需要通过移动指针来完成,时间复杂度为O(1)。

二、单链表的Java实现
1、定义单链表的存储结构
public class Node {

E element;
Node next;

Node() {
}

Node(E e) {
    this.element = e;
    this.next = null;
}

}
一个Node结点包含两个属性,E element为存储的数据,指定为泛型;Node next为逻辑上的下一个结点的存储地址。

2、定义操作接口
public interface Collection {

void add(E e);

void insert( E e, int index);

void delete(int index);

E get(int index);

void modify( E e,int index);

boolean isEmpty();

int size();

}
为集合、列表类操作定义一个包含公有行为的接口。

3、实现单链表
单链表的插入和删除操作可以抽象成两个步骤:

(1)找到目标结点

通过头节点进行遍历,直到找到目标结点;

(2)插入或删除;

插入:

//front为index - 1结点,即要插入位置的前一个结点
node.next = front.next;
front.next = node;
删除:

//front为index - 1结点,即要删除位置的前一个结点
node = front.next;
front.next = node.next;
//释放node结点
node = null;
单链表完整实现如下:

public class LinkedList implements Collection {

/**
 * 头指针
 */
private Node<E> head;

/**
 * 尾指针
 */
private Node<E> tail;

private int size;

public LinkedList() {
    //初始化时创建空的头指针和尾指针,并指向同一个节点,后续增加元素时,尾指针后移,但头指针一直不变
    head = new Node<E>();
    tail = head;
    size = 0;
}

@Override
public void add(E e) {
    Node node = new Node<E>(e);
    //设置尾指针的下一个节点为node
    tail.next = node;
    //设置node为新的尾指针
    tail = node;
    //长度+1
    size++;
}

@Override
public void insert(E e, int index) {
    verifyIndex(index, size);
    Node node = new Node<E>(e);
    //先遍历找到index-1结点,然后在index-1结点插入,复杂度O(n)
    int i = 0;
    //index - 1结点
    Node front = head;
    while (i < index) {
        front = front.next;
        i++;
    }
    node.next = front.next;
    front.next = node;
    size++;
    System.out.println(this.toString());
}

@Override
public void delete(int index) {
    verifyIndex(index, size - 1);
    //找到index-1节点
    int i = 0;
    Node front = head;
    while (i < index) {
        front = front.next;
        i++;
    }
    Node target = front.next;
    front.next = target.next;
    target = null;
    size--;
    System.out.println(this.toString());
}

@Override
public E get(int index) {
    verifyIndex(index, size - 1);
    Node node = head;
    int i = 0;
    while (i <= index) {
        node = node.next;
        i++;
    }
    return (E) node.element;
}

@Override
public void modify(E e, int index) {
    verifyIndex(index, size - 1);
    Node node = head;
    int i = 0;
    while (i <= index) {
        node = node.next;
        i++;
    }
    node.element = e;
    System.out.println(this.toString());
}

@Override
public boolean isEmpty() {
    return size <= 0;
}

@Override
public int size() {
    return 0;
}

/**
 * 判断操作的索引是否合法,
 * @param index
 * @param end   右边界,插入时允许在末尾插入,即end = size
 * @return
 */
private void verifyIndex(int index, int end) {
    if (index < 0 || index > end) {
        throw new IndexOutOfBoundsException("invalid index for LinkedList:" + this.toString());
    }
}

@Override
public String toString() {
    Node node = head;
    StringBuilder stringBuilder = new StringBuilder();
    while (node.next != null) {
        node = node.next;
        stringBuilder.append(node.element + " ");
    }
    return stringBuilder.toString();
}

}
Github下载地址
原文地址https://www.cnblogs.com/sqchen/p/10778472.html

相关文章
|
13天前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
24 6
|
1月前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
4月前
|
Java
环形数组链表(java)
环形数组链表(java)
|
4月前
|
算法
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
43 0
|
1月前
|
安全 Java API
Java 18 概述:新特性一览
Java 18 作为 Java 平台的最新版本,引入了多项令人振奋的新特性和改进,包括模式匹配、记录类型、流库改进、外部函数与内存 API 以及并发处理增强。这些新功能不仅提升了开发者的生产力,还显著增强了 Java 的性能和安全性。本文将详细介绍 Java 18 的主要新特性,并通过代码示例帮助读者更好地理解和应用这些功能。
|
1月前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
2月前
|
存储 Oracle Java
01 Java概述基础与计算机基础(DOS+进制+原码反码补码)
01 Java概述基础与计算机基础(DOS+进制+原码反码补码)
39 17
|
2月前
|
存储 算法 Oracle
19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)
19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)
63 8
|
2月前
|
Java 数据安全/隐私保护
09 Java面向对象三大特征(概述)
09 Java面向对象三大特征(概述)
65 4
|
2月前
|
存储 Java 开发者
揭秘!HashMap底层结构大起底:从数组到链表,再到红黑树,Java性能优化的秘密武器!
【8月更文挑战第24天】HashMap是Java集合框架中的核心组件,以其高效的键值对存储和快速访问能力广受开发者欢迎。在JDK 1.8及以后版本中,HashMap采用了数组+链表+红黑树的混合结构,实现了高性能的同时解决了哈希冲突问题。数组作为基石确保了快速定位;链表则用于处理哈希冲突;而当链表长度达到一定阈值时,通过转换为红黑树进一步提升性能。此外,HashMap还具备动态扩容机制,当负载因子超过预设值时自动扩大容量并重新哈希,确保整体性能。通过对HashMap底层结构的深入了解,我们可以更好地利用其优势解决实际开发中的问题。
81 0