1,对于线性表而言,里面的元素是无序的,可以随意地将新元素增加到线性表中而不需要考虑该元素在线性表中的位置。但是,对于有序表而言,其中的元素是按照某种方式进行排序的,因此在有序表中插入元素时,需要按照顺序将该新元素放置到有序表的合适的位置。

但由于有序表与线性表有很多相似的地方,因此,下面通过继承线性表来实现有序表。线性表的实现参考:http://www.cnblogs.com/hapjin/p/4549492.html

2,在Node内部类的实现中,定义了获取Node类的属性的get方法和set方法,这些方法为protected类型的,意味着Node类所在的外部类的子类可以通过这些方法来访问Node类里面的数据域。同样地,在Node类所在的外部类中(LinkedChainBase)也定义了protected类型的方法addFirstNode、getFirstNode、removeFirstNode……这样使得LinkedChainBase的子类可以直接访问其数据域,提高操作的效率。

3,有序表的实现类SortedLinkList.java通过继承基类LinkedChainBase来达到直接访问线性中的数据域的目的。由于有序表终究不是线性表,因此从线性表中继承而来的某些方法(如:replace方法)会破坏有序的有序性质。因此,对于这些方法可能通过抛出异常的方式来处理。

ListInterface代码参考:http://www.cnblogs.com/hapjin/p/4549492.html

具体的实现代码如下:

基类LinkedChainBase.java

public class LinkedChainBase<T> implements java.io.Serializable {
private Node firstNode;
private int length; public LinkedChainBase(){
clear();
}
public final void clear() {//clear()在构造器中被调用了,所以此外用final修饰符
firstNode = null;
length = 0;
} /*
* 提供操作数据域firstNode的protected方法,使得子类可以直接操作表的数据域
*/
//在表的表头插入元素
protected void addFirstNode(Node newNode){
assert newNode != null:"null argument in addFirstNode";
newNode.setNextNode(firstNode);
firstNode = newNode;
length++;
} protected Node getFirstNode(){//获取表的第一个结点
return firstNode;
}
//获取表中某个位置处的结点
protected Node getNodeAt(int givenPosition){
assert (!isEmpty() && ((1 <= givenPosition) && (givenPosition <= length)));
Node currentNode = firstNode;
for(int counter = 1; counter < givenPosition; counter++){
currentNode = currentNode.next;
}
assert currentNode != null;
return currentNode;
}
//在表中某个结点后添加新结点
protected void addAfterNode(Node nodeBefore, Node newNode){
assert newNode != null:"illegal to add a null node";
newNode.setNextNode(nodeBefore.getNextNode());
nodeBefore.setNextNode(newNode);
}
//删除表中的第一个结点
protected T removeFirstNode(){
T result = null;
if(firstNode != null){
result = firstNode.data;
firstNode = firstNode.getNextNode();
}
return result;
}
//删除表中的指定结点后的其他结点
// protected T removeAfterNode(Node nodeBefore){
//
// }
public boolean isEmpty() {//判断链表是否为空
boolean result;
if(length == 0){
assert firstNode == null;
result = true;
}
else{
assert firstNode != null;
result = false;
}
return result;
} public int getLength() {//获取表的长度
return length;
} public void display() {//遍历表,显示表中的每个结点的值
Node currentNode = firstNode;
while(currentNode != null){
System.out.println(currentNode.data);
currentNode = currentNode.next;
}
} public T getEntry(int givenPosition) {//获取指定位置的结点的值
T result = null;
if((!isEmpty()) && ((givenPosition >= 1) && (givenPosition <= getLength()))){
result = getNodeAt(givenPosition).getData();
}
return result;
} public boolean contains(T anEntry) {//判断链表中的结点是否包含某个值
boolean found = false;
Node currentNode = getFirstNode();
while(!found && currentNode != null){
if(currentNode.getData().equals(anEntry)){
found = true;
break;
}
currentNode = currentNode.getNextNode();
}
return found;
} /*
* Node 是一个内部类,通用类型T与类中声明的通用类型相同,因此Node后面不需要<T>
* Node 声明为protected,这样子类就可以访问Node类中的方法,从而直接地操作线性表的数据域,提高操作效率
*/
protected class Node{
private T data;
private Node next; protected Node(T dataPortion){
data = dataPortion;
next = null;
}
private Node(T dataPortion, Node nextNode){
data = dataPortion;
next = nextNode;
}
protected T getData(){
return data;
}
protected void setData(T dataPortion){
data = dataPortion;
}
protected Node getNextNode(){
return next;
}
protected void setNextNode(Node nextNode){
next = nextNode;
}
}
}

有序表的实现类SortedLinkList.java

import linklist.ListInterface;
public class SortedLinkList<T extends Comparable<? super T>> extends LinkedChainBase<T>
implements ListInterface<T>,java.io.Serializable { //有序表中的元素之所以是有序的,主要是通过该add方法来保证的
@Override
public boolean add(T newEntry) {
Node newNode = new Node(newEntry);
Node nodeBefore = getNodeBefore(newEntry);
if(nodeBefore == null)
addFirstNode(newNode);
else
addAfterNode(nodeBefore, newNode);
return true;
} private Node getNodeBefore(T anEntry){
Node currentNode = getFirstNode();
Node nodeBefore = null;
//对待插入的元素与有序表中的元素进行比较,保证元素有序
while((currentNode != null) && (anEntry.compareTo(currentNode.getData()) > 0)){
nodeBefore = currentNode;
currentNode = currentNode.getNextNode();
}
return nodeBefore;
} @Override
public boolean add(int givenPosition, T newEntry) {
throw new UnsupportedOperationException("illegal to add element at a specified position.");
} @Override
public T remove(int givenPosition) {
throw new UnsupportedOperationException("illegal to add element at a specified position."); } @Override
public boolean replace(int givenPosition, T newEntry) {
throw new UnsupportedOperationException("illegal to add element at a specified position.");
}
}

参考《数据结构与算法分析 第二版 JAVA语言描述》Frank M. Carrano 著

JAVA通过继承线性表来实现有序表的更多相关文章

  1. 查找->静态查找表->折半查找(有序表)

    文字描述 以有序表表示静态查找表时,可用折半查找算法查找指定元素. 折半查找过程是以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等 ...

  2. 查找(顺序表&有序表)

    [1]查找概论 查找表是由同一类型是数据元素(或记录)构成的集合. 关键字是数据元素中某个数据项的值,又称为键值. 若此关键字可以唯一标识一个记录,则称此关键字为主关键字. 查找就是根据给定的某个值, ...

  3. Java数据结构之线性表(2)

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  4. Java数据结构之线性表

    从这里开始将要进行Java数据结构的相关讲解,Are you ready?Let's go~~ java中的数据结构模型可以分为一下几部分: 1.线性结构 2.树形结构 3.图形或者网状结构 接下来的 ...

  5. 第一阶段:Java内功秘籍-线性表

    前言 为什么要学习数据结构与算法,如果你学会了做安卓,javaweb,前端等,都是你的武功秘籍,但是如果你的内功不够好,再厉害的功夫也是白费. 数据结构和算法:什么是数据结构,什么是数据,在计算机内部 ...

  6. Java数据结构与算法(1) - ch02有序表(OrderedArray)

    有序表需要掌握的插入方法,删除方法和二分法查找方法. 插入方法: 从前往后找到比要插入的值大的数组项,将该数组项及之后的项均后移一位(从最后一项起依次后移),最后将要插入的值插入当前数组项. 删除方法 ...

  7. java数据结构之有序表查找

    这篇文章是关于有序表的查找,主要包括了顺序查找的优化用法.折半查找.插值查找.斐波那契查找: 顺序优化查找:效率极为底下,但是算法简单,适用于小型数据查找: 折半查找:又称为二分查找,它是从查找表的中 ...

  8. Java的继承、封装与多态

    Java的继承.封装与多态 基本概念 面向对象OO(Object Oriented):把数据及对数据的操作方法放在一起,作为一个相互依存的整体,即对象. 对同类对象抽象出共性,即类. 比如人就是一个类 ...

  9. [ Java学习基础 ] Java的继承与多态

    看到自己写的东西(4.22的随笔[ Java学习基础 ] Java构造函数)第一次达到阅读100+的成就还是挺欣慰的,感谢大家的支持!希望以后能继续和大家共同学习,共同努力,一起进步!共勉! ---- ...

随机推荐

  1. 面象对象设计原则之五:依赖倒置原则(The Dependency Inversion Principle,DIP)

    如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要实现机制之一,它是系统抽象化的具体实现.依赖倒转原则是Robert C. Martin在1996年为“C++Reporte ...

  2. Docker 执行nginx以及简单进入container

    1. docker run -d --name mynginx nginx 运行起来nginx镜像之后 2. docker exec -ti mynginx /bin/bash 能够进入操作界面 发现 ...

  3. Spring MVC @ModelAttribute注解

    在一个Controller内,被@ModelAttribute标注的方法会在此controller的每个handler方法执行前被执行. 被@ModelAttribute标注的方法的参数绑定规则和普通 ...

  4. BZOJ3732Network——kruskal重构树+倍增+LCA/最小生成树+倍增

    题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...

  5. Luogu5055 【模板】可持久化文艺平衡树(fhq-treap)

    注意下传标记时也需要新建节点.空间开的尽量大. #include<iostream> #include<cstdio> #include<cmath> #inclu ...

  6. 【Linux】memcache和memcached的自动安装

    赶时间所以写一个简单的一个脚本,没有优化,想优化的可以学习下shell,自己优化下. 且行且珍惜,源码包+脚本领取处 链接:https://pan.baidu.com/s/1wIFR1wY-luDKs ...

  7. Codeforces Round #420 (Div. 2) A,B,C

    A. Okabe and Future Gadget Laboratory time limit per test 2 seconds memory limit per test 256 megaby ...

  8. MT【44】抛物线不常见性质3

    注:S为抛物线的焦点

  9. 自学工业控制网络之路1.2-典型的现场总线介绍PROFIBUS

    返回 自学工业控制网络之路 自学工业控制网络之路1.2-典型的现场总线介绍PROFIBUS 目前看来,现场总线标准不会统一,多标准并存现象将会持续. 现场总线国家标准: 中国的DeviceNet和AS ...

  10. 【BZOJ3879】SvT(后缀自动机,虚树)

    [BZOJ3879]SvT(后缀自动机,虚树) 题面 BZOJ 题解 看着这个东西,询问若干个前缀两两之间的\(lcp\)? 显然\(lcp\)就是\(SAM\)构建出来的\(parent\)数上的\ ...