线性表结构的Java实现
一、线性表的抽象数据类型表述
线性表的结构简单,长度允许动态增长或搜索;可以对线性表中的任何数据元素进行访问和查找;允许进行数据的插入和删除操作;求线性表中的指定数据的前驱和后继;合并线性表以及拆分线性表中。
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实现的更多相关文章
- [置顶] ※数据结构※→☆线性表结构(queue)☆============队列 顺序存储结构(queue sequence)(八)
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的 ...
- [置顶] ※数据结构※→☆线性表结构(queue)☆============循环队列 顺序存储结构(queue circular sequence)(十)
循环队列 为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量.存储在其中的队列称为循环队列(Circular Queue). ...
- [置顶] ※数据结构※→☆线性表结构(queue)☆============优先队列 链式存储结构(queue priority list)(十二)
优先队列(priority queue) 普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有 ...
- [置顶] ※数据结构※→☆线性表结构(stack)☆============栈 序列表结构(stack sequence)(六)
栈(stack)在计算机科学中是限定仅在表尾进行插入或删除操作的线性表.栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据.栈 ...
- ※数据结构※→☆线性表结构(list)☆============单向循环链表结构(list circular single)(四)
循环链表是另一种形式的链式存贮结构.它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环. 单循环链表——在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点即可. 循环链表的 ...
- 根据数据库表结构生成java类
import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWrit ...
- [置顶] ※数据结构※→☆线性表结构(list)☆============单向链表结构(list single)(二)
单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始:链表是使用指针进行构造的列表:又称为结点列表,因为链表是由一个个结点组装起来的:其中每个结点都有指 ...
- [置顶] ※数据结构※→☆线性表结构(list)☆============双向链表结构(list double)(三)
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点. ~~~~~~~~~~~~ ...
- 线性表的Java实现
一.概念 对于常用的数据结构,可分为线性结构和非线性结构,线性结构主要是线性表,非线性结构主要是数和图.当n>0时,表可表示为:(a0,a1,a2,a3,…an) 1. 线性表的特征: 1.存在 ...
随机推荐
- Keras学习基础(2)
目录: Keras的模块结构 数据预处理 模型 网络层 网络配置 Keras中的数据处理 文本预处理 序列预处理 图像预处理 Keras中的模型 Sequential顺序模型 Model模型[通用模型 ...
- HDU 2266 How Many Equations Can You Find(模拟,深搜)
题目 这是传说中的深搜吗....不确定,,,,貌似更加像是模拟,,,, //我要做深搜题目拉 //实际上还是模拟 #include<iostream> #include<string ...
- apply,call,bind区别
js中有三个改变this指针的方法,分别是 apply,call,bind.很多人只知道能改变的this,但是具体的适用场景不是太清楚.我也是遇到坑后不断的实践发现了区别. call ,apply方法 ...
- 八进制、十进制、操作符(day04)
把二进制表示的数字从右向左每三个数位分成 一组,每组用一个0到7之间的数字替换. 这个替换结果叫做数字的八进制表示方式 (八进制) 可以直接在程序里用八进制方式表示数字, 这种数字必须以0做开头 可以 ...
- 1069. The Black Hole of Numbers
For any 4-digit integer except the ones with all the digits being the same, if we sort the digits in ...
- Ningx初学
原文地址 1. 到官网下载Ningx 2. 启动 2.1双击nginx.exe图标,可见黑窗口一闪而过,启动完毕. 2.2 命令行到nginx目录,输入nginx启动.(注,此方式命令行窗口无任何提示 ...
- binlog
binlog基本定义:二进制日志,也成为二进制日志,记录对数据发生或潜在发生更改的SQL语句,并以二进制的形式保存在磁盘中: 作用:MySQL的作用类似于Oracle的归档日志,可以用来查看数据库的变 ...
- [jQuery]$.get跨域提交不发送原因
使用 $.ajax({ url: "http://pastebin.com/embed_js.php?i=sy9gt3FR", dataType: "jsonp" ...
- HDU 4510
省一等,保研. #include <iostream> #include <cstdio> #include <cstring> #include <algo ...
- ural 1707. Hypnotoad's Secret(线段树)
题目链接:ural 1707. Hypnotoad's Secret 题目大意:给定N和M,然后N组s0, t0, Δs, Δt, k,每组能够计算出k个星星的坐标:M组a0, b0, c0, d0, ...