一、线性表概述

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

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

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> {
E element;
Node next; Node() {
} Node(E e) {
this.element = e;
this.next = null;
}
}

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

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

    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<E> implements Collection<E> {

    /**
* 头指针
*/
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下载地址

线性表概述及单链表的Java实现的更多相关文章

  1. javascript实现数据结构与算法系列:线性表的静态单链表存储结构

    有时可借用一维数组来描述线性链表,这就是线性表的静态单链表存储结构. 在静态链表中,数组的一个分量表示一个结点,同时用游标(cur)代替指针指示结点在数组中的相对位置.数组的第0分量可看成头结点,其指 ...

  2. 正整数构成的线性表存放在单链表中,编写算法将表中的所有的奇数删除。(C语言)

    /* 正整数构成的线性表存放在单链表中,编写算法将表中的所有的奇数删除 */ #include <stdio.h> #include <stdlib.h> typedef st ...

  3. PHP数据结构之三 线性表中的单链表的PHP实现

    线性表的链式存储:用一组任意的存储单元存储线性表中的数据元素.用这种方法存储的线性表简称线性链表. 链式存储线性表的特点:存储链表中结点的一组任意的存储单元可以是连续的,也可以是不连续的,甚至是零散分 ...

  4. 线性表:实现单链表和子类栈(Stack)及单向队列(Queue) [C++]

    刚刚开始学习c++.之前c的内容掌握的也不多,基本只是一本概论课的程度,以前使用c的struct写过的链表.用python写过简单的数据结构,就试着把两者用c++写出来,也是对c++的class,以及 ...

  5. ytu 2231: 交集问题(线性表)(数据结构,链表练习)

    2231: 交集问题(线性表) Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 6  Solved: 3[Submit][Status][Web Boar ...

  6. 单链表数据结构 - java简单实现

    链表中最简单的一种是单向链表,每个元素包含两个域,值域和指针域,我们把这样的元素称之为节点.每个节点的指针域内有一个指针,指向下一个节点,而最后一个节点则指向一个空值.如图就是一个单向链表 一个单向链 ...

  7. 单链表之Java实现

    初次接触java,用java也写了一个链表.代码如下: import java.io.*; class Node{ public int data; //数据域 public Node next; / ...

  8. 单链表反转java代码

    据说单链表反转问题面试中经常问,而链表这个东西相对于数组的确稍微难想象,因此今天纪录一下单链表反转的代码. 1,先定义一个节点类. public class Node { int index; Nod ...

  9. 使用java实现单链表----(java中的引用就是指针)

    //一直以为java中没有指针,其实java的引用就是指针,只不过堆栈中的引用储存了在堆中的地址,可以看做java中的指针.public class sibgleLink<E> { // ...

随机推荐

  1. 百度技术沙龙之2013-2&3

    2013年2月2日技术沙龙 商业产品开发------谢马林 业务逻辑加大设计难度 集成难度大 降低学习成本 统一标准化开发模式 面向集成的架构平台 业务复杂,设计抽象的技术支撑不够 抽象6类数据流业务 ...

  2. AngularJS - 使用RequireJS还是Browserify?

    http://www.html-js.com/article/2126 AngularJS - 使用RequireJS还是Browserify? AngularJS之所以吸引了很多开发者的关注,很大一 ...

  3. (二)SpringBoot基础篇- 静态资源的访问及Thymeleaf模板引擎的使用

    一.描述 在应用系统开发的过程中,不可避免的需要使用静态资源(浏览器看的懂,他可以有变量,例:HTML页面,css样式文件,文本,属性文件,图片等): 并且SpringBoot内置了Thymeleaf ...

  4. 架构之高可用性(HA)集群(Keepalived)

    Keepalived简介 Keepalived是Linux下一个轻量级别的高可用解决方案.高可用(High Avalilability,HA),其实两种不同的含义:广义来讲,是指整个系统的高可用行,狭 ...

  5. C#之Redis为所欲为

    一 Redis是一种支持多种数据结构的键值对数据库 1.1Redis下载地址 :https://github.com/MicrosoftArchive/Redis 建议下载 .msi结尾的应用程序进行 ...

  6. Java MD5加密与RSA加密

    区别: MD5加密: 加密时通过原字符串加密成另一串字符串 解密时需要原加密字符串进行重新加密比较两次加密结果是否一致 T=RSA加密: 加密时通过原字符串生成密钥对(公钥+私钥) 解密时通过公钥和私 ...

  7. Linux下的磁盘分区和逻辑卷

    一.硬盘接口类型 硬盘的接口主要有IDE.SATA.SCSI .SAS和光纤通道等五种类型.其中IDE和SATA接口硬盘多用于家用产品中,也有部分应用于服务器,SATA是一种新生的硬盘接口类型,已经取 ...

  8. PAT1126:Eulerian Path

    1126. Eulerian Path (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue In grap ...

  9. PAT1120: Friend Numbers

    1120. Friend Numbers (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Two in ...

  10. spring+jotm+ibatis+mysql实现JTA分布式事务

    1 环境 1.1 软件环境  spring-framework-2.5.6.SEC01-with-dependencies.zip ibatis-2.3.4 ow2-jotm-dist-2.1.4-b ...