JAVA数据结构单链表

链表是以节点的方式来存储,是链式存储
每个节点包含data域,next域,指向下一个节点
如图,发现链表的各个节点不一定是连续存储
链表分带头节点和不带头节点链表,根据实际的需求来确定

链表主要的操作就是增删查改,还有逆序输出。

添加(创建)
1.先创建一个head头节点,作用就是表示单链表的头
2.后面我们每添加一个节点,就直接加到链表最后

遍历:
通过一个辅助变量,帮助遍历整个链表

 public void printList(){

        HeroNode temp = head.next;

        while (true){
            if (temp == null){
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }

插入:
按照有序加入节点:
首先找到新添加节点的位置,通过辅助变量指针来实现,
新的节点.next = temp.next;
将temp.next = 新的节点
插入一个节点:

 //添加节点到单链表
    //思路
    //1.找到这个链表的最后节点
    //2.将最后这个节点的next指向新的节点

    public void add(HeroNode heroNode){
        //因为head节点不可以动,所以我们添加一个辅助遍历temp
        HeroNode temp = head;

        //遍历链表找到最后
        while (true){
            //判断是否是最后一个节点
            if (temp.next == null){
                break;//找到最后节点就退出
            }
            temp = temp.next;//不是最后一个节点就往后移
        }
        temp.next = heroNode;//推出循环以后就将temp指向链表最后,然后就将传入的节点加入到链表最后
    }

按照节点顺序添加节点

 //按照顺序添加节点
    public  void addByOrder(HeroNode heroNode){
        //头节点不可以动,通过辅助指针来遍历
        //我们的temp要位于添加位置的前一个节点,否则插入不了

        HeroNode temp = head;
        boolean flag = false;
        while (true){

            if (temp.next == null){
                break;
            }
            if (temp.next.no > heroNode.no){
                break;
            }else if (temp.next.no == heroNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            System.out.printf("该编号%d已经存在,不可以插入\n",heroNode.no);
        }else{
            heroNode.next = temp.next;
            temp.next = heroNode;
        }

    }

删除
删除比较简单
只要将要删除前面的那个节点的next指向删除节点的next,这就实现了删除。

  //删除节点
    //我们需要找到要删除节点的前一个节点,然后删除节点
    public void del(int no){

        //判断链表是否为空
        if (head.next == null){
            System.out.printf("链表为空\n");
            return;
        }

        HeroNode temp = head;

        boolean flag = false;//标志是否找到要删除的节点
        while (true){

            if (temp.next == null){//已经到节点最后
                break;
            }
            if (temp.next.no == no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            temp.next = temp.next.next;
            System.out.printf("删除 %d 节点\n",no);
        }else {
            System.out.printf("删除失败\n");
        }
    }

修改:

  //修改节点信息
    public void update(HeroNode newHeroNode){

        //先判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //找到需要修改的节点,根据编号

        HeroNode temp = head.next;
        boolean flag = false;
        while (true){

            if (temp == null){
                break;
            }
            if (temp.no == newHeroNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag){
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
        }else{
            System.out.printf("编号为 %d 的节点没有找到\n",newHeroNode.no);
        }

    }

将单链表反装:
主要思路:
每遍历一个节点之后将节点放在链表最前面;
主要实现代码:

 public static void reverseLinkedList(HeroNode head){

     //判断链表是否为空
        if (head.next == null){
            System.out.print("链表为空");
            return ;
        }

        HeroNode cur = head.next;//定义一个辅助指针,帮助我们遍历原来的链表
        HeroNode next = null; //指向当前节点【cur】的下一个节点
        HeroNode reverseHead = new HeroNode(0,"","");
        //遍历原来的链表,每遍历一个节点,就将这个节点取出放入这个链表的最前面
        while (cur != null){

         next = cur.next;//先暂时保管下一个节点
         cur.next = reverseHead.next;//将cur的下一个节点指向链表的最前端
         reverseHead.next = cur;//将cur连接到新的链表上
         cur = next;//让cur后移
        }
        head.next = reverseHead.next;//将head.next指向reverseHead.next,实现单链表的反转
    }

查找单链表中的倒数第K个链表的节点

public static void findHeroNode(int k,HeroNode head){

     //判断链表是否为空
     if (head.next == null){
         System.out.printf("链表为空\n");
         return;
     }

     int length = getLength(head);//得到链表长度
     HeroNode temp = head.next;

     if (length < k || k < 0){
         System.out.print("输入查找条件不正确");
         return;
     }

    for (int i = 0; i < length - k; i++){
        temp = temp.next;
    }
    System.out.print("倒数第"+k+"个节点为:"+temp);
 }

得到链表长度

//得到链表的长度
 //传入一个头节点
 public static int getLength(HeroNode head){

      if (head.next == null){
          return 0;//链表为空
      }
      HeroNode temp = head.next;
      int length = 0;
      while (temp != null){
          length ++;
          temp = temp.next;
      }
    return length;
 }

上面是单链表的一些基本操作
下面是完整的测试代码

package com.gsy.linkedlist;

import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

import javax.rmi.ssl.SslRMIClientSocketFactory;

/**
 * @program: DataStructures
 * @description: 单链表
 * @author: GSY
 * @create: 2020-03-27 10:41
 **/
public class SingleLinkedListDemo {




 public static void main(String[] args){


     HeroNode heroNode1 = new HeroNode(1,"武松","行者");
     HeroNode heroNode2 = new HeroNode(2,"关羽","武圣");
     HeroNode heroNode3 = new HeroNode(3,"花容","小李广");
     HeroNode heroNode4 = new HeroNode(4,"林冲","豹子头");
     HeroNode heroNode5 = new HeroNode(5,"卢俊义","玉麒麟");

     SingleLinkedList singleLinkedList = new SingleLinkedList();

     //插入测试
    /* singleLinkedList.add(heroNode1);
     singleLinkedList.add(heroNode2);
     singleLinkedList.add(heroNode3);
     singleLinkedList.add(heroNode4);
     singleLinkedList.add(heroNode5);*/

    //按照节点号码顺序插入
     singleLinkedList.addByOrder(heroNode3);
     singleLinkedList.addByOrder(heroNode5);
     singleLinkedList.addByOrder(heroNode2);
     singleLinkedList.addByOrder(heroNode1);
     singleLinkedList.addByOrder(heroNode4);
     singleLinkedList.printList();


     HeroNode newHeroNode = new HeroNode(5,"卢哥","玉老虎");

     singleLinkedList.update(newHeroNode);
     System.out.printf("跟新之后\n");
     singleLinkedList.printList();

     singleLinkedList.del(1);
     System.out.printf("删除节点之后\n");
     singleLinkedList.printList();

     System.out.printf("链表长度为%d\n",getLength(singleLinkedList.getHead()));

     findHeroNode(1,singleLinkedList.getHead());

     System.out.print("\n反向输出\n");
     reverseLinkedList(singleLinkedList.getHead());
     singleLinkedList.printList();
 }



 //得到链表的长度
 //传入一个头节点
 public static int getLength(HeroNode head){

      if (head.next == null){
          return 0;//链表为空
      }
      HeroNode temp = head.next;
      int length = 0;
      while (temp != null){
          length ++;
          temp = temp.next;
      }
    return length;
 }



 /*
 * 查找单链表中的倒数第K个链表的节点
 *
 * */

 public static void findHeroNode(int k,HeroNode head){

     //判断链表是否为空
     if (head.next == null){
         System.out.printf("链表为空\n");
         return;
     }

     int length = getLength(head);//得到链表长度
     HeroNode temp = head.next;

     if (length < k || k < 0){
         System.out.print("输入查找条件不正确");
         return;
     }

    for (int i = 0; i < length - k; i++){
        temp = temp.next;
    }
    System.out.print("倒数第"+k+"个节点为:"+temp);
 }


    //将链表方向输出

    public static void reverseLinkedList(HeroNode head){

     //判断链表是否为空
        if (head.next == null){
            System.out.print("链表为空");
            return ;
        }

        HeroNode cur = head.next;//定义一个辅助指针,帮助我们遍历原来的链表
        HeroNode next = null; //指向当前节点【cur】的下一个节点
        HeroNode reverseHead = new HeroNode(0,"","");
        //遍历原来的链表,每遍历一个节点,就将这个节点取出放入这个链表的最前面
        while (cur != null){

         next = cur.next;//先暂时保管下一个节点
         cur.next = reverseHead.next;//将cur的下一个节点指向链表的最前端
         reverseHead.next = cur;//将cur连接到新的链表上
         cur = next;//让cur后移
        }
        head.next = reverseHead.next;//将head.next指向reverseHead.next,实现单链表的反转
    }

}


//定义SingleLinkedList来管理

class SingleLinkedList{

    //先初始化一个头节点,头节点不要动,不存放具体的数据

    private HeroNode head = new HeroNode(0,"","");

    public HeroNode getHead() {
        return head;
    }

    //添加节点到单链表
    //思路
    //1.找到这个链表的最后节点
    //2.将最后这个节点的next指向新的节点

    public void add(HeroNode heroNode){
        //因为head节点不可以动,所以我们添加一个辅助遍历temp
        HeroNode temp = head;

        //遍历链表找到最后
        while (true){
            //判断是否是最后一个节点
            if (temp.next == null){
                break;//找到最后节点就退出
            }
            temp = temp.next;//不是最后一个节点就往后移
        }
        temp.next = heroNode;//推出循环以后就将temp指向链表最后,然后就将传入的节点加入到链表最后
    }



    //按照顺序添加节点
    public  void addByOrder(HeroNode heroNode){
        //头节点不可以动,通过辅助指针来遍历
        //我们的temp要位于添加位置的前一个节点,否则插入不了

        HeroNode temp = head;
        boolean flag = false;
        while (true){

            if (temp.next == null){
                break;
            }
            if (temp.next.no > heroNode.no){
                break;
            }else if (temp.next.no == heroNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            System.out.printf("该编号%d已经存在,不可以插入\n",heroNode.no);
        }else{
            heroNode.next = temp.next;
            temp.next = heroNode;
        }

    }

    //打印链表

    public void printList(){

        HeroNode temp = head.next;

        while (true){
            if (temp == null){
                break;
            }
            System.out.println(temp);
            temp = temp.next;
        }
    }


    //修改节点信息
    public void update(HeroNode newHeroNode){

        //先判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //找到需要修改的节点,根据编号

        HeroNode temp = head.next;
        boolean flag = false;
        while (true){

            if (temp == null){
                break;
            }
            if (temp.no == newHeroNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag){
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
        }else{
            System.out.printf("编号为 %d 的节点没有找到\n",newHeroNode.no);
        }

    }

    //删除节点
    //我们需要找到要删除节点的前一个节点,然后删除节点
    public void del(int no){

        //判断链表是否为空
        if (head.next == null){
            System.out.printf("链表为空\n");
            return;
        }

        HeroNode temp = head;

        boolean flag = false;//标志是否找到要删除的节点
        while (true){

            if (temp.next == null){//已经到节点最后
                break;
            }
            if (temp.next.no == no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag){
            temp.next = temp.next.next;
            System.out.printf("删除 %d 节点\n",no);
        }else {
            System.out.printf("删除失败\n");
        }
    }


}





//定义一个HeroNode,每个HeroNode对象就是一个节点
class HeroNode{

    public int no;
    public String name;
    public String nickName;
    public HeroNode next;//指向下一个节点

    //构造器
    public HeroNode(int no,String name,String nickName){
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }


}

发布了34 篇原创文章 · 获赞 15 · 访问量 3220

猜你喜欢

转载自blog.csdn.net/weixin_43404016/article/details/105177427