三、单链表

一、单链表介绍和内存布局

      链表是有序的列表,但是它在内存中的存储不是有序的,单链表中每个节点包含data域和next域,next指向下一个节点。链表分带头节点的链表和没有头节点的链表,根据实际的需求来确定。

二、单链表创建和遍历的分析实现

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, "林冲", "豹子头");

        SingleLinkedList singleLinkedList = new SingleLinkedList();
        singleLinkedList.add(heroNode1);
        singleLinkedList.add(heroNode2);
        singleLinkedList.add(heroNode3);
        singleLinkedList.add(heroNode4);

        singleLinkedList.list();
    }
}

class SingleLinkedList{   //创建单链表

    private HeroNode head = new HeroNode(0,"","");    //创建头节点

      public void add(HeroNode heroNode){      //添加函数
        HeroNode temp = head;
        while(true){                           //while循环寻找末节点
            if((temp.next) == null)
                break;
            temp = temp.next;
        }
        temp.next = heroNode;                  //找到末节点后,将之前的末节点的next指向待添加节点
    }


      public void list(){                       //循环输出链表数据
            if(head.next == null){              //确认不为空
                System.out.println("链表为空");
                return;
            }

            HeroNode temp = head.next;           //辅助节点,来实现遍历
            while(true){                        //依次输出各个节点信息
                if(temp == null){
                    break;
                }
                System.out.println(temp);
                temp = temp.next;
            }
      }
}


class HeroNode{  //创建一个节点,定义Data域和Next域
    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  +
                '}';
    }
}

三、单链表按顺序插入节点

增加下面函数实现顺序添加:

  public void addByorder(HeroNode heroNode){
        HeroNode temp = head;                   //创建辅助节点
        boolean flag = false;
        while(true){
            if(temp.next == null){
                break;
            }
            if(temp.next.no > heroNode.no){                     //找到temp位置,在待添加数据的前面一个位置
                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
            temp.next = heroNode;                           //将待添加的节点传给temp的next
        }

    }

测试:

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, "林冲", "豹子头");

        SingleLinkedList singleLinkedList = new SingleLinkedList();
        singleLinkedList.addByorder(heroNode1);
        singleLinkedList.addByorder(heroNode4);
        singleLinkedList.addByorder(heroNode3);
        singleLinkedList.addByorder(heroNode2);

        singleLinkedList.list();
    }
}

结果:

HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='玉麒麟}
HeroNode{no=3, name='吴用', nickname='智多星}
HeroNode{no=4, name='林冲', nickname='豹子头}

结论:实现了顺序插入,虽然添加的顺序不同,但是在链表中按照顺序插入。

四、单链表节点的修改

增加下面函数实现节点修改:

 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的节点,不能修改");
        }

    }

测试:

ublic 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, "林冲", "豹子头");

        SingleLinkedList singleLinkedList = new SingleLinkedList();

        singleLinkedList.addByorder(heroNode1);
        singleLinkedList.addByorder(heroNode3);
        singleLinkedList.addByorder(heroNode4);
        singleLinkedList.addByorder(heroNode2);
        singleLinkedList.list();
        HeroNode newHeroNode = new HeroNode(2, "小卢","玉麒麟~");
        singleLinkedList.update(newHeroNode);
        System.out.println("修改后的链表情况");
        singleLinkedList.list();
    }
}

结果:

HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='玉麒麟}
HeroNode{no=3, name='吴用', nickname='智多星}
HeroNode{no=4, name='林冲', nickname='豹子头}
修改后的链表情况
HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='小卢', nickname='玉麒麟~}
HeroNode{no=3, name='吴用', nickname='智多星}
HeroNode{no=4, name='林冲', nickname='豹子头}

**结论:**实现了节点信息的修改。

五、单链表节点的删除

增加下面函数实现节点删除:

    public void del(int no){
        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;             //直接跳过待删除的节点,将该节点的前一个节点的next指向该节点的next节点
        }else{
            System.out.printf("要删除的%d节点不存在\n",no);
        }
    }

测试:

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, "林冲", "豹子头");

        SingleLinkedList singleLinkedList = new SingleLinkedList();

        singleLinkedList.addByorder(heroNode1);
        singleLinkedList.addByorder(heroNode3);
        singleLinkedList.addByorder(heroNode4);
        singleLinkedList.addByorder(heroNode2);
        singleLinkedList.list();
        singleLinkedList.del(4);
          System.out.println("删除后的链表情况");
          singleLinkedList.list();
    }
}

结果:

HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='玉麒麟}
HeroNode{no=3, name='吴用', nickname='智多星}
HeroNode{no=4, name='林冲', nickname='豹子头}
删除后的链表情况
HeroNode{no=1, name='宋江', nickname='及时雨}
HeroNode{no=2, name='卢俊义', nickname='玉麒麟}
HeroNode{no=3, name='吴用', nickname='智多星}

结论:实现了节点的删除功能。

六、单链表新浪面试题

A.输出单链表中一共有多少节点

public HeroNode getHead(){
        return head;
    }

    public  int getLength(HeroNode head){
        if(head.next == null){
            System.out.println("空链表");
            return  0;
        }
        HeroNode cur = head.next;
        int length =0;
        while(cur != null){
            length++;
            cur = cur.next;
        }
        return length;
    }

B.查找单链表中的倒数第K个结点

 public  HeroNode findLastIndexNode(HeroNode head,int index){
        if(head.next == null){
            return null;
        }

        int size = getLength(head);
        if(index <= 0 || index >= size){
            return null;
        }

        HeroNode cur = head.next;
        for (int i = 0; i < size-index; i++) {
            cur = cur.next;
        }
            return cur;
    }

七、单链表腾讯面试题

单链表的反转

 public void reverseList(HeroNode head){
        if(head.next == null  ||  head.next.next == null){   //排除空链表或者只有一个数据的链表的情况
            return;
        }
        HeroNode cur = head.next;                           //
        HeroNode next = null;     //指向当前节点的下一个节点
        HeroNode reverseHead = new HeroNode(0,"","");    //新建一个节点头,用来连接节点
        while(cur != null){
            next = cur.next;
            cur.next = reverseHead.next;
            reverseHead.next = cur;
            cur = next;         //cur后移
        }
        head.next = reverseHead.next;     //相当于借助了辅助链表reverseHead,遍历结束后将head重新指向反转后的链表节点
    }

八、单链表百度面试题

从尾到头打印单链表(要求实现方式:利用Stack栈)

 public void reversePrint(HeroNode head){
        if(head.next ==null){
            return;
        }
        Stack<HeroNode> stack = new Stack<HeroNode>();
        HeroNode cur = head.next;
        while(cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        while(stack.size() > 0){
            System.out.println(stack.pop());   //先进后出
        }
    }

附录代码:

import java.util.Stack;

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, "林冲", "豹子头");

        SingleLinkedList singleLinkedList = new SingleLinkedList();

        singleLinkedList.addByorder(heroNode1);
        singleLinkedList.addByorder(heroNode3);
        singleLinkedList.addByorder(heroNode4);
        singleLinkedList.addByorder(heroNode2);
        singleLinkedList.list();
       singleLinkedList.reverseList(singleLinkedList.getHead());
        System.out.println("反转后链表如下:");
        singleLinkedList.list();
        System.out.println("反向打印:");
        singleLinkedList.reversePrint(singleLinkedList.getHead());
    }
}

class SingleLinkedList{

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

    public void reversePrint(HeroNode head){
        if(head.next ==null){
            return;
        }
        Stack<HeroNode> stack = new Stack<HeroNode>();
        HeroNode cur = head.next;
        while(cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        while(stack.size() > 0){
            System.out.println(stack.pop());   //先进后出
        }
    }

    public void reverseList(HeroNode head){
        if(head.next == null  ||  head.next.next == null){   //排除空链表或者只有一个数据的链表的情况
            return;
        }
        HeroNode cur = head.next;                           //
        HeroNode next = null;     //指向当前节点的下一个节点
        HeroNode reverseHead = new HeroNode(0,"","");    //新建一个节点头,用来连接节点
        while(cur != null){
            next = cur.next;
            cur.next = reverseHead.next;
            reverseHead.next = cur;
            cur = next;         //cur后移
        }
        head.next = reverseHead.next;     //相当于借助了辅助链表reverseHead,遍历结束后将head重新指向反转后的链表节点
    }

    public  HeroNode findLastIndexNode(HeroNode head,int index){
        if(head.next == null){
            return null;
        }

        int size = getLength(head);
        if(index <= 0 || index >= size){
            return null;
        }

        HeroNode cur = head.next;
        for (int i = 0; i < size-index; i++) {
            cur = cur.next;
        }
            return cur;
    }

    public HeroNode getHead(){
        return head;
    }

    public int getLength(HeroNode head){
        if(head.next == null){
            System.out.println("空链表");
            return  0;
        }
        HeroNode cur = head.next;
        int length =0;
        while(cur != null){
            length++;
            cur = cur.next;
        }
        return length;
    }


    public void add(HeroNode heroNode){
        HeroNode temp = head;
        while(true){
            if((temp.next) == null)
                break;
            temp = temp.next;
        }
        temp.next = heroNode;
    }

    public void addByorder(HeroNode heroNode){
        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 del(int no){
          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;
          }else{
              System.out.printf("要删除的%d节点不存在\n",no);
          }
    }



    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的节点,不能修改");
          }

    }


      public void list(){
            if(head.next == null){
                System.out.println("链表为空");
                return;
            }

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


}


class HeroNode{  //创建一个节点,定义Data域和Next域
    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  +
                '}';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值