作为对简单的数据结构,数组,在各方面都,缺点都是很明显的,1,无序数组,查找和删除,都是计较慢的,2.有序数组,插入效率很低3.数组一旦定义,起长度是不可改变的,在内存中的连续区域,如果要增加长度,需要对数组复制,也会造成空间的浪费。在实际开放中,如果是需要通过下标来查询元素,数组还是很好的选择。在开始链表前,先复习一下Java中的数据在内存中的存储,why?往下走:
先来看一段代码:
// 节点
class Linked {
public int age;
public String name;
public Linked next;//next节点
public Linked(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Linked [age=" + age + ", name=" + name + "]";
}
}
我们看到这里,有一个Linked类,这个类里面包含一个Linked 类型的属性,那么问题来了?
编译器,怎么能知道,我们new 一个对象的时候,要给它分配多大的内存空间尼?基本类型的数据,如:boolean ,char,byte,short,int,float,long,double,编译器给他们分配空间是按照,他们自身的长度范围,给他们一定长度的字节空间,注意并且,数据就放在开辟的这个空间里,然而对象,却不是这样的,这里只分配了一段内存空间地址作为引用,实际的数据最后还是对应到基本数据类型,也就是说:Java里,new 了一个对象,其实我们只给了它一个引用的地址。
找了大堆,书的都很模糊,笼统,百度百科是这样给的定义:
可以看到,链表有三个很重要的特点:1.存储单元上的非连续性2.个元素间,通过描述,其他节点的位置,我确定自身位置,是一种非独立的关系,二不是线性的索引。
一本说来,链表分为两部分,表头部分,和数据项部
链表分类:
1.单链表:顾名思义,从一个方向的首节点,可以获得整个链表的节点
2.有序链表:数据项中,基本类型可排序数据,按照此顺序来连接的普通链表
3双端链表:普通链表的表头部分,添加一个last引用,快速获得链表的最后一个节点
4.双向链表:普通链表的,数据项中增加一个相反节点的描述引用
1.单链表的java实现
public class TestLinkedList {
public Linked first;
//插入节点
public void insertFirst(int age, String name) {
Linked link = new Linked(age, name);
link.next = first;
first = link;
}
//判断是否是空链表
public boolean isEmpty() {
return first == null ? true : false;
}
//删除首节点
public void deleteFirst(){
if (!isEmpty()) {
first=first.next;
}
}
//删除某个节点
public Linked deleteLinked(int age){
Linked linked=null;
Linked nex=null;
Linked pre=null;
int i=0;
Linked current=first;
while(current!=null){
if(age==current.age){
//找到先关节点
pre.next=current.next;
linked=current;
break;
}else{
pre=current;
current=current.next ;
}
i++;
}
System.out.println("count="+i);
return linked;
}
//查找某个节点
public Linked findLinked(int age){
Linked linked=null;
Linked current=first;
while(current!=null){
if(current.age==age){
linked=current;
System.out.println("I find it,its name is"+linked.name);
break;
}else{
current=current.next;
}
}
if(linked==null){
System.out.println("the point not find");
}
return linked;
}
public void disPlayLinkedList(){
Linked current=first;
while(current!=null){
System.out.println(current.toString());
current=current.next;
}
}
// 节点
class Linked {
public int age;
public String name;
public Linked next;
public Linked(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Linked [age=" + age + ", name=" + name + "]";
}
}
}
可以看到,这里提供了几个方法:
disPlayLinkedList();
insertFirst(int age, String name)
findLinked(int age);
deleteLinked(int age);
分别来测试下,这几个方法:
1.向链表中插入数据,显示链表:
TestLinkedList list=new TestLinkedList();
list.insertFirst(10, "A");
list.insertFirst(11, "B");
list.insertFirst(12, "C");
list.insertFirst(14, "D");
list.insertFirst(15, "E");
list.insertFirst(16, "F");
list.disPlayLinkedList();
我们来看看打印结果:
Linked [age=16, name=F]
Linked [age=15, name=E]
Linked [age=14, name=D]
Linked [age=12, name=C]
Linked [age=11, name=B]
Linked [age=10, name=A]
2.查找删除
查找
list.findLinked(14);
结果:
I find it,its name is D
删除
TestLinkedList list=new TestLinkedList();
list.insertFirst(10, "A");
list.insertFirst(11, "B");
list.insertFirst(12, "C");
list.insertFirst(14, "D");
list.insertFirst(15, "E");
list.insertFirst(16, "F");
list.disPlayLinkedList();
// list.findLinked(14);
list.deleteLinked(14);
list.disPlayLinkedList();
结果:
Linked [age=16, name=F]
Linked [age=15, name=E]
Linked [age=12, name=C]
Linked [age=11, name=B]
Linked [age=10, name=A]
可以看到age=14,name=”D”的节点被清除掉了
需要说明一点:其实链表的删除,只是将链表中的某一个节点,其连接关系,pre,and ,next打断,然后将前一个和后一个直接相连;这个说来,其实他的数据,还是在内存空间内的,Java里我们有垃圾回收器,在一个伴随线程里,对无用对象进行清理;
其他链表基本原理和单链表类似