链表的实现(2)

1. 开发可用链表

 可用链表是指可以使用链表实现数据的增加、修改、删除和查询操作。

a. 程序基本结构

   Node类负责所有的节点数据的保存以及节点关系的匹配,所以Node类不可能单独去使用。
   范例:链表的开发结构
   class Link{//链表类,外部能够看见的只有这一个
          private class Node{//定义节点类
private String data; //保存数据
private Node next; //引用关系
public Node(String data){
      this.data = data;
}
 }
     //=====================以上为内部类=======================
          private Node root; //需要根节点

   }

b. 数据增加:public void add(数据类型 变量)

   
   如果要进行新数据的增加,则应该有Link类负责节点对象的产生,并且由Link类维护根节
   点,所有节点的关系匹配交给Node类处理。
   class Link{//链表类,外部能够看见的只有这一个
          private class Node{//定义节点类
private String data; //保存数据
private Node next; //引用关系
public Node(String data){
      this.data = data;
}
                public void addNode(Node newNode){
     if(this.next == null){//当前的下一个节点为空
         this.next = newNode;
                      }else{
  this.next.addNode(newNode);
     }
}
 }
     //=====================以上为内部类=========================
          private Node root; //需要根节点
          public void add(String data){
Node newNode = new Node(data);//要保存的数据
if(this.root == null){
   this.root = newNode; //保存根节点
}else{ //根节点存在,其它节点交给Node类处理
   this.root.addNode(newNode);
}
 }
   }
   public class LinkDemo{
    public static void main(String args[]){
       Link all = new Link();
 all.add("Hello");
 all.add("World");
  }
}

c.取得保存元素个数:public int size()

  既然每个链表都有一个root根元素,那么每一个链表就有自己的长度,可以直接在Link类
  里面设置一个count属性,随后每一次数据添加完成之后可以进行数据累加。
 范例:修改Link类
   增加一个count属性:
  class Link{//链表类,外部能够看见的只有这一个
          private class Node{//定义节点类
          ...
 }
     //=====================以上为内部类===================
          private Node root; //需要根节点
          private int count=0;//保存元素的个数
          public void add(String data){
Node newNode = new Node(data);//要保存的数据
if(this.root == null){
   this.root = newNode; //保存根节点
}else{ //根节点存在,其它节点交给Node类处理
   this.root.addNode(newNode);
}
this.count ++;//每一次保存完数据count加1
 }
 public int size(){ //取得保存的数据量
      return this.count;
 }

   }

d. 判断是否为空链表:public boolean isEmpty()

   空链表判断实际上可以通过两种方式完成:
   ·第一个:判断root有对象(是否为null);
   ·第二个:判断保存的数据量(count);
范例:
    class Link{
...
public boolean isEmpty(){
      return this.count==0;
}
    }

e. 数据查询 public boolean contains(数据类型 变量)

   在链表之中一定会保存多个数据,那么基本的判断某一个数据是否存在的方式:
   以String数据为例,循环链表中的内容,并且与要查询的数据进行匹配(equals()),如  
   果查找到返回true,查不到返回false。
范例:修改Link 类
class Link{
     ...
     public boolean contains(String data){
   if (data ==null || this.root == null ){
                      return false;
   }
            return this.root. containsNode(data);//给Node类,从根节点开始查
}
}
修改Node 类
private class Node{//定义节点类
private String data; //保存数据
private Node next; //引用关系
public Node(String data){
      this.data = data;
}
                public void addNode(Node newNode){
...
}
//第一次调用(Link):this = Link.root
//第二次调用(Node): this = Link.root.next
public boolean containsNode(String data){
             if(data.equals(this.data)){//当前节点数据为查询的数据
 return true;//后面不要查询了
}else{ //当前节点不满足查询要求
  if (this.next!= null){
      return this.next.containsNode(data);
  }else{ //没有后续节点
return false;
                           }
}
}
 }
本次使用的是String 数据类型,所以判断数据使用的是equals()方法,如果是自定义对象呢
?则需要定义一个对象比较的方法(compare())。


f. 根据索引取得数据:public 数据类型 get(int index)

   通过以上的代码测试,链表里面保存了多个String类的对象,在程序里面只有数组可以保
存多个对象,使用的链表与数组相比较的话,优势就是没有长度限制,所以链表严格意义上

来讲就是一个动态对象数组,那么也应该具备像数组那样可以根据索引取得元素的功能。

   由于是动态对象数组,所以数组中的每一个元素的索引的内容都一定是动态生成的。

范例:在Link类里面增加一个foot的属性表示每一个Node元素的编号
      private int foot = 0;
      在每一次查询的时候(一个链表可能查询多次),那么foot应该在每一次查询时都从
头开始。但是千万要记住,如果有内容,或者是要查询的索引小于个数才可以查。
     public String get(int index){
if (index>this.count){ //超过了查询范围
     return null; //没有数据
}
         this.foot =0; //表示从前向后查询
         return this.root. getNode(index);//查询过程交给Node类
     }
范例:在Node类里面实现getNode()方法,内部类和外部类之间可以方便的互相访问私有属性
private class Node{//定义节点类
private String data; //保存数据
private Node next; //引用关系
public Node(String data){
      this.data = data;
}
                public void addNode(Node newNode){
...
}
//第一次调用(Link):this = Link.root
//第二次调用(Node): this = Link.root.next
public boolean containsNode(String data){
...
}
                public String getNode(int index){
                       if(Link.this.foot ++ == index){ //为要查询的索引
   return this.data;//返回当前节点数据
}else{ //现在应该继续向后查询
   return this.next.getNode(index);
}
}
 }

g. 修改指定索引内容:public void set(int index, 数据类型 变量)

   修改数据和查询的区别不大,查询的时候当满足索引值的时候,只是进行了一个数据的返回,那么此处只需要将数据返回变为数据的重新赋值即可。
范例:在Link 类里面增加set()方法
      public void set(int index, String data){
   if (index > this.count){
return; //结束方法调用
   }
            this.foot = 0; //重新设置foot属性的内容,作为索引出现
   this.root. setNode(index,data); //交给Node类设置数据内容
}
范例:在Node类增加setNode()方法
      public void setNode(int index, String data){
              if (Link.this.foot ++ == index){
                    this.data = data;//进行内容的修改
}else{
                     this.next.setNode(index,data);
}
}

h. 删除数据:public void remove(数据类型 变量)

 对于删除数据而言,实际上分为两种情况:
    ·情况-:要删除的节点是根节点,则root应该变为“根节点.next”,在Link类里处理。

    ·情况二:要删除的是非根节点,应该在Node类里处理,此处是从第二个节点开始判断的。

 删除数据的最终形式,当前节点的上一节点.next=当前节点.next,即空出了当前节点。

 范例:在Node类里面增加一个removeNode(),此方法专门处理非根节点的删除

    //要传递上一个节点以及要删除的数据
public void removeNode(Node previous, String data){
               if(data.equals(this.data)){ //当前节点为要删除节点
   previous.next = this.next;
}else{ //应该继续向后查询
   this.next.removeNode(this, data);
}
}
  范例:在Link类里面增加根节点的删除
       public void remove(String data){
              if(this.contains(data)){//主要是判断数据是否存在
         //要删除数据是否是根节点数据
 //root是Node类的对象,此处直接访问了内部类的私有操作
                  if(data.equals(this.root.data)){ //为要删除节点
      this.root = this.root.next; //空出当前根节点
 }else{ //不是根元素
//此时根元素已经判断过了,从第二个元素开始判断
this.root.next. removeNode(this.root, data);
 }
         this.count --;//个数要减少
     }

        }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值