您的位置:首页 > 编程语言 > Java开发

单链表的Java实现(全方法)

2017-04-28 21:37 239 查看
只有当自己去写一遍数据结构时,才能真正体会到其中的妙处,多思考数据结构的写法为什么不用其他的方式,有助于对代码的理解。
本文的注释较为详细,细节之处请看代码对应的注释。


/**
* @title 单链表的Java实现
* @author 未名
* @date 2017-4-28
*
* @implement
*      通过闭卷书写一遍,再与课本的写法对比、修改,加深了对数据结构的理解,提升了编码能力
*      1、其中Node节点的有参构造方法可以为Node(data),或者为Node(data,next),在这里只用了第一种
*      2、再链表类参数申明中,length和p是一个可选项。
*          (1)若声明了length,需要在相应的方法中用到它,当方法较多时容易出错。
*              若不声明,只用在size()方法中返回一个数值即可。本文采用了length
*          (2)若声明了Node next= p,则在单链表的方法中不用新建变量,直接用统一的p,就不用每次写方法都新建节点变量
*              若不声明,在每个方法中p的名字可以是front、rear等等,使用起来比较直观。本文采用此种方法
*      3、在不同实现方法中,head 可以是节点,也可以只作为指针,本文采用后者
*      4、还有诸多细节之处需要自己写一遍才能体会,这里不做一一说明,有疑问欢迎留言交流
*/

package datastructure;

public class LinkedList<A> {
public Node<A> head ;//该处为头指针,指向头结点(自己并非是头结点)
//Node<A> p = head;//增加节点P来记录当前的节点位置
private int length = 0;

//1、构造方法
public LinkedList(){    //构造空单链表
this.head = new Node<A>();
}

public LinkedList(A[] val){
this();   //调用无参构造方法,构造空链表
Node<A> rear = this.head;
for(int i=0;i<val.length;i++){
rear.next = new Node<A>(val[i]);
rear = rear.next;
length++;
}
}

public boolean isEmpty(){
return this.head.next == null; //头结点为空时链表为空
}

//2、数据存取
public A get(int index){   //下标越界返回null而不是返回异常
Node<A> p = this.head.next;
p = head ;
if(index<0||p==null)
return null;
for(int i=0;i<=index&&p!=null;i++)
p=p.next;
return p.data;
}

public void set(int i,A x){
Node<A> p = this.head.next;
for(int j=0;j<i;j++){
p = p.next;
}
p.data = x;
}

public int size(){
return length;
}

public String toString(){
String s = this.getClass().getName()+"(";
for(Node<A> p=this.head.next;p!=null;p=p.next){
s+=p.data.toString();
if(p.next!=null)
s+=","; //不是最后一点时加分隔符
}
return s+")";
}

//3、插入
public Node<A> insert(int index,A data){
if(data==null)
throw new NullPointerException("data=null");
Node<A> front = this.head;  //指向头指针,所以插入节点时就包括了插入到空表插入、头结点和中间节点及尾部节点的情况
//删除以下条件设置是因为index必须要容错,为防止超过上限,for循环中加条件front.next!=null
//      if(index>length||index<0)
//          return null;  //
for(int i=0;i<index&&front.next!=null;i++){
front = front.next; //最多只会指向最后一个节点
}
front.next = new Node<A>(data);
length++;
return front.next;
}

public Node<A> insert(A data){
length++;
return insert(length,data); //实际应为length-1,但是insert(,)具有容错性
}

//4、删除
public A remove(int index){
if(index>=length||index<0){
return null;
}else{
Node<A> front = this.head;
for(int i=0;i<index;i++){
front = front.next;
}
A oldData = front.next.data;
front = front.next.next;
length--;
return oldData;
}
}

public A remove(){
return remove(--length);  //删除尾部节点
}

public void clear(){
this.head.next = null;  //Java自动回收
}

//5、查找相关
public Node<A> search(A key){   //查找第一个与key相等的元素
Node<A> p = this.head.next;
while(p!=null){
if(p.data==key)
break;
p = p.next;
}
return p;
}

public boolean contains(A key){
Node<A> p = search(key);
if(p==null)
return false;
return true;
}

public Node<A> insertDifferent(A x){
if(contains(x))
return null;
return insert(x);
}

public A remove(A x){   //删除与x相等的元素
Node<A> p=this.head.next;
for(int i=0;p!=null;p=p.next,i++){
if(p.data==x)
return remove(i);
}
return null;
}
//遍历所有元素,在这里其实与toString重复
public void travelAll(){
Node<A> p = head.next;
System.out.println("All elements is:");
while(p!=null){     //用while循环而不同for,减少中间变量的使用
System.out.print(p.toString()+" ");
p=p.next;
}
}
}

class Node<A> {
protected A data;
protected Node<A> next;

public Node(){
this.data = null;
}

public Node(A data){
this.data = data;
//this.next = next;
}
//输出存储数据信息
public String toString(){
return data.toString();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息