单向链表与顺序表的区别在于单向链表的底层数据结构是节点块,而顺序表的底层数据结构是数组。节点块中除了保存该节点对应的数据之外,还保存这下一个节点的对象地址。这样整个结构就像一条链子,称之为“链表”

  我们可以推理出单向链表和顺序表这两种数据结构特性对其本身操作的影响:

    1、对读和改的影响:对于底层为数组的顺序表来说,读取(改写)数据是通过arr[n]的方式。而对于链表来说,操作第n个节点的数据必须要从第0个节点开始获取下一个节点的对象地址,直到第n个,如果运气不好要获取最后一个节点的数据,甚至要遍历整个链表所有的数据,其效率可想而知。

    2、对插入的影响:对于底层为数组的顺序表来说,如果从首部或者中间位置插入一个数据,则其后的数据的物理内存地址全部都要往后移动一个单位,因为数组本身便是一连串的数据集合。而对于链表来说,如果要插入数据只需要对应位置前一位的对象地址以及在插入节点中加上后一位节点的对象地址即可。

  下面我们通过代码的方式来实现我们自己的单向链表,我们首先先定义List接口:

 package com.chen.arithmetic_test.list_test;

 /**
* Created by ChenMP on 2017/7/3.
*/
public interface List {
//获得长度
public int size();
//插入元素
public boolean insert(int index, Object o) throws Exception;
//新增元素
public boolean add(Object o) throws Exception;
//删除元素
public boolean remove(int index) throws Exception;
//获取元素
public Object get(int index) throws Exception;
//判断线性表是否为空
public boolean isEmpty();
}

  编写节点类Node:

 package com.chen.arithmetic_test.list_test;

 /**
* Created by ChenMP on 2017/7/4.
*/
public class Node { private Object nodeData; //当前节点数据
private Node nextNode; //保存下一个节点 public Node() {
super();
} public Node(Object nodeData) {
this.nodeData = nodeData;
} public Object getNodeData() {
return nodeData;
} public void setNodeData(Object nodeData) {
this.nodeData = nodeData;
} public Node getNextNode() {
return nextNode;
} public void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
}

  编写LinkList的实现类:

 package com.chen.arithmetic_test.list_test;

 /**
* Created by ChenMP on 2017/7/4.
*/
public class LinkList implements List {
private Node fristNode;//开始节点
private Node lastNode;//结束节点
private int size;//List长度
private boolean isFixed;//是否限定List长度
private int fixedLength;//List定长 public LinkList() {
this.size = 0;
this.fristNode = null;//第一次成功插入时定义
this.lastNode = null;
this.isFixed = false;//不限定List长度
this.fixedLength = -1;//不限定长度
} public LinkList(int length) {
this.fristNode = null;//第一次成功插入时定义
this.lastNode = null;
this.size = 0;
this.isFixed = true;//限定List长度
this.fixedLength = length;//设置限定长度
} @Override
public int size() {
return this.size;
} @Override
public boolean insert(int index, Object o) throws Exception {
if(index > size)
throw new Exception("IndexOutOfBoundsException"); if (index == size && this.isFixed && size>=this.fixedLength)
throw new Exception("IndexOutOfBoundsException"); Node previousNode = null; //遍历节点,用于存放更新节点的前一个节点
Node currentNode = this.fristNode; //遍历节点,用于存放当前节点
for (int i=1; i<=index; i++) {
if (null == currentNode) //插入节点前有空节点
throw new Exception("IndexOutOfBoundsException"); previousNode = currentNode;
currentNode = previousNode.getNextNode();
} if (null == currentNode) { //把节点插入到最后
currentNode = new Node(o); if (null != previousNode) { //fristNode不为空
previousNode.setNextNode(currentNode);
} else { //fristNode不为空,更新fristNode
this.fristNode = currentNode;
} this.lastNode = currentNode;
size++;
} else { //节点不为空,取代原节点数据
currentNode.setNodeData(o);
} return true;
} @Override
public boolean add(Object o) throws Exception {
if (this.isFixed && size == fixedLength)
throw new Exception("IndexOutOfBoundsException"); Node currentNode = new Node(o);
if (0 == size) {//List中插入第一个元素
this.fristNode = currentNode;
this.lastNode = currentNode;
size++;
} else {
this.lastNode.setNextNode(currentNode);
this.lastNode = currentNode;
size++;
} return true;
} @Override
public boolean remove(int index) throws Exception {
if(index < 0 || index >= size)
throw new Exception("IndexOutOfBoundsException"); Node previousNode = null; //遍历节点,用于存放删除节点的前一个节点
Node currentNode = this.fristNode; //遍历节点,用于存放删除节点
for (int i=1; i<=index; i++) {
if (null == currentNode) //删除节点前有空节点
throw new Exception("IndexOutOfBoundsException"); previousNode = currentNode;
currentNode = previousNode.getNextNode();
} previousNode.setNextNode(currentNode.getNextNode());
currentNode = null;
size--; return true;
} @Override
public Object get(int index) throws Exception {
if(index < 0 || index >= size)
throw new Exception("IndexOutOfBoundsException"); Node currentNode = this.fristNode; //遍历节点,用于存放查询节点
for (int i=1; i<=index; i++) {
if (null == currentNode) //删除节点前有空节点
throw new Exception("IndexOutOfBoundsException"); currentNode = currentNode.getNextNode();
} return currentNode.getNodeData();
} @Override
public boolean isEmpty() {
return this.size>0?false:true;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node currentNode = this.fristNode; //遍历节点,用于存放查询节点 while (null != currentNode) {
sb.append(currentNode.getNodeData()).append(",");
currentNode = currentNode.getNextNode();
}
return sb.toString();
}
}

  编写测试代码:

 package com.chen.arithmetic_test.list_test;

 import java.util.LinkedList;

 /**
* Created by ChenMP on 2017/7/3.
*/
public class TestList { public static void main(String[] args) throws Exception {
List list = new LinkList(3);
list.insert(0,0);
// list.add(0);
list.add(1);
list.add(2);
// list.add(3);
System.out.print("测试定长list: " + list.toString() + "|| list长度为: " + list.size()); System.out.println();
List list2 = new SequenceList();
list2.add(0);
list2.add(1);
list2.add(2);
list2.add(3);
System.out.print("测试不定长list: " + list2.toString() + "|| list长度为: " + list2.size()); }
}

  通过我们自己实现的代码,相信我们再去看JDK中LinkList源码的时候一定能够很轻松的理解其原理实现。怀挺!!

  

[Java算法分析与设计]--单向链表(List)的实现和应用的更多相关文章

  1. java笔试之从单向链表中删除指定值的节点

    输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针. 链表的值不能重复 构造过程,例如 1 -> 2 3 -> 2 5 -> 1 4  ...

  2. java创建节点和单向链表

    package datastructure; public class Node { private Object data; private Node next; public Node() { t ...

  3. [Java算法分析与设计]--顺序栈的实现

    在程序的世界,栈的应用是相当广泛的.其后进先出的特性,我们可以应用到诸如计算.遍历.代码格式校对等各个方面.但是你知道栈的底层是怎么实现的吗?现在跟随本篇文章我们来一睹它的庐山真面目吧. 首先我们先定 ...

  4. [Java算法分析与设计]--线性结构与顺序表(List)的实现应用

    说到线性结构,我们应该立马能够在脑子里蹦出"Array数组"这个词.在Java当中,数组和对象区别基本数据类型存放在堆当中.它是一连串同类型数据存放的一个整体.通常我们定义的方式为 ...

  5. [Java算法分析与设计]--链式堆栈的设计

    在上篇文章当中,我们实现了底层为数组的顺序栈.在我之前的文章中也提到过:以数组为数据结构基础在存储数据方面需要一整块连续的内存来存放数据,一旦遇到需要可以动态扩展的功能需求时如果数据量大可能会给虚拟机 ...

  6. 单向链表的归并排序——java实现

    在做Coursera上的Algorithms第三周测验练习的时候有一道链表随机排序问题,刚开始没有什么思路,就想着先把单向链表归并排序实现了,再此基础上进行随机排序的改造.于是就结合归并排序算法,实现 ...

  7. 笔试题&amp;面试题:设计一个复杂度为n的算法找到单向链表倒数第m个元素

    设计一个复杂度为n的算法找到单向链表倒数第m个元素.最后一个元素假定是倒数第0个. 提示:双指针查找 相对于双向链表来说,单向链表仅仅能从头到尾依次訪问链表的各个节点,所以假设要找链表的倒数第m个元素 ...

  8. Java实现单向链表基本功能

    一.前言 最近在回顾数据结构与算法,有部分的算法题用到了栈的思想,说起栈又不得不说链表了.数组和链表都是线性存储结构的基础,栈和队列都是线性存储结构的应用- 本文主要讲解单链表的基础知识点,做一个简单 ...

  9. JAVA单向链表实现

    JAVA单向链表实现 单向链表 链表和数组一样是一种最常用的线性数据结构,两者各有优缺点.数组我们知道是在内存上的一块连续的空间构成,所以其元素访问可以通过下标进行,随机访问速度很快,但数组也有其缺点 ...

随机推荐

  1. C语言中字符串常用函数--strcat,strcpy

    strcpy 原型声明:extern char *strcpy(char* dest, const char *src); 头文件:#include <string.h> 功能:把从src ...

  2. Java单例模式之饿汉模式与懒汉模式

    单例模式是我们在开发软件的过程中经常用到的23中常用的java模式之一,主要的功能就是保证我们所使用的对象只有一个,这也在一方面减少了出错的可能性,增强了代码的健壮.单例模式一般来说有两种实现的方式, ...

  3. 【一天一道LeetCode】#52. N-Queens II

    一天一道LeetCode系列 (一)题目 Follow up for N-Queens problem. Now, instead outputting board configurations, r ...

  4. python函数参数是值传递还是引用传递(以及变量间复制后是否保持一致):取决于对象内容可变不可变

    函数参数传递本质上和变量整体复制一样,只是两个变量分别为形参a和实参b.那么,a=b后,a变了,b值是否跟着变呢?这取决于对象内容可变不可变 首先解释一下,什么是python对象的内容可变不可变? p ...

  5. 网络小白之WAN与LAN的区别

    剑指Offer--网络小白之WAN与LAN的区别 基本作用 wan接口是外网接口,是用来连接互联网或局域网等外部网络的. lan接口是内网接口,是用来连接计算机终端或其他路由器等终端设备的. 举例 w ...

  6. Oracle Applications DBA 基础(二)

    6.OAM及系统管理 2014年9月13日 20:40 参考资料: 1.Oracle Applications System Administrator's Guide - Configuration ...

  7. java工具类(四)之实现日期任意跳转

    Java实现日期任意跳转 项目开发过程中,需要进行订单提醒日期的设置,主要包括设置每月指定的日期或者指定的天数,代码如下: public static String DateOperation(Str ...

  8. Learning ROS for Robotics Programming Second Edition学习笔记(九) indigo Gazebo rviz slam navigation

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 书中三维环境gazebo,slam的仿真例子 --$ r ...

  9. OpenCV GUI基本操作,回调函数,进度条,裁剪图像等

    代码为转载,出处找不到了,不贴了 工具条进度条: // ConvertColor.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #incl ...

  10. "《算法导论》之‘栈’":栈的三种实现(静态数组、动态数组及指针)

    本文有关栈的介绍部分参考自网站数据结构. 1. 栈  1.1 栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底( ...