线性表是一种简单的数据类型,它是具有相同类型的n个数据元素组成的有限序列。形如如A0,A1,...,An-1。大小为0的表为空表,称Ai后继Ai-1,并称Ai-1前驱Ai

printList打印出表元素,makeEmpty置空表,find返回某一项首次出现的位置,insert和remove一般是从表的某个位置插入和删除某个元素;而findKth则返回某个位置上的元素,next和previous会取一个位置作为参数返回前驱元和后继元的值。

表的数组实现

对表的所有操作都可以通过数组实现。数组的存储示意图如下:

这种存储结构的特点是:数据是连续的,随机访问速度快。printList以线性时间执行,findKth操作则话费常数时间。对于插入和删除来说效率是比较低下的,最坏情况下,在位置0的插入需要将所有元素向后移动一个位置。

基于数组的链表实现:

public class MyArrayList<T> implements Iterable<T>{

    private static final int DEFAULT_CAPACITY=10;
private int size;
private T[] items; public MyArrayList() {
doClear();
} public void clear() {
doClear();
} public int size() {
return size;
} public boolean isEmpty() {
return size == 0;
} public void trimToSize() {
ensureCapacity(size);
} public boolean add(T x) {
add(size, x);
return true;
} public void add(int idx, T x) {
if (items.length == size) {
ensureCapacity(size * 2 + 1);
}
for (int i = size; i > idx; i--) {
items[i] = items[i - 1];
}
items[idx] = x;
size++;
} public T remove(int idx) {
T removedItem = items[idx];
for (int i = idx; i < size - 1; i++) {
items[i] = items[i + 1];
}
size--;
return removedItem;
} private void doClear() {
size = 10;
ensureCapacity(DEFAULT_CAPACITY);
} private void ensureCapacity(int newCapacity) {
if (newCapacity < size) {
return;
}
T[] old = items;
items = (T[]) new Object[newCapacity];
for (int i = 0; i < size; i++) {
items[i] = old[i];
}
} public Iterator<T> iterator() {
return new ArrayListIterator();
} private class ArrayListIterator implements Iterator<T> {
private int current = 0; @Override
public boolean hasNext() {
return current < size;
} @Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
return items[current++];
} public void remove() {
MyArrayList.this.remove(--current);
}
}
}

单链表

当需要对表进行频繁的插入删除操作时,数组的实现方式就显得效率过低了。链表由一些列节点组成,这些节点不必在内存中相连。每一个节点均含有表元素和到包含该元素后继元的节点的链。单链表的存储示意图如下:

remove操作只需要移动next引用即可实现:

insert方法需要先添加一个节点,然后执行两次引用的调整:

单链表的特点:节点的链接方向是单向的;相对于数组,单链表的随机访问速度较慢,添加、删除效率较高

双向链表

双向链表与单向链表结构相似,由数据元素和两个链组成,这两个链分别指向该节点的前驱和后继。一般构建为双向循环链表,即最后一个节点的next链指向链表的第一个元素,第一个节点的previous链指向链表的最后一个元素。存储结构如下:

双向链表删除:

双向链表的添加就是删除的一个逆过程,不再画图了。

双向链表实现:

public class DoubleLink<T> {
// 表头
private Node<T> head;
// 节点数
private int count; private class Node<T> {
public Node prev; // 前节点
public Node next; // 后节点
public T value; public Node(T value, Node prev, Node next) {
this.prev = prev;
this.next = next;
this.value = value;
}
} public DoubleLink() {
// 创建表头
head = new Node<>(null, null, null);
head.prev = head.next = head;
count = 0;
} // 节点数
public int size() {
return count;
} // 判断表是否为空
public boolean isEmpty() {
return count == 0;
} // 获取第index位置的节点
private Node<T> getNode(int index) {
if (index < 0 || index >= count) {
throw new IndexOutOfBoundsException();
}
// 正向查找
if (index <= count / 2) {
Node<T> node = head.next;
for (int i = 0; i < index; i++) {
node = node.next;
}
return node;
}
// 反向查找
Node<T> rnode = head.prev;
int rindex = count - index - 1;
for (int j = 0; j < rindex; j++) {
rnode = rnode.prev;
}
return rnode;
} // 获取第index位置节点的值
public T get(int index) {
return getNode(index).value;
} // 将节点插入到index位置
public void insert(int index, T t) {
if (index == 0) {
Node node = new Node(t, head, head.next);
head.next.prev = node;
head.next = node;
count++;
return;
}
Node<T> inode = getNode(index);
// 创建新节点
Node<T> newNode = new Node<>(t, inode.prev, inode);
inode.prev.next = newNode;
inode.next = newNode;
return;
} // 删除节点
public Node<T> delete(int index) {
Node<T> delNode = getNode(index);
delNode.prev.next = delNode.next;
delNode.next.prev = delNode.prev;
count--;
return delNode;
}
}

Java数据结构与算法(1):线性表的更多相关文章

  1. Java数据结构和算法 - 哈希表

    Q: 如何快速地存取员工的信息? A: 假设现在要写一个程序,存取一个公司的员工记录,这个小公司大约有1000个员工,每个员工记录需要1024个字节的存储空间,因此整个数据库的大小约为1MB.一般的计 ...

  2. 【数据结构与算法】线性表操作(C++)

    #include <stdio.h> #define maxSize 100 //定义整型常量maxSize值为100 /*顺序表的结构体定义*/ typedef struct SqLis ...

  3. 【数据结构与算法】线性表操作(C语言)

    #include <stdio.h> #include <stdlib.h> #define OK 1 #define NO 0 #define MAXSIZE 20 type ...

  4. Java数据结构和算法(一)线性结构

    Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ...

  5. Java数据结构和算法(一)线性结构之单链表

    Java数据结构和算法(一)线性结构之单链表 prev current next -------------- -------------- -------------- | value | next ...

  6. 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现

      本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型   栈是 ...

  7. java数据结构与算法之栈(Stack)设计与实现

    本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...

  8. Java数据结构和算法 - 高级排序

    希尔排序 Q: 什么是希尔排序? A: 希尔排序因计算机科学家Donald L.Shell而得名,他在1959年发现了希尔排序算法. A: 希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插 ...

  9. Java数据结构和算法(一)散列表

    Java数据结构和算法(一)散列表 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 散列表(Hash table) 也叫哈希表 ...

随机推荐

  1. spring扩展点之PropertyPlaceholderConfigurer

    原理机制讲解 https://leokongwq.github.io/2016/12/28/spring-PropertyPlaceholderConfigurer.html 使用时多个配置讲解 ht ...

  2. 微信JSSdk实现分享功能

    1. 概述 微信分享服务器的作用是为用户在微信浏览器端对来自网站以及客户端的页面进行二次分享链接时更友好的展示提供服务.为实现二次分享功能需要使用微信JS-SDK来开发. 微信JS-SDK是微信公众平 ...

  3. PY个树状数组

    树状数组看起来比较简单,于是就挑它下手了... 于是生活终于也对咱下手了... 要讲的就两个东西,一个是开数组,全局变量写最前面,数组是这么开的: f=[0 for i in range(500005 ...

  4. jQuery之样式的类操作

    方法:添加类addClass    .删除类removeClass. 切换类toggleClass <style> div { width: 150px; height: 150px; b ...

  5. Window Operations详解

    window(windowLength, slideInterval):返回窗口长度为windowLength,每隔slideInterval滑动一次的window DStream countByWi ...

  6. div的edit和drag(点击div可编辑、删除、拖动)

    1.可编辑: <div id="move" contentEditable="true">可编辑</div> 设置contentEdit ...

  7. [IIS]修改MaxFieldLength与MaxRequestBytes彻底解决Request Too Long的问题

    当 IIS7/7.5 收到的请求头的长度超过16K(默认值),就会引发"Bad Request - Request Too Long. HTTP Error 400. The size of ...

  8. Linux学习--第四天--find、locate、帮助命令、grep、who、w、压缩命令、网络命令、mount

    find 命令格式:find 搜索范围 匹配条件find 搜索范围 匹配条件(搜索范围一定要填写,不写默认为当前文件夹,不包括子文件夹.) find /etc -name init #搜索文件和文件夹 ...

  9. Linux下载:wget、yum与apt-get用法及区别

    一般来说著名的linux系统基本上分两大类: RedHat系列:Redhat.Centos.Fedora等 Debian系列:Debian.Ubuntu等 RedHat 系列 常见的安装包格式 rpm ...

  10. STM32 总线

    AHB,是Advanced High performance Bus的缩写,译作高级高性能总线,这是一种“系统总线”.AHB主要用于高性能模块(如CPU.DMA和DSP等)之间的连接.AHB 系统由主 ...