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

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

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. elasticsearch重建索引

    1.重建索引 一个field的设置是不能被修改的,如果要修改一个Field,那么应该重新按照新的mapping,建立一个index,然后将数据批量查询出来,重新用bulk api写入index中 批量 ...

  2. php第六讲

    继承和静态 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...

  3. 构造函数和初始化表、this指针与常函数、析构函数、拷贝构造与拷贝赋值(day05)

    十四 构造函数和初始化表 ... 初始化表 )语法形式 class 类名{ 类名(形参表):成员变量1(初值),...{} }; )必须要使用初始化表的场景 -->如果有类 类型的成员变量,而该 ...

  4. 51nod1081 子段求和

    给出一个长度为N的数组,进行Q次查询,查询从第i个元素开始长度为l的子段所有元素之和. 例如,1 3 7 9 -1,查询第2个元素开始长度为3的子段和,1 {3 7 9} -1.3 + 7 + 9 = ...

  5. Linux目录与相关配置文件讲解

    linux目录介绍及配置文件详细介绍 重要目录简介 目录名 作用 boot 与电脑启动相关,推荐单独分区. etc 存放配置文件 mnt 一般用来设置挂载点 src.sys.proc 与系统内核相关, ...

  6. SpringBoot快速创建HelloWorld项目

    废话不多提,拿起键盘,打开 IDEA 就是一通骚操作. 打开 IDEA 后,首页选择 Create New Project,再接着按下图所示,快速搭建SpringBoot项目. 接下来将 Group ...

  7. 【微软2017年预科生计划在线编程笔试第二场 A】Queen Attack

    [题目链接]:http://hihocoder.com/problemset/problem/1497 [题意] 给你n个皇后; 然后问你其中能够互相攻击到的皇后的对数; 皇后的攻击可以穿透; [题解 ...

  8. FZU - 2062 - Suneast & Yayamao

    先上题目: Problem 2062 Suneast & Yayamao Accept: 146    Submit: 319Time Limit: 1000 mSec    Memory L ...

  9. 模型概念--MVC-MVVM

    MVVM 第一个M是数据访问曾,第二个v是view视图页面,第三个vm是ViewModel视图模型

  10. 优化系列 | DELETE子查询改写优化

    0.导读 有个采用子查询的DELETE执行得非常慢,改写成SELECT后执行却很快,最后把这个子查询DELETE改写成JOIN优化过程 1.问题描述 朋友遇到一个怪事,一个用子查询的DELETE,执行 ...