Java实现单链表(面试题)

package SingleLinkedList;

//链表结点
public class HeroNode {
    //数据域
    public int no;
    public String name;
    public String nickname;
    //指针域
    public HeroNode next;

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

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

package SingleLinkedList;

//链表类
public class SingleLinkedList {
    //先初始化一个头结点,头结点不要动,不存放具体数据
    private HeroNode head=new HeroNode(0,"","");

    public HeroNode getHead() {
        return head;
    }

    //添加结点到单链表
    //思路,当不考虑编号顺序时,
    //找到当前链表的最后结点,插入;
    public void add(HeroNode heroNode){
        //因为头结点不能动,需要一个辅助结点遍历temp;
        HeroNode temp=head;
        //遍历链表找到最后
        while (true){
            //找到链表最后
            if (temp.next==null){
                break;
            }
            //没有找到最后,temp后移
            temp=temp.next;
        }
        //插入链表中
        temp.next=heroNode;
    }

    //第二种添加英雄方式,根据排名将英雄插入到指定位置,如果有排名,则添加失败
    public void addByOrder(HeroNode heroNode){
        //找到添加位置的前一个结点
        HeroNode temp=head;
        boolean flag=false;//编号是否已经存在
        //找位置
        while (true){
            if (temp.next==null){
                //temp已到最后
                break;
            }
            if (temp.next.no>heroNode.no){
                break;
            }else if (temp.next.no==heroNode.no){
                //编号已存在
                flag=true;
                break;
            }
            temp=temp.next;//后移
        }
        //判断flag的值
        if (flag){
            //已存在,不能添加
            System.out.printf("准备插入的英雄编号%d已存在,不能加入\n",heroNode.no);
        }else {
            //插入到temp后面
            heroNode.next=temp.next;
            temp.next=heroNode;
        }
    }

    //修改结点
    /**
     * 根据编号来找到结点进行修改
     * @param newHeroNode
     */
    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;
            // temp=newHeroNode;//相当于把temp指向了newHeroNode,没有修改链表的值
        }else {
            //没有找到
            System.out.printf("没有找到编号为 %d 的结点,不能修改\n",newHeroNode.no);
        }
    }

    //删除结点
    public void delete(int n){
        if (head.next==null){
            System.out.println("链表为空。。。");
            return;
        }
        HeroNode temp=head;//注意!
        Boolean flag=false;
        while (true){
            if (temp.next.no==n){
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if (flag){
            //删除
            temp.next=temp.next.next;
        }else {
            System.out.printf("要删除的%d结点不存在\n",n);
        }
    }
    //显示链表[遍历]
    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=temp.next;
        }

    }
}

package SingleLinkedList;

public class SingleLinkedListDemo {
    public static void main(String[] args) {
        //进行测试
        //创建结点
        HeroNode hero1=new HeroNode(1,"宋江","及时雨");
        HeroNode hero2=new HeroNode(2,"卢俊义","玉麒麟");
        HeroNode hero3=new HeroNode(3,"吴用","智多星");
        HeroNode hero4=new HeroNode(4,"林冲","豹子头");
        //创建链表
        SingleLinkedList singleLinkedList=new SingleLinkedList();
        /*System.out.println("按照添加顺序排列:");
        //加入链表
        singleLinkedList.add(hero1);
        singleLinkedList.add(hero2);
        singleLinkedList.add(hero3);
        singleLinkedList.add(hero4);*/

        //按no排序
        singleLinkedList.addByOrder(hero2);
        singleLinkedList.addByOrder(hero4);
        singleLinkedList.addByOrder(hero1);
        singleLinkedList.addByOrder(hero3);

        System.out.println("修改前...");
        singleLinkedList.list();
        /*//修改结点
        HeroNode newHero=new HeroNode(1,"舒奇","魁拔");
        singleLinkedList.update(newHero);
        */

        singleLinkedList.delete(1);
        singleLinkedList.delete(4);
        System.out.println("修改后...");
        //打印链表
        singleLinkedList.list();


    }
}

面试题!

package Interview_Questions;

import SingleLinkedList.*;

import java.util.Scanner;
import java.util.Stack;

public class SingleLinkedList_IQ extends SingleLinkedList{

    public static void main(String[] args) {
        //使用继承
        SingleLinkedList_IQ singleLinkedList_iq=new SingleLinkedList_IQ();
        //要在psvm内使用继承的方法!
        HeroNode hero1=new HeroNode(1,"1","1");
        HeroNode hero2=new HeroNode(2,"2","2");
        HeroNode hero3=new HeroNode(3,"3","3");
        HeroNode hero4=new HeroNode(4,"4","4");
        HeroNode hero5=new HeroNode(5,"5","5");
        HeroNode hero6=new HeroNode(6,"6","6");
        /*singleLinkedList_iq.addByOrder(hero1);
        singleLinkedList_iq.addByOrder(hero2);
        singleLinkedList_iq.addByOrder(hero3);
        singleLinkedList_iq.addByOrder(hero4);
        singleLinkedList_iq.addByOrder(hero5);
        singleLinkedList_iq.addByOrder(hero6);
        singleLinkedList_iq.list();*/

        //1,统计结点个数
        //实例对象可以调用类(static)方法!编译器提示有点慢而已!
       // System.out.println("结点个数为:"+singleLinkedList_iq.getLength(singleLinkedList_iq.getHead()));

        //2,倒数第k个结点
       /* Scanner scanner=new Scanner(System.in);
        System.out.println("请输入要寻找倒数第几个结点?");
        int k=scanner.nextInt();
        System.out.printf("倒数第%d个结点是:"+singleLinkedList_iq.findLastIndexNode(singleLinkedList_iq.getHead(),k),k);*/

       //3,单链表反转
       /* singleLinkedList_iq.reverse(singleLinkedList_iq.getHead());
        System.out.println("链表反转后为:");
        singleLinkedList_iq.list();*/

       //4,逆序打印单链表
       // singleLinkedList_iq.reversePrint(singleLinkedList_iq.getHead());

        //5,合并两个有序链表
        SingleLinkedList_IQ linkedList1=new SingleLinkedList_IQ();
        linkedList1.addByOrder(hero1);
        linkedList1.addByOrder(hero3);
        linkedList1.addByOrder(hero5);
        SingleLinkedList_IQ linkedList2=new SingleLinkedList_IQ();
        linkedList2.addByOrder(hero2);
        linkedList2.addByOrder(hero4);
        linkedList2.addByOrder(hero6);

        /*//合并链表,返回的是不带头结点的链表!
        HeroNode link3 = merge1(linkedList1.getHead().next, linkedList2.getHead().next);
        while (link3!=null){
            System.out.println(link3);
            link3=link3.next;
        }*/

      /* merge2(linkedList1.getHead(), linkedList2.getHead());
        linkedList1.list();*/

        merge3(linkedList1.getHead(), linkedList2.getHead());
        linkedList1.list();
    }


    //1,统计有效结点个数
    public static int getLength(HeroNode head){
        if (head.next==null){
            return 0;//
        }
        int length=0;
        HeroNode temp=head.next;
        while(temp!=null){
           length++;
           temp=temp.next;
        }
        return length;
    }

    //2,查找单链表中的倒数第K个结点【新浪面试题】
    /*思路:
        1,首先遍历链表得到总的结点个数n
        2,第二次遍历(n-k)个结点*/
    public static HeroNode findLastIndexNode(HeroNode head,int k){
        if (head.next==null){
            System.out.println("链表为空!");
            return null;
        }
        int size = getLength(head);
        if (k<=0||k>size){
            System.out.println("输入的K值有误!");
            return null;
        }
        //定义赋值变量
        HeroNode cur = head.next;
        for (int i=1;i<=size-k;i++){
            cur=cur.next;
        }
        return cur;
    }

    //3,链表反转(腾讯面试题)
    /*思路:
    * 头插法*/
    public static void reverse(HeroNode head){
        //如果是空链表或者节点个数为1,则不用反转
        if (head.next==null||head.next.next==null){
            System.out.println("链表为空或者结点个数为1不需反转。");
            return;
        }
        HeroNode cur=head.next;
        head.next=null;//原链表置空!
        HeroNode next;//指向cur的下一个结点
        while(cur!=null){
            next=cur.next;//先保留cur的下一个结点,以防止断链!
            cur.next=head.next;
            head.next=cur;
            cur=next;
        }
    }

    //4,逆序打印链表(百度面试题)
    /*
    * 方法1:链表反转,再打印输出
    * 方法2:使用栈*/
    public static void reversePrint(HeroNode head){
        if (head.next==null){
            System.out.println("链表为空...");
            return;
        }
        HeroNode cur=head.next;
        Stack<HeroNode> stack = new Stack<>();
        //链表入栈
        while (cur!=null){
            stack.push(cur);
            cur=cur.next;
        }
        //链表出栈,打印
        while (stack.size()>0){
            System.out.println(stack.pop());
        }
    }

    //5.1,合并两个有序(从小到大)列表,【合并为从小到大】
    /*思路:
    * 1,递归:相当于每次比较两个结点,返回较小的结点!(注意无头结点)
    */
    public static HeroNode merge1(HeroNode head1,HeroNode head2){
        //结点都为null,返回null
        if (head1==null&& head2==null)
            return null;
        if (head1==null)
            return head2;
        if (head2==null)
            return head1;
        HeroNode newhead=null;
        if (head1.no>head2.no){
            //每次把小的结点返回
           newhead=head2;
           //继续比较head2的下一个结点
            newhead.next=merge1(head1,head2.next);
        }else {
            newhead=head1;
            newhead.next=merge1(head1.next,head2);
        }
        return newhead;
    }

    //5.2,合并两个有序(从小到大)列表,【合并为从小到大!!!】
    //使用循环
    public static HeroNode merge2(HeroNode head1,HeroNode head2){
        HeroNode cur1=head1.next;
        HeroNode cur2=head2.next;
        HeroNode temp=null;//用来保存较小的结点
        //合并到头结点head1后
        head1.next=null;
        HeroNode next=head1;
        while (cur1!=null&&cur2!=null){
            if (cur1.no>cur2.no){
                temp=cur2;
                cur2=cur2.next;//后移一位
            }else {
                temp=cur1;
                cur1=cur1.next;
            }
            next.next=temp;
            next=temp;
        }
        //当cur和cur2分别未结束
        while(cur1!=null){
            temp=cur1;
            cur1=cur1.next;
            next.next=temp;
            next=temp;
        }
        while(cur2!=null){
            temp=cur2;
            cur2=cur2.next;
            next.next=temp;
            next=temp;
        }
        return head1;
    }
    //5.3,合并两个有序(从小到大)列表,【合并为从小到小!!!】
    //使用循环
    public static HeroNode merge3(HeroNode head1,HeroNode head2){
        HeroNode cur1=head1.next;
        HeroNode cur2=head2.next;
        HeroNode temp=null;//用来保存较小的结点
        //合并到头结点head1后
        head1.next=null;
        while (cur1!=null&&cur2!=null){
            if (cur1.no>cur2.no){
                temp=cur2;
                cur2=cur2.next;//后移一位
            }else {
                temp=cur1;
                cur1=cur1.next;
            }
            //找到较小的结点后,插入到新的链表(头插法,顺序变为从大到小)
            temp.next=head1.next;
            head1.next=temp;
        }
        //当cur和cur2分别未结束
        while(cur1!=null){
            temp=cur1;
            cur1=cur1.next;
            //头插法插入->从大到小
            temp.next=head1.next;
            head1.next=temp;
        }
        while(cur2!=null){
            temp=cur2;
            cur2=cur2.next;
            //头插法插入->从大到小
            temp.next=head1.next;
            head1.next=temp;
        }
        return head1;
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值