链表的理解

 

一、链表的基本结构

      链表程序的本质在于节点的相互引用,缺点就是数据的保存顺序就是你的添加顺序

      public class Link{
           private class  Node{
           private Object data;
           private Node next;//下一个节点;用作自身关联
           public Node(Object data){
               this.data=data;//创建节点的时候封装数据,由于节点有序,封装的数据也就有序了
           }
        }
       
        /*----------------以下是Link的操作-------------------*/
        private Node root;
        public void add(Object data){
         ...
        }
         ...
         
     }

   二、链表和动态数组关系:
      1.数组的长度等于链表的长度,链表如果添加了数据,长度就发生了变化,
         间接地数组的长度也就发生了变化,即可以实现动态数组(长度可变)
       private Object[] rdata; 
       public Object[] toArray(){//将链表转化为对象数组
        //判断链表是否为空
        if(count==0 || this.root==null){
            return null;
        }
        //count:链表的长度
        this.rdata=new Object[count];
        foot=0;//foot清零,
        //用this.root去获取数据(Node类来获取数据)
        this.root.toArrayNode();
        return rdata;

        //在Node类中取数据
        public void toArrayNode(){
            Link_get.this.rdata[Link_get.this.foot++]=this.data;
            if(this.next!=null){
                this.next.toArrayNode();
            }
        }
    }
 
      2.链表添加一个数据(实际是将数据封装在Node中)
        然后将封装了数据的节点添加到链表中,
        数组对应保存一个数据(采用索引foot++实现),链表         
         输出可以通过遍历数组获取数据
        private Node root;
        public void add(Object data){
            if(data==null) return ;
            Node newNode =new Node(data);//封装数据到节点中
            if(this.root==null){
                this.root=newNode;//将一个节点赋值给根节点
            }else{
                this.root.addNode(newNode);//交给Node类自己去完成节点的排序任务
            }
        }
      
        //第一次调用:this代表的是Link.root(根节点)
        public void addNode(Node newNode){
         if(this.next==null){
              this.next=newNode;
          }else{
              if(this.next!=null){
                  this.next.addNode(newNode);
               }
          }   
       }
 
       
      3.链表删除数据
         public void delete(Object data){
             if(this.contains(data)){//链表存在要删除的数据
                 if(this.root.data.equals(data)){//要删除的数据在根节点中
                      this.root=this.root.next;//删除根节点
                 }else{//要删除的数据不在根节点中
                      //删除其它节点的条件是:要被删除的节点的上一个节点.next=要被删除的节点.next
                      //所以传入的参数应该有:调用方法的节点的上一个节点和要被删除的数据
                      this.root.next.deleteNode(this.root,data);//this.root就是调用deleteNode方法的节点this.root.next的上一个节点
                  } 
                 //注意:删除数据之后,链表的长度会发生改变
                  count--;
             }
         }
       
           //在Node类中
           public void deleteNode(Node previous,Object data){
              if(this.next.data.equals(data)){
                   previous.next=this.next;
               }else{
                   if(this.next!=null){
                       this.next.deleteNode(this,data);
                   }
               }

           }

 
/*
 *自定义的一个较完整的链表类
 */
package com.petshop;

public class Link {
     private class Node{
         private Object data;
         private Node next;
         public Node(Object data){
             this.data=data;
         }
         //添加节点
         public void addNode(Node newNode){
             if(this.next==null){
                 this.next=newNode;
             }else{
                 this.next.addNode(newNode);
             }
         }
         public void toArrayNode(){
             //将取出的数据放在rdata数组中
             Link.this.rdata[Link.this.foot++]=this.data;//取出根节点的数据
             if(this.next!=null){
                 this.next.toArrayNode();
             }
         }
         //判断是否包含要查询的数据
         public boolean containsNode(Object data){
             if(this.data.equals(data)){//根节点的数据满足查询条件
                 return true;
             }else{
                 if(this.next!=null){
                    return this.next.containsNode(data);
                 }else{
                     return false;
                 }
             }
         }
         //根据索引查找数据
         public Object getNode(int index){
             if(Link.this.foot++ == index){
                 return this.data;
             }else{
                 if(this.next!=null){
                       return this.next.getNode(index);
                 }else{
                     return null;
                 }     
             }
         }
         //根据索引修改数据
         public void setNode(int index,Object data){
             if(Link.this.foot++ == index){
                 this.data=data;
             }else{
                 if(this.next!=null){
                     this.next.setNode(index, data);
                 }
             }
         }
         /*
          * 第一次调用:this:Link.root.next; previous:Link.root
          * 第二次调用:this:Link.root.next.next; previous:Link.root.next
          */
         public void removeNode(Node previous,Object data){
             if(this.data.equals(data)){
                 previous.next=this.next;
             }else{
                 if(this.next!=null){
                     this.next.removeNode(this, data);//this是this.next的上一个节点
                 }
             }
             
         }
     }
    
/*---------------以下是Link的操作----------------------------*/ 
     
     private Node root;
     private int count;
     private int foot;
     private Object[] rdata;//用于存储链表中的数据
     
     //删除数据
     public void remove(Object data){
         if(this.contains(data)){//确保链表中包含有要删除数据
             if(this.root.data.equals(data)){//判断删除数据是否在根节点中
                 //删除根节点
                 this.root=this.root.next;
             }else{ //要删除的数据不在根节点中
                 //删除其它节点:删除节点的上一个节点.next=删除节点.next;
                 //所以传入参数有:删除节点的上一个节点和要删除的数据
                 this.root.next.removeNode(this.root,data);
             }
             //注意链表长度的改变
               count--;
         }
         
     }
     
     //根据索引修改数据
     public void set(int index,Object data){
         if(index>=count || data==null || this.root ==null){
             return;
         }else{
             //Link类做一些判断,最终实现细节的操作都是由Node类来完成
             /*
              *this.root.containsNode()
              *this.root.toArrayNode()
              *this.root.getNode()
              *...
              */
             this.root.setNode(index,data);
         }
     }
     
     //根据索引获取数据
     public Object get(int index){
         if(index>=count || this.root==null){
             //索引大于了链表的长度(数组的长度)
             return null;
         }else{
             //从根节点(foot=0)开始查询,直到数组的索引等于要查询的索引为止
             foot=0;
             return this.root.getNode(index);
         }
         
     }
     
     //判断链表是否存在有要被查询的数据
     public  boolean contains(Object data){
         if(data==null || this.root==null){
             return false;
         }else{
             //从根节点开始查询是否存在查询的数据
             return this.root.containsNode(data);
         }
     }
     
     public Object[] toArray(){
         if(count==0 || this.root==null){
             return null;
         }
         //忘记写了
         rdata=new Object[count];//动态定义数组长度
         foot=0;
         this.root.toArrayNode();//采用链表去获取数据
         return this.rdata;
     }
     //获取链表数据的个数
     public int size(){
         return count;
     }
         //判断链表是否为空
     public boolean isEmpty(){
         return count==0 && this.root==null;
     }
          //链表添加数据
     public void add(Object data){
         if(data==null) return ;
         Node newNode=new Node(data);
         if(this.root==null){
             this.root=newNode;
         }else{
             this.root.addNode(newNode);
         }
         //记录链表长度
         count++;
     }
}
原文地址:https://www.cnblogs.com/yuefeng123/p/7460709.html