继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

【新手自白书】简单单项链表的实现(JAVA)

肆意先生
关注TA
已关注
手记 6
粉丝 0
获赞 151

复习一下简单单项链表的实现。

在动手写链表之前,需要思考链表是如何组成的,一般来说,一个简单的单项链表主要是由节点构成,由于链表的特性,头节点是一个十分重要的成员,所以,链表必须的成员是节点Node,头指针headNode;链表的基础功能是增删改查,所以应有关于增删改查的四个方法;链表应该提供打印链表的功能,故应该有这个方法:

public class Links{
    class Node{}
    private Node headNode = null ;
    public void addNodeToLink(){}
    public void delNodeFromLink(){}
    public void sltNodeFromLink(){}
    public void fixNodeFromLink(){}
    public void printLink(){}
}

为了丰富链表的操作,我们可以追加一下几个属性,链表长度length,备用指针节点pointNode;方法中应该提供获取链表总长的方法,初始化备用节点的方法:

public class Links{
    class Node{}
    private Node headNode = null ;
    private Node pointNode = headNode ;
    private int length = 0 ;
    public void addNodeToLink(){}
    public void delNodeFromLink(){}
    public void sltNodeFromLink(){}
    public void fixNodeFromLink(){}
    public void printLink(){}
    public int getLinkLength(){
        return this.length ;
    }
    public void resetPointNode(){
        this.pointNode = null ;
    }
}

接下来思考Node类的成员。
Node是节点,那么必须有指向下一节点的引用next;Node中要有数据data,以及关于数据的getter和setter方法:

public class Links{
    class Node{
        private String data = null ;
        private Node next = null ;
        public Node(String data){
            this.setData(data) ;
        }
        public void setData(String data){
            this.data = data ;
        }
        public String getData(){
            return this.data ;
        }
    }
    private Node headNode = null ;
    private Node pointNode = headNode ;
    private int length = 0 ;
    public void addNodeToLink(){}
    public void delNodeFromLink(){}
    public void sltNodeFromLink(){}
    public void fixNodeFromLink(){}
    public void printLink(){}
    public int getLinkLength(){
        return this.length ;
    }
    public void resetPointNode(){
        this.pointNode = null ;
    }
}

成员基本定义好了以后,开始逐一实现方法。

  • 增加
    链表增加节点之前一定要确定是否是头结点,如果头结点为空就将头结点设置为我们新建的节点。节点的添加使用尾插法,即新的节点链接在链表的尾部,判断的逻辑为:如果当前节点为空,则把新建的节点设置为此节点,如果该节点不为空,则检查该节点的next引用。此过程是一个递归的过程,如果该过程在链表的方法里实现会很麻烦,所以可以在Node类中定义方法,让节点自行判断,代码如下:
public class Links{
    class Node{
        private String data = null ;
        private Node next = null ;
        public Node(String data){
            this.setData(data) ;
        }
        public void setData(String data){
            this.data = data ;
        }
        public String getData(){
            return this.data ;
        }
        public void linkNext(Node node){        //链表增加指定的节点
            if(this.next == null){              //如果当前节点的下一个节点为null,就将传入的节点设置为next
                this.next = node ;
            }else{                              //如果当前节点的下一个节点不为空,则让next节点递归调用此方法
                this.next.linkNext(node) ;
            }
        }
    }
    private Node headNode = null ;
    private Node pointNode = headNode ;
    private int length = 0 ;
    public void addNodeToLink(String data){     //向链表中添加一个节点
        Node node = new Node(data) ;
        if(this.headNode == null){          //如果头结点为空,则将该节点设置为头节点
            this.headNode = node ;
        }else{
            this.headNode.linkNext(node) ;  //如果头结点不会为,则调用节点类中的方法处理
        }
        this.length ++ ;                    //链表长度+1
    }
    public void delNodeFromLink(){}
    public void sltNodeFromLink(){}
    public void fixNodeFromLink(){}
    public void printLink(){}
    public int getLinkLength(){
        return this.length ;
    }
    public void resetPointNode(){
        this.pointNode = null ;
    }
}

至此,增加功能设计完毕。

  • 查找

由于删除和修改的本质是先查找再操作,所以先实现查找功能。
查找的本质也是递归调用,运用Node方法中的getter方法和传进去的数据进行比较,如果一样则说明存在,如果不一样则调用该节点的next引用,当next引用为空的时候仍然没有一样的,说明不存在该节点,逻辑上还是很好实现的,需要注意的是,凡事递归最好都在Node中定义,因为这样比较好实现:

public class Links{
    class Node{
        private String data = null ;
        private Node next = null ;
        public Node(String data){
            this.setData(data) ;
        }
        public void setData(String data){
            this.data = data ;
        }
        public String getData(){
            return this.data ;
        }

        public void linkNext(Node node){        //链表增加指定的节点
            if(this.next == null){              //如果当前节点的下一个节点为null,就将传入的节点设置为next
                this.next = node ;
            }else{                              //如果当前节点的下一个节点不为空,则让next节点递归调用此方法
                this.next.linkNext(node) ;
            }
        }

        public boolean selectNode(String data){ //根据给定的data查找是否存在该节点
            if(this.getData().equals(data)){
                return true ;                   //存在,返回true
            }else{
                if(this.next != null){          //如果当前节点的下一个节点不为空,返回下一个节点的调用结果
                    return this.next.selectNode(data) ;
                }else{
                    return false ;              //当前节点的下一个节点为空,说明不存在该节点,返回false
                }
            }
        }

    }
    private Node headNode = null ;
    private Node pointNode = headNode ;
    private int length = 0 ;

     public void addNodeToLink(String data){     //向链表中添加一个节点
        Node node = new Node(data) ;
        if(this.headNode == null){          //如果头结点为空,则将该节点设置为头节点
            this.headNode = node ;
        }else{
            this.headNode.linkNext(node) ;  //如果头结点不会为,则调用节点类中的方法处理
        }
        this.length ++ ;                    //链表长度+1
    }

    public void delNodeFromLink(){}

    public void sltNodeFromLink(String data){       //查找一个节点
        boolean hasNode = true ;
        if(this.headNode.selectNode(data) == hasNode){
            System.out.println("存在节点【" + data + "】") ;
        }else{
            System.out.println("不存在节点【" + data + "】") ;
        }
    }

    public void fixNodeFromLink(){}
    public void printLink(){}
    public int getLinkLength(){
        return this.length ;
    }
    public void resetPointNode(){
        this.pointNode = null ;
    }
}
  • 修改
    修改和查找的思路基本一样,找到节点之后用setter方法设置即可,不赘述:
public class Links{
    class Node{
        private String data = null ;
        private Node next = null ;
        public Node(String data){
            this.setData(data) ;
        }
        public void setData(String data){
            this.data = data ;
        }
        public String getData(){
            return this.data ;
        }

        public void linkNext(Node node){        //链表增加指定的节点
            if(this.next == null){              //如果当前节点的下一个节点为null,就将传入的节点设置为next
                this.next = node ;
            }else{                              //如果当前节点的下一个节点不为空,则让next节点递归调用此方法
                this.next.linkNext(node) ;
            }
        }

        public boolean selectNode(String data){ //根据给定的data查找是否存在该节点
            if(this.getData().equals(data)){
                return true ;                   //存在,返回true
            }else{
                if(this.next != null){          //如果当前节点的下一个节点不为空,返回下一个节点的调用结果
                    return this.next.selectNode(data) ;
                }else{
                    return false ;              //当前节点的下一个节点为空,说明不存在该节点,返回false
                }
            }
        }

       public void fixNode(String oldData,String newData){      //修改节点
        if(this.getData().equals(oldData)){
            this.setData(newData) ;
        }else{
            if(this.next != null){
                this.next.fixNode(oldData, newData) ;
            }
        }
    }
    }
    private Node headNode = null ;
    private Node pointNode = headNode ;
    private int length = 0 ;

     public void addNodeToLink(String data){     //向链表中添加一个节点
        Node node = new Node(data) ;
        if(this.headNode == null){          //如果头结点为空,则将该节点设置为头节点
            this.headNode = node ;
        }else{
            this.headNode.linkNext(node) ;  //如果头结点不会为,则调用节点类中的方法处理
        }
        this.length ++ ;                    //链表长度+1
    }

    public void delNodeFromLink(){}

    public void sltNodeFromLink(String data){       //查找一个节点
        boolean hasNode = true ;
        if(this.headNode.selectNode(data) == hasNode){
            System.out.println("存在节点【" + data + "】") ;
        }else{
            System.out.println("不存在节点【" + data + "】") ;
        }
    }

   public void fixNodeFromLink(String oldData,String newData){      //修改节点数据
        boolean hasNode = true ;
        if(this.headNode.selectNode(oldData) == hasNode){
            this.headNode.fixNode(oldData, newData) ;
        }else{
            System.out.println("链表中没有【"+ oldData +"】节点,无法完成修改");
        }
    }
    public void printLink(){}
    public int getLinkLength(){
        return this.length ;
    }
    public void resetPointNode(){
        this.pointNode = null ;
    }
}
  • 删除
    删除比修改要稍复杂,删除的本质,是将要删除的节点的上一个节点的next引用改成该节点的next引用,即:

last.next = this.next

因为头结点没有last节点,所以要分开处理:如果是头结点,则把头结点更改为头结点的next节点即可,如果不是头结点,则要把last节点一并传入。如果是递归操作的话,第二个节点调用的方法只要把头结点传入即可完成递归:

public class Links{
    class Node{
        private String data = null ;
        private Node next = null ;
        public Node(String data){
            this.setData(data) ;
        }
        public void setData(String data){
            this.data = data ;
        }
        public String getData(){
            return this.data ;
        }

        public void linkNext(Node node){        //链表增加指定的节点
            if(this.next == null){              //如果当前节点的下一个节点为null,就将传入的节点设置为next
                this.next = node ;
            }else{                              //如果当前节点的下一个节点不为空,则让next节点递归调用此方法
                this.next.linkNext(node) ;
            }
        }

        public boolean selectNode(String data){ //根据给定的data查找是否存在该节点
            if(this.getData().equals(data)){
                return true ;                   //存在,返回true
            }else{
                if(this.next != null){          //如果当前节点的下一个节点不为空,返回下一个节点的调用结果
                    return this.next.selectNode(data) ;
                }else{
                    return false ;              //当前节点的下一个节点为空,说明不存在该节点,返回false
                }
            }
        }

       public void fixNode(String oldData,String newData){      //修改节点
        if(this.getData().equals(oldData)){
            this.setData(newData) ;
        }else{
            if(this.next != null){
                this.next.fixNode(oldData, newData) ;
            }
        }
    }

    public void delectNode(Node lastNode,String data){      //删除节点
        if(this.getData().equals(data)){
            lastNode.next = this.next ;
        }else{
            if(this.next != null){
                this.next.delectNode(this, data) ;
            }
            //在外部方法中已经进行了节点是否存在的验证,所以不用考虑this.next = null的情况
        }
    }
    }
    private Node headNode = null ;
    private Node pointNode = headNode ;
    private int length = 0 ;

     public void addNodeToLink(String data){     //向链表中添加一个节点
        Node node = new Node(data) ;
        if(this.headNode == null){          //如果头结点为空,则将该节点设置为头节点
            this.headNode = node ;
        }else{
            this.headNode.linkNext(node) ;  //如果头结点不会为,则调用节点类中的方法处理
        }
        this.length ++ ;                    //链表长度+1
    }

    public void delNodeFromLink(String data){       //删除一个节点
        boolean hasNode = true ;
        if(this.headNode.selectNode(data) == hasNode){
            if(this.headNode.getData().equals(data)){
                this.headNode = this.headNode.next ;
                this.length -- ;
            }else{
                this.headNode.next.delectNode(this.headNode,data) ;
                this.length -- ;
            }
        }else{
            System.out.println("链表中没有【"+ data +"】节点,无法完成删除");
        }
    }

    public void sltNodeFromLink(String data){       //查找一个节点
        boolean hasNode = true ;
        if(this.headNode.selectNode(data) == hasNode){
            System.out.println("存在节点【" + data + "】") ;
        }else{
            System.out.println("不存在节点【" + data + "】") ;
        }
    }

   public void fixNodeFromLink(String oldData,String newData){      //修改节点数据
        boolean hasNode = true ;
        if(this.headNode.selectNode(oldData) == hasNode){
            this.headNode.fixNode(oldData, newData) ;
        }else{
            System.out.println("链表中没有【"+ oldData +"】节点,无法完成修改");
        }
    }
    public void printLink(){}
    public int getLinkLength(){
        return this.length ;
    }
    public void resetPointNode(){
        this.pointNode = null ;
    }
}
  • 打印

最后将打印功能加入:

public void printLink(){        //打印链表
        this.pointNode = this.headNode ;
        System.out.print("输出链表:");
        for(int i=0 ;i < this.length ;i ++){
            if(this.pointNode.next == null){
                System.out.println(this.pointNode.getData());
            }else{
                System.out.print(this.pointNode.getData() + "->");
            }
            this.pointNode = this.pointNode.next ;
        }
        this.resetPointNode() ;
    }

完整代码如下:

public class Links{

    class Node{         //内部类来实现
        private String data = null ;    //节点数据
        private Node next = null ;      
        public Node(String data){
            this.setData(data) ;
        }
        public void setData(String data){
            this.data = data ;
        }
        public String getData(){
            return this.data ;
        }

        public void linkNext(Node node){        //链表增加指定的节点
            if(this.next == null){              //如果当前节点的下一个节点为null,就将传入的节点设置为next
                this.next = node ;
            }else{                              //如果当前节点的下一个节点不为空,则让next节点递归调用此方法
                this.next.linkNext(node) ;
            }
        }

        public boolean selectNode(String data){ //根据给定的data查找是否存在该节点
            if(this.getData().equals(data)){
                return true ;                   //存在,返回true
            }else{
                if(this.next != null){          //如果当前节点的下一个节点不为空,返回下一个节点的调用结果
                    return this.next.selectNode(data) ;
                }else{
                    return false ;              //当前节点的下一个节点为空,说明不存在该节点,返回false
                }
            }
        }

        public void fixNode(String oldData,String newData){     //修改节点
            if(this.getData().equals(oldData)){
                this.setData(newData) ;
            }else{
                if(this.next != null){
                    this.next.fixNode(oldData, newData) ;
                }
            }
        }

        public void delectNode(Node lastNode,String data){      //删除节点
            if(this.getData().equals(data)){
                lastNode.next = this.next ;
            }else{
                if(this.next != null){
                    this.next.delectNode(this, data) ;
                }
                //在外部方法中已经进行了节点是否存在的验证,所以不用考虑this.next = null的情况
            }
        }
    }

    private int length = 0 ;    //记录链表长度
    private Node headNode = null ;      //头结点
    private Node pointNode = null ;     //备用指针

    public void resetPointNode(){   //备用指针节点初始化
        this.pointNode = null ;
    }

    /* 增加 */
    public void addNodeToLink(String data){     //向链表中添加一个节点
        Node node = new Node(data) ;
        if(this.headNode == null){          //如果头结点为空,则将该节点设置为头节点
            this.headNode = node ;
        }else{
            this.headNode.linkNext(node) ;  //如果头结点不会为,则调用节点类中的方法处理
        }
        this.length ++ ;                    //链表长度+1
    }

    /* 删除 */
    public void delNodeFromLink(String data){       //删除一个节点
        boolean hasNode = true ;
        if(this.headNode.selectNode(data) == hasNode){
            if(this.headNode.getData().equals(data)){
                this.headNode = this.headNode.next ;
                this.length -- ;
            }else{
                this.headNode.next.delectNode(this.headNode,data) ;
                this.length -- ;
            }
        }else{
            System.out.println("链表中没有【"+ data +"】节点,无法完成删除");
        }
    }

    /* 查找 */
    public void sltNodeFromLink(String data){       //查找一个节点
        boolean hasNode = true ;
        if(this.headNode.selectNode(data) == hasNode){
            System.out.println("存在节点【" + data + "】") ;
        }else{
            System.out.println("不存在节点【" + data + "】") ;
        }
    }

    /* 修改 */
    public void fixNodeFromLink(String oldData,String newData){     //修改节点数据
        boolean hasNode = true ;
        if(this.headNode.selectNode(oldData) == hasNode){
            this.headNode.fixNode(oldData, newData) ;
        }else{
            System.out.println("链表中没有【"+ oldData +"】节点,无法完成修改");
        }
    }

    public int getLinkLength(){     //获取链表长度
        return this.length ;
    }

    public void printLink(){        //打印链表
        this.pointNode = this.headNode ;
        System.out.print("输出链表:");
        for(int i=0 ;i < this.length ;i ++){
            if(this.pointNode.next == null){
                System.out.println(this.pointNode.getData());
            }else{
                System.out.print(this.pointNode.getData() + "->");
            }
            this.pointNode = this.pointNode.next ;
        }
        this.resetPointNode() ;
    }

    /*
    public void delNodeFromLink(int nodeNum){}
    public void sltNodeFromLink(int nodeNum){}
    public void fixNodeFromLink(int nodeNum){}
    //*/
}
  • 测试

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        Links link = new Links() ;
        //1 测试链表是否可以被正常创建
        link.addNodeToLink("1") ;
        link.addNodeToLink("2") ;
        link.addNodeToLink("3") ;
        System.out.println("链表的长度为:" + link.getLinkLength());

        ///*2 测试链表的查找功能
        link.sltNodeFromLink("1") ;
        link.sltNodeFromLink("2") ;
        link.sltNodeFromLink("3") ;
        link.sltNodeFromLink("4") ;//*/

        //3 测试链表的修改功能和打印链表功能
        link.printLink() ;
        link.fixNodeFromLink("4","3") ;
        link.fixNodeFromLink("3","4") ;
        link.printLink() ;

        //4 测试链表的删除功能
        link.delNodeFromLink("3") ;
        link.delNodeFromLink("4") ;
        link.printLink() ;

    }

}

输出结果:
链表的长度为:3
存在节点【1】
存在节点【2】
存在节点【3】
不存在节点【4】
输出链表:1->2->3
链表中没有【4】节点,无法完成修改
输出链表:1->2->4
链表中没有【3】节点,无法完成删除
输出链表:1->2

打开App,阅读手记
5人推荐
发表评论
随时随地看视频慕课网APP

热门评论

为啥在Node中添加了节点之后还要在链表中添加节点

查看全部评论