java拆装_JAVA线性表拆解

线性表(List)是一种线性结构。其特点是数据元素直线的线性关系。

1.线性表抽象类定义

public abstract class AbsList implements Iterable,List{

protected int length;

abstract public T get(int i); //返回第i(i≥0)个元素

abstract public boolean set(int i, T x); //设置第i个元素值为x

//查找,返回首次出现的关键字为key元素

abstract public int indexOf(int begin,int end,T o);

abstract public void add(int i, T x); //插入x作为第i个元素

abstract public void clear();

abstract public T remove(int i); //删除第i个元素并返回被删除对象

abstract public Iterator iterator();//返回一个迭代器

public boolean isEmpty(){ return length==0;} //判断线性表是否空

public int length(){ return length;} //返回线性表长度

public void add(T x){ add(length,x); } //在线性表最后插入x元素

public void append(T x){ add(length,x); }

public int indexOf(T o){

return indexOf(0,length,o);

}

public int indexOf(int begin,T o){

return indexOf(begin,length,o);

}

public T remove(T o){ //删除第i个元素并返回被删除对象

return remove(indexOf(o));

}

}

1.1初始化:

public Seqlist(int initlen){//initlen初始化容量

if(initlen<0) initlen = 16;

length = 0;

incrementSize = 0;

data = new Object[initlen];

}

//默认构造函数

public Seqlist(){

this(16);

}

//用数组elem初始化顺序表

public Seqlist(T[] elem){

length = elem.length;

incrementSize = 0;

data=Arrays.copyOf(elem,length);//将elem全部存入data

}

1.2容量管理

public void setCapacity(int newsize){

data=Arrays.copyOf(data,newsize);

}

//获取顺序表的最大容量

public int getCapacity(){

return data.length;

}

public void setIncr(inc){

incrementSize=inc;

}

//内部使用,顺序表自动扩容

private void grow(){

int newsize=data.length+incrementSize;

data=Arrays.copyOf(data.newsize);

}

1.3数据存取

public T get(int i)

{

if(i<0 || i>length - 1)

return null;

return (T)data[i];

}

public boolean set(int i,T x)

{

if(i<0 || i>length - 1)

return false;

else

{

data[i] = x;

return true;

}

}

1.4指定位置插入元素

public void add(int i,T x)

{

if(length == data.length)

grow();

if(i<0)

i = 0;

if(i>length)

i = length;

for(int j=length-1;j>=i;j--)

data[j+1] = data[j];

data[i] = x;

length++;

}

public void add(T x)

{

if(length == data.length)

grow();

data[length] = x;

length++;

}

1.5删除顺序表元素

//删除下标为i的元素

public T remove(int i)

{

if(i<0 || i>length -1)

throw new IndexOutOfBoundsException("下标越界 i="+i);

T olddata = (T)data[i];

for(int j=i;j

data[j] = data[j+1];

data[--length] = null;

return olddata;

}

//删除值为o的元素

public T remove(T o)

{

int i =indexOf(o);

return remove(i);

}

//清空顺序表

public void clear()

{

for(int i=0;i

remove(i);

}

1.6查找值为o的数据元素的下标,使用顺序查找算法

//注意:我们许可查到的是null

public int indexOf(T o)

{

if(o == null)

{

for(int i=0;i

if(data[i] == null)

return i;

}

else

{

for(int i=0;i

if(compare(o,(T)data[i]) == 0)

return i;

}

return -1;

}

1.7顺序表中元素有序插入与插入排序

//T数据元素比较方法

protected int compare(T a,T b)

{

if(a instanceof Comparable && b instanceof Comparable)

return ((Comparable) a).compareTo((Comparable)b);

else

return ((String)a).compareTo((String)b);

}

instanceof运算符的前一个操作数是一个引用类型变量,后一个操作数是一个类(接口),用于判断前面的对象是否是后面的类,或子类、实现类的实例。若是,返回true;反之,返回false。

如果a,b均是comparable容器已实现的类型,则用comparable直接比较。

否则,转换为string类比较

//内部使用,有序地插入x

privated void insertOrder(int end,T x)

{

if(length == data.length)

grow();

int k;

for(k=end-1;k>=0;k--)

{

if(compare(x,(T)data[k])<0)

data[k+1] = data[k];

else

break;

}

data[k+1]=x;

}

public void addSort(T x)

{

insertOrder(length,x);

length++;

}

//顺序表排序算法

public void sort()

{

for(int i=0;i

insertOrder(i,(T)data[i]);

}

addSort时间复杂度为O(n) sort为a4ec902e620b74114a88cab4afbd95b7.png

1.8顺序表转换为数组

public Object[] toArray()

{

return Arrays.copyOf(this.data, this.length);

}

public T[] toArray (T[] a)

{

if(a.length

//创建一个与数组a运行类型相同的新数组,长度可以是0

return (T[])Arrays.copyOf(this.data, this.length,a.getClass());

System.arraycopy(this.data, 0, a, 0, this.length);

if(a.length > this.length)

a[length] = null;

return a;

}

1.9顺序表转换为字符串

public String toString()

{

StringBuilder strb = new StringBuilder();

strb = strb.append("(");

for(int i=0;i

{

strb = strb.append(data[i].toString()+",");

}

strb=strb.append(data[length-1]+")");

String s = new String(strb);

strb=null;

return s;

}

2单链表的定义及其应用

2.1单链表的概念

单链表是一个用指向后继元素的指针将具有线性关系的节点链接起来,最后一个节点的后继指针为空指针。

296e311210df5ad63f4345a29f0ce327.png

节点:

class Lnode{

public T data;

public Lnode next;

}

由于节点类由data、next两部分组成,没有Comparable中数据类型的实现。故需改写Comparable中的方法。

节点类新增、改写几个方法:equals,comparaTo,toString

public class Lnode implements Comparable> {

public T data;

public Lnode next;

public Lnode(T key){

data = key;

next = null;

}

public Lnode(T key,Lnode next){

data = key;

this.next = next;

}

//重写的三个方法

public boolean equals (Object e){

@SuppressWarnings("unchecked")

Lnode node =(Lnode)e;

return data.equals(node.data);

}

@SuppressWarnings("unchecked")

public int compareTo(Lnode e) {

Comparable x;

if(data instanceof Comparable){

x = (Comparable)data;

return (int)x.compareTo(e.data);

}

else throw new ClassCastException("类型无法比较");

}

public String toString(){

return data.toString();

}

单链表的定义(部分):

public class LinkList extends AbsList implements Iterable {

Lnode first,last;//头指针与尾指针

Iterator itr = null;//指向当前节点迭代器的指针

public LinkList(){

first = last = null; length = 0;

this.itr = new LinkIterator();

}

public LinkList(int i){

first = last = null; length = 0;

if(i!=-1)

this.itr = new LinkIterator();

}

private int compare(Lnode a,Lnode b)

{

return a.compareTo(b);

}

public void clear()

{

first=last=null;

length=0;

}

public void removeAll()

{

clear();

}

//...

2.2单链表如何存取数据

首先用getNode(i)获取编号为i节点的引用。

链表getNode(i)时间复杂度为O(n)。注意,在顺序表中,复杂度为O(1)

获得引用后,用get(i)取得data值,set(i,x)修改i号节点的值。

protected Lnode getNode(int i)//getNode(i)获取编号为i节点的引用

{

if(i<0 || i>length-1)

return null;

if(i==0)

return first;

Lnode p= first;

int j=0;

while(p!=null&&j

{

p=p.next;

j++;

}

return p;

}

public T get(int i)//从引用中获取值

{

Lnode p=getNode(i);

if(p==null)

return null;

else

return p.data;

}

public boolean set(int i,T x)//在引用中修改值

{

Lnode p=getNode(i);

if(p==null)

return false;

else

{

p.data = x;

return true;

}

}

2.3向链表中插入元素

s=new Lnode(x)

s是指向新结点的引用变量,x是被插入的值。

分四种情况讨论:

1.向空链表插入一个新节点

if(first==null){

first = s;//直接将first指向s即可

last = s;

}

2.在链表头结点之前插入新节点

s.next = first; first=s;

3.在链表中间插入新节

024be381dcc0e9fb85edaeed7a2ebff2.png

s.next = p.next; p.next=s;

思考,两条语句能否调换位置? 答:不能,p.next=s,此时s未确定,p指向未知位置。

4.在链表尾部插入新节点

last.next=s; last=s;

完整的链表插入算法:

//注意:i是逻辑位置

public void add(int i,T x)

{

Lnodep,s;

int j = i-1;

s=new Lnode(x,null);

if(first==null||length==0)//1.向空链表插入一个新节点

{

first = s; last = s;

}

else if(j<0)//2.在链表头结点之前插入新节点

{

s.next = first; first = s;

}

else if(j>length-1)//4.在链表尾部插入新节点

{

last.next =s; last = s;

}

else //3.在链表中间插入新节

{

p=getNode(j);

s.next=p.next;

p.next=s;

}

length++;

}

//实际开发中,为方便使用,增加的函数

//重载add

public void add(T key){

add(length,key);

}

public void addBack(T key)

{

add(length,key);

}

public void addFront(T key)

{

add(0,key);

}

2.4删除链表节点

分三种情况处理:

1.删除的是空链表(first==null)

链表为空,此时删除非法。

2.被删除的是头结点(i=0)

first = first.next;//即可实现

实际开发中,可能需要被删除的值,故:

p=first;

first = first.next;

return p.data;

3.被删除的节点在中间

q.next = p

return p.data

a52c612ea3bd8115823fac5e81fb80af.png

得知要删除的节点p后,如何准确找到指针q的位置呢

q=getNode(i-1);

完整的删除算法如下:

public T remove(int i)

{

Lnode p=removeNode(i);

if(p!=null)

return p.data;

else

return null;

}

//删除逻辑第i节点,返回节点类型

protected Lnode removeNode(int i)

{

Lnode p,q;

if(first == null) return null;//1.删除的是空链表(first==null)

if(i==0)//2.被删除的是头结点(i=0)

{

p = first; first = first.next; length--;

return p;

}

if(i>=1&&i<=length-1)//3.被删除的节点在中间

{

q=getNode(i-1);

p = q.next;

q.next = p.next;

if(p==last)last = q;

length--;

return p;

}

return null;

}

2.5查找节点

//在begin-end中查找节点

public int indexOf(int begin,int end,T key)

{

Lnodep = getNode(begin);

int i = begin;

while(p!=null&i

{

if(p.data.equals(key)) return i;

p = p.next;

i++;

}

return i;

}

//在全链表中查找节点

public T search(T key)

{

Lnode p = getNode(0);

while(p!=null)

{

if(p.data.equals(key)) return p.data;

p = p.next;

}

return null;

}

//是否存在值为key的节点

public boolean contains(T key)

{

if(indexOf(key)==-1)

return false;

else

return true;

}

2.5向链表中插入有序节点

分四种情况讨论

1.链表为空

first = s;first.next = null;

2.插入节点s的值小于头结点

s.next=first;

first=s;//first 指向新节点

3.插入节点s值大于尾节点

last.next=s;

last=s;

4.插入节点处于中间位置

p1=p2=first;

while(p2.next!=null){

if(p1.datas.data){

将节点插入到p1之后;

break;

}else{

p1=p2;p2=p2.next;

}

}

单链表有序插入算法:

public void addSort(T x)

{

Lnode s=new Lnode(x,null);

insertOrder(s);

}

//核心算法

public void insertOrder(Lnode s)

{

Lnode p1,p2;

length++;

if(first==null)//链表为空

{

first=s;

last=first;

return;

}

if(compare(s,first)<0)//插入到头结点以前

{

s.next=first;

first=s;

return;

}

if(compare(s,last)>=0)//插入到尾节点

{

last.next=first;

last=s;

return;

}

//插入到中央

p2=first;

p1=p2;

while(p2!=null)

{

if(compare(s,p2)>0)//第一次执行必然s>p2

{

p1=p2;

p2=p2.next;

}

else break;

}

s.next=p2;

p1.next=s;

return;

}

2.6链表排序

单链表的插入排序示例:

public void sort()

{

LinkList s1=new LinkList();//有序链表

Lnode p;

p=this.getNode(0);//取出无序链表的头结点,this是调用这个方法的链表

while(p!=null)

{

s1.insertOrder(p);

p=this.getNode(0);

}

this.first=s1.first;

this.last=s1.last;

this.length=s1.length;

}

总结:1.若是要在单链表中插入、删除一个节点,必须知道其前驱结点。

2.单链表不具有按序号随机处理的特点,只能从头指针一个一个顺序进行。

2.7链表转换为字符组/数组

public String toString(Lnode first)

{

String s;

Lnode p;

p =first; s="(";

while(p!=null)

{

s=s+p.data.toString();

p = p.next;

}

return s= s+")\n";

}

public Object[] toArrays()

{

Object[] a=new Object[length];

Lnode p=first;

for(int i=0;i

{

a[i] = p.data;

p=p.next;

}

return a;

}

3.循环链表与双向链表

3.1单循环链表

5866eee9569c539ba176b9bdc9340ace.png

具有单链表的特征,无需增加额外存储空间,对链表的处理更加灵活,整个链表构成一个环, 可以遍历已经访问过的元素。

在建立循环链表时,必须使最后一个节点的指针指向表头节点,而不是null。

在判断是否到表尾是.first==rear,而不是后继结点为null。

3.2双向链表

class DoubleNode(){

public int data;

public DoubleNode prior;

public DoubleNode next;

}

1.双链表的插入运算

s= new DoubleNode;

s.data=e;

s.next=p.next;

p.next.prior=s;

p.next=s;

s.prior=p;//一定要注意顺序

faa25e7287b455054634825555d422e1.png

2.双链表的删除运算

直接断开节点间链接关系

删除s:

s.prior.next = s.next;

s.next.prior = s.prior;

4.额外补充:顺序表与链表的比较

一、顺序表的特点是逻辑上相邻的数据元素,物理位置相邻,

并且,顺序表的存储空间需要预先分配。

它的优点是:

(1)方法简单,各种高级语言中都有数组,易实现。

(2)不用为表示节点间的逻辑关系而增加额外的存储开销。

(3)顺序表具有按元素序号随机访问的特点。

缺点:

(1)在顺序表中做插入、删除操作时,平均移动表中的一半元素,因此对n较大的顺序表效率低。

(2)需要预先分配足够大的存储空间(难以估计),估计过大,可能会导致顺序表后部大量闲置;

预先分配过小,又会造成溢出。

二、在链表中逻辑上相邻的数据元素,物理存储位置不一定相邻,它使用**指针实现元素之间的

逻辑关系。并且,链表的存储空间是动态分配**的。

链表的最大特点是:

插入、删除运算方便。

缺点:

(1)要占用额外的存储空间存储元素之间的关系,存储密度降低。

存储密度是指一个节点中数据元素所占的存储单元和整个节点所占的存储单元之比。

(2)链表不是一种随机存储结构,不能随机存取元素。

三、顺序表与链表的优缺点切好相反,那么在实践应用中怎样选取存储结构呢?

通常有以下几点考虑:

(1)“MaxSize”分配,动态?静态?

当对线性表的长度或存储规模难以估计时,不宜采用顺序表。

当线性表的长度变化不大而且事先容易确定其大小时,为节省存储空间,

则采用顺序表作为存储结构比较适宜。

(2)基于运算的考虑(时间)

顺序存储是一种随机存取的结构,而链表则是一种顺序存取结构,

如果频繁按序号访问数据元素,显然顺表优于链表。

如果频繁增删,显然链表优于顺表。

(3)基于环境的考虑(语言)

顺序表容易实现,任何高级语言中都有数组类型;

链表的操作是基于指针的。相对来讲前者简单些,也用户考虑的一个因素。

总结: 通常“较稳定”的线性表,即主要操作是查找操作的线性表,适于选择顺序存储;

而频繁做插入删除运算的(即动态性比较强)的线性表适宜选择链式存储。

不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376085.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

display:none;与visibility:hidden;的区别

display:none;不会占用任何空间 visibility:hidden;会占用隐藏前的空间大小转载于:https://www.cnblogs.com/yaser/p/4414825.html

(转)起点

要想做Java程序员&#xff0c;并不需要必须是计算机专业出身。很多人不是计算机专业却也成为计算机高手&#xff1b;有的高中生都已经小有所成&#xff0c;可称得上是合格程序员了&#xff1b;甚至很多学校初中生都能写出漂亮的应用程序。所以&#xff0c;Java程序员的起点要求…

以太网 数据包速率计算方法

以太网 数据包速率计算方法 我们知道1个千兆端口的线速包转发率是1.4881MPPS, 百兆端口的线速包转发率是0.14881MPPS&#xff0c;这是国际标准&#xff0c;但是如何得来的呢&#xff1f; 具体的数据包在传输过程中会在每个包的前面加上64个&#xff08;前导符&#xff09;pream…

linux 多个java_linux 同时出现两个java进程,新手~ 请详细说明,这个是怎么回事。 我就装了一个jdk...

首先Tomcat是用java开发的&#xff0c;所以它的开始和停止的命令都是用java来执行的。你执行一下ps -ef |grep tomcat如果输出&#xff1a;sun 5144 1 0 10:21 pts/1 00:00:06 /java/jdk/bin/java -Djava.util.logging.managerorg.apache.juli.ClassLoaderLogManager -Djava.en…

ISP与IAP的区别

转&#xff1a; ISP&#xff08;In-System Programming&#xff09;在系统可编程&#xff0c;指电路板上的空白器件可以编程写入最终用户代码&#xff0c; 而不需要从电路板上取下器件&#xff0c;已经编程的器件也可以用ISP方式擦除或再编程。IAP&#xff08;In-Application P…

【转】手把手实现企业级开源监控软件cacti+nagios+ntop整合(图解)

http://freeze.blog.51cto.com/1846439/386828转载于:https://www.cnblogs.com/nhlinkin/p/3595532.html

【BZOJ】【1041】【HAOI2008】圆周上的点

数学 orz hzwer 完全不会做…… 很纠结啊&#xff0c;如果将来再遇到这种题&#xff0c;还是很难下手啊…… 引用题解&#xff1a; 【分析】&#xff1a; 样例图示&#xff1a; 首先,最暴力的算法显而易见&#xff1a;枚举x轴上的每个点&#xff0c;带入圆的方程&#xff0c;检…

php authcode java_PHP(authcode)加密解密

//************************加密解密*************************//** $string&#xff1a; 明文 或 密文* $operation&#xff1a;DECODE表示解密,其它表示加密* $key&#xff1a; 密匙* $expiry&#xff1a;密文有效期* */function authcode($string, $operation DECODE, $key…

nginx环境下搭建nagios 3.5.0,及配置pnp4nagios画图

本文基于《LNMP最新源码安装脚本》,Nagios依赖PHP环境和perl环境&#xff0c;由于Nginx不支持Perl的CGI&#xff0c;需先来搭建Perl环境&#xff0c;Nagios原理介绍略。一、下载最新稳定源码包和Perl脚本wget http://www.cpan.org/modules/by-module/FCGI/FCGI-0.74.tar.gzwget…

python indexerror怎么办_Python IndexError:使用列表作为可迭代对象时...

这是代码&#xff1a;import math as mprimeproduct 5397346292805549782720214077673687806275517530364350655459511599582614290primes [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127…

【Android】配置APK开发环境

【Android】配置APK开发环境1.安装java jdk去oracle公司下载jdk-7u15-windows-i586.exehttp://www.oracle.com/technetwork/cn/java/javase/downloads/jdk7-downloads-1880260-zhs.html---C:\Documents and Settings\XXXX>java -versionjava version "1.7.0_15"Ja…

C++细节系列(零):零散记录

老规矩&#xff1a;记录细节&#xff0c;等待空余&#xff0c;再进行整理。 1&#xff1a;const,static,const static成员初始化。 1、const成员&#xff1a;只能在构造函数后的初始化列表中初始化 2、static成员&#xff1a;初始化在类外&#xff0c;且不加static修饰。 3、co…

java js highcharts_Highcharts.js -纯javasctipt图表库初体验

一.highcharts简介以及引入highcharts作为免费提供给个人学习、个人网站和非商业用途使用的前端图表演示插件的确使用起来十分方便和轻便。在我最近完成一个需求的时候用到了它&#xff0c; 它的兼容性也很强&#xff0c;其在标准(W3C标准)浏览器中使用SVG技术渲染图形&#xf…

PHP:class const

const变量经常被当做常量用在php的类中&#xff0c;隐含的意思是这个变量是常量&#xff0c;不能被修改。编译器会自动检测&#xff0c;如果被赋值会被提示错误警告。 正确实例1&#xff1a; <?php class test {const ERRNO 100; } echo test::ERRNO."\n"; 输出…

java web核心知识_JAVA web 相关知识点

1&#xff1a; web的三个核心标准&#xff1a;URL&#xff1a; http VS httpsHTTP: 通信协议&#xff0c;客户端&#xff0f;服务器端信息交互方式; 特点是无状态&#xff1b;HTML:2: HTTP 协议&#xff1a;http是通用的&#xff0c;无状态的&#xff0c;面向对象的协议。H…

20135127陶俊杰 实验一

北京电子科技学院(BESTI) 《Java程序设计》课实验报告 班 级&#xff1a;201351 姓名及学号&#xff1a;陶俊杰 20135127 指导教师&#xff1a;娄佳鹏 必修/选修&#xff1a;选修 实验日期&#xff1a; 2015年4月16日 实验时间&…

2014.3.12-C语言小测试

测试代码&#xff1a; 学号:14020491.请实现一个函数&#xff0c;功能为使用循环输出以下的图案void print_alpha(int n) {int i, j;for(i0;i<n;i){for(j0;j<i;j)printf("%c", A j);printf("\n");} }2.请实现一个函数&#xff0c;功能为删除数组指定…

seqlist插入java_大话数据结构(五)(java程序)——顺序存储结构的插入与删除...

获得元素操作对于线性表的顺序存储结构来说&#xff0c;我们要实现getElement操作&#xff0c;即将线性表的第i个位置元素返回即可插入操作插入算法思路&#xff1a;1、如果插入位置不合理&#xff0c;抛出异常2、如果插入表的长度大于等于数组长度&#xff0c;则抛出异常或动态…

142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Follow up:Can you solve it without using extra space? Craking interview书上原题&#xff0c;快慢指针&#xff0c;话题较简单说明。 /** * Definition for singly-lin…