一、线性表的抽象数据类型表述

线性表的结构简单,长度允许动态增长或搜索;可以对线性表中的任何数据元素进行访问和查找;允许进行数据的插入和删除操作;求线性表中的指定数据的前驱和后继;合并线性表以及拆分线性表中。

Java JDK中有ArrayList和LinkedList两个类很好的实现了顺序存储和链式存储。因此学习数据结构的最好方式是去研究JDK源码。

这里的代码个人作为练习,为了便于理解,很多地方处理的并非十分严谨,仅供参考。转载注明出处,技术讨论 email: <yaoyao0777@Gmail.com>

 package org.yohhan.data_structure.api;

 /**
* @author yohhan <yaoyao0777@Gmail.com>
* @date create:2016年1月10日 下午4:05:35
*
* 线性表的抽象数据类型
*
*/
public interface MyList {
public void clear(); public boolean isEmpty(); public int length(); public Object get(int i) throws Exception; public void insert(int i, Object obj) throws Exception; public void remove(int i) throws Exception; public int indexOf(Object obj); public void display();
}

二、线性表的顺序存储实现

1.顺序表的定义:

顺序存储采用一组地址连续的存储单元依次存储线性表占用的各个数据元素的存储结构。

2.顺序表的特点:

1)逻辑上相邻的数据元素,在物理存储位置上也是相邻的。

2)存储密度高,事先需要分配足够应用的存储空间。

3)随机存取,查询速度快,直接访问地址单元中的数据。时间复杂度 O(1)

4)插入删除操作会引起大量的数据移动,时间复杂度O(n)

3.顺序表的结构类描述:

 package org.yohhan.data_structure.linear;

 import org.yohhan.data_structure.api.MyList;

 /**
* @author yohhan <yaoyao0777@Gmail.com>
* @date create:2016年1月10日 下午4:09:15
*
* 线性表的顺序存储实现
*/
public class SqList implements MyList { private Object[] listElem; // 数组作为线性表的存储空间
private int curLen; // 线性表的当前长度 public SqList(int maxSize) {
curLen = 0;
listElem = new Object[maxSize];
} @Override
public void clear() {
curLen = 0;
} @Override
public boolean isEmpty() {
return curLen == 0;
} @Override
public int length() {
return curLen;
} @Override
public Object get(int i) throws Exception {
if (i < 0 || i > curLen - 1)
throw new Exception("元素不存在");
return listElem[i];
} @Override
public void insert(int i, Object obj) throws Exception {
if (curLen == listElem.length)
throw new Exception("存储空间已满");
if (i < 0 || i > curLen)
throw new Exception("插入位置不合法");
for (int j = curLen; j > i; j--)
listElem[j] = listElem[j - 1];
listElem[i] = obj;
++curLen;
} @Override
public void remove(int i) throws Exception {
if (i < 0 || i > curLen - 1)
throw new Exception("删除位置不合法");
for (int j = i; j < curLen; j++)
listElem[j] = listElem[j + 1];
--curLen;
} @Override
public int indexOf(Object obj) {
int j = 0;
while (j < curLen && !listElem[j].equals(obj))
j++;
if (j < curLen)
return j;
return -1;
} @Override
public void display() {
for (int j = 0; j < curLen; j++)
System.out.print(listElem[j] + ", ");
} @Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[");
for (Object obj : listElem) {
if (null != obj)
sb.append(obj.toString() + ", ");
}
sb.delete(sb.length() - 2, sb.length());
sb.append("]");
return sb.toString();
} }

三、线性表的链式存储实现

1.单链表的定义:

采用链式存储方式存储的线性表,链表中每一个结点中包含存放数据元素值的数据域和存放逻辑上相邻结点的指针域。(示例中的结点只包含一个指针域,称为单链表(Single Linked List))

(图片摘自网上)

单链表通过指向后继结点的指针将结点串联成一条链。

以线性表中的第一个数据元素的存储地址作为线性表的起始地址,称为线性表的头指针。通过头指针(head)来唯一标识一个链表。

单链表中的最后一个节点没有后继,指针域为空指针(null),称为尾结点。

示例中采用一个“虚头结点”数据域不存放具体值,指针域中的指针指向单链表的第一个结点(首结点)。即当头结点中的指针域为空时,链表为空

2.链式存储的特点:

1)不需要预先分配存储空间,动态分配存储空间,存储密度较低、

2) 无法随机查询,需要从头遍历来查找元素。时间复杂度O(n)

3)便于进行数据的插入和删除。时间复杂度O(1)

3.线性表的单链表实现:

结点类结构:

 package org.yohhan.data_structure.node;

 /**
* @author yohhan <yaoyao0777@Gmail.com>
* @date create:2016年1月10日 下午4:39:15
*
* 链表的结点类描述
*
*/
public class Node { private Object data;
private Node next; public Node() {
this(null, null);
} public Node(Object data) {
this(data, null);
} public Node(Object data, Node next) {
super();
this.data = data;
this.next = next;
} public Object getData() {
return data;
} public void setData(Object data) {
this.data = data;
} public Node getNext() {
return next;
} public void setNext(Node next) {
this.next = next;
} }

单链表类的描述:

 package org.yohhan.data_structure.linear;

 import org.yohhan.data_structure.api.MyList;
import org.yohhan.data_structure.node.Node; /**
* @author yohhan <yaoyao0777@Gmail.com>
* @date create:2016年1月10日 下午4:51:58
*
* 带头结点的单链表实现
*
*/
public class LinkList implements MyList { private Node head; public LinkList() {
head = new Node();
} public LinkList(int n, boolean order) throws Exception {
this();
if (order)
createFromTail(n);
else
createFromHead(n);
} private void createFromTail(int n) throws Exception {
// 可在此添加输入流,传入数据 for (int j = 0; j < n; j++)
insert(length(), j + 1);
} private void createFromHead(int n) throws Exception {
// 可在此添加输入流,传入数据 for (int j = 0; j < n; j++)
insert(0, j + 1);
} @Override
public void clear() {
head.setData(null);
head.setNext(null);
} @Override
public boolean isEmpty() {
return head.getNext() == null;
} @Override
public int length() {
Node node = head.getNext();
int length = 0;
while (node != null) {
node = node.getNext();
++length;
}
return length;
} /**
* 按位序号查找算法
*/
@Override
public Object get(int i) throws Exception {
Node node = head.getNext();
int j = 0;
while (node != null && j < i) {
node = node.getNext();
++j;
}
if (j > i || node == null)
throw new Exception("元素不存在");
return node.getData();
} /**
* 在index前插入新结点
*/
@Override
public void insert(int i, Object obj) throws Exception {
Node node = head;
int j = -1;
while (node != null && j < i - 1) {
node = node.getNext();
++j;
}
if (j > i - 1 || node == null)
throw new Exception("插入位置不合法");
Node newNode = new Node(obj);
newNode.setNext(node.getNext());
node.setNext(newNode);
} @Override
public void remove(int i) throws Exception {
Node node = head;
int j = -1;
while (node.getNext() != null && j < i - 1) { // 链表不能为空
node = node.getNext();
++j;
}
if (j > i - 1 || node == null)
throw new Exception("删除位置不合法");
node.setNext(node.getNext().getNext());
} /**
* 按值查找算法
*/
@Override
public int indexOf(Object obj) {
Node node = head.getNext();
int j = 0;
while (node != null && !node.getData().equals(obj)) {
node = node.getNext();
++j;
}
if (node != null)
return j;
return -1;
} @Override
public void display() {
Node node = head.getNext();
while (node != null) {
System.out.print(node.getData() + "");
node = node.getNext();
}
System.out.println();
} @Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("[");
Node node = head.getNext();
while (node != null) {
sb.append(node.getData().toString() + ", ");
node = node.getNext();
}
sb.delete(sb.length() - 2, sb.length());
sb.append("]");
return sb.toString();
} }

附:线性表的单元测试类:

 package org.yohhan.data_structure.test;

 import static org.junit.Assert.*;
import org.junit.Test;
import org.yohhan.data_structure.linear.LinkList;
import org.yohhan.data_structure.linear.SqList; /**
* @author yohhan <yaoyao0777@Gmail.com>
* @date create:2016年1月10日 下午4:25:12
*
* 线性表单元测试类
*
*/
public class LinearTest { @Test
public void sqListTest() throws Exception {
SqList sqList = new SqList(10);
for (int i = 0; i < 5; i++)
sqList.insert(i, i + 1);
System.out.println(sqList);
assertTrue(sqList.toString().equals("[1, 2, 3, 4, 5]"));
assertTrue(sqList.length() == 5);
assertTrue(sqList.indexOf(2) == 1);
assertTrue(sqList.get(0).equals(1));
sqList.remove(1);
assertTrue(sqList.length() == 4);
assertTrue(sqList.indexOf(1) == 0);
} @Test
public void linkListTest() throws Exception {
LinkList linkList = new LinkList(5, true);
System.out.println(linkList);
assertTrue(new LinkList(5, false).toString().equals("[5, 4, 3, 2, 1]"));
assertTrue(linkList.toString().equals("[1, 2, 3, 4, 5]"));
assertTrue(linkList.length() == 5);
assertTrue(linkList.indexOf(2) == 1);
assertTrue(linkList.get(0).equals(1));
linkList.remove(1);
assertTrue(linkList.length() == 4);
assertTrue(linkList.indexOf(1) == 0); } }

线性表结构的Java实现的更多相关文章

  1. [置顶] ※数据结构※→☆线性表结构(queue)☆============队列 顺序存储结构(queue sequence)(八)

    队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的 ...

  2. [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)

    循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...

  3. [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)

    优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...

  4. [置顶] ※数据结构※→☆线性表结构(stack)☆============栈 序列表结构(stack sequence)(六)

    栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线性表.栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据.栈 ...

  5. ※数据结构※→☆线性表结构(list)☆============单向循环链表结构(list circular single)(四)

    循环链表是另一种形式的链式存贮结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环. 单循环链表——在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点即可. 循环链表的 ...

  6. 根据数据库表结构生成java类

    import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWrit ...

  7. [置顶] ※数据结构※→☆线性表结构(list)☆============单向链表结构(list single)(二)

    单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始:链表是使用指针进行构造的列表:又称为结点列表,因为链表是由一个个结点组装起来的:其中每个结点都有指 ...

  8. [置顶] ※数据结构※→☆线性表结构(list)☆============双向链表结构(list double)(三)

    双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点. ~~~~~~~~~~~~ ...

  9. 线性表的Java实现

    一.概念 对于常用的数据结构,可分为线性结构和非线性结构,线性结构主要是线性表,非线性结构主要是数和图.当n>0时,表可表示为:(a0,a1,a2,a3,…an) 1. 线性表的特征: 1.存在 ...

随机推荐

  1. switch 语句的反汇编浅析

    switch 的简单情景(case 不超过 3 项) 首先,我们分析一下 switch 语句的一种简单情景,我们可以用 C 写出如下如下代码. 编译后用 OllyDBG 载入,它将显示出如下的反汇编代 ...

  2. [置顶] tcpflow 抓包

    转自:  http://www.rwifeng.com/jekyll/update/2015/04/16/how-to-tcpflow/ tcpflow 抓包 Apr 16, 2015 大家都知道 t ...

  3. 洛谷P1012 拼数【字符串+排序】

    设有nn个正整数(n≤20)(n≤20),将它们联接成一排,组成一个最大的多位整数. 例如:n=3n=3时,33个整数1313,312312,343343联接成的最大整数为:3433121334331 ...

  4. nyoj24-素数 距离问题

    素数距离问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度.如果左右有等距离长度素数 ...

  5. vue 注册全局组件

    注册全局组件有啥好处呢? 提高代码的复用性:哪里需要写哪里,贼方便,就写一个标签:减少代码量:可以再配合slot一起使用,咦~~,舒服 为了让整个项目的可读性,我创建一个文件统一存放全局组件 1.创建 ...

  6. mysql 7 种 join

    一. select * from A inner join B on A.key = B.key 二. select * from A left join B on A.key = B.key 三. ...

  7. foj 2173 floyd+矩阵快速幂

     Problem 2173 Nostop Accept: 52    Submit: 210 Time Limit: 3000 mSec    Memory Limit : 32768 KB  Pro ...

  8. 推荐一个同步Mysql数据到Elasticsearch的工具

    把Mysql的数据同步到Elasticsearch是个很常见的需求,但在Github里找到的同步工具用起来或多或少都有些别扭. 例如:某记录内容为"aaa|bbb|ccc",将其按 ...

  9. SSL延迟

    原文链接 据说,Netscape公司当年设计SSL协议的时候,有人提过,将互联网所有链接都变成HTTPs开头的加密链接. 这个建议没有得到采纳,原因之一是HTTPs链接比不加密的HTTP链接慢很多.( ...

  10. python TypeError: &#39;builtin_function_or_method&#39; object is not iterable keys

    statinfo = os.stat( OneFilePath ) if AllFiles.has_key( statinfo.st_size ): OneKey = AllFiles[ statin ...