Java〖链表〗各种单链表的面试题,你真的做得出来吗

实现功能

  • 链表无序加入数据
  • 打印所有节点信息
  • 有序插入节点
  • 修改节点数据
  • 删除节点
  • 获取链表有效节点个数
  • 获取倒数第K个节点(思路:定义两个指针变量一开始指向头节点,让第一个first先走k-1步,然后第二个second跟第一个一起走,当第一个走到头后,输出第二个就是倒数第K个元素)
  • 用栈来反转链表
  • 使用头插法反转链表
  • 将两个有序的链表合并(非递归)
  • 递归合并链表

可以看看注释,面试的题与链表基本实现都有

package DataStructure.LinkListDemo;


import java.util.Stack;

//定义node
class Node{
    public int no;
    public String name;
    public Node next; //存放指向下一个节点的数据

    public Node(int no, String name) {
        this.no = no;
        this.name = name;
    }



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

//实现链表功能
class LinkedListDemo{
    private Node head=new Node(-1,"");//初始化头节点

    /**
     * 链表无序加入数据
     * @param node
     */
    public   void add(Node node){
        Node temp=head; //由于不能移动head,所以用temp代替
        while(true){
            if(temp.next==null){ //当找到下一个节点元素为空是,就可以把新的数据加入到这里
                break;
            }
            temp=temp.next; //当找不到时,一直向后找
        }
        temp.next=node;   //这里加入新节点
    }

    /**
     * 打印所有节点信息
     */
    public void prtList(){
        if(head.next==null) System.out.println("链表为空");
        Node temp=head.next; //由于不能移动head,所以用temp代替
        while(true){
            if(temp==null){ //判断链表谁否到最后
                break;
            }
            System.out.println(temp);//输出节点信息
            temp=temp.next;//节点后移
        }
    }

    /**
     *有序插入节点
     */
    public void addOrder(Node node){
        Node temp=head;
        boolean flag=false; //判断是否重复添加
        while (true){  //查找该插入的节点位置
            if(temp.next==null){ //在链表最后
              break;
            }
            if(node.no<temp.next.no){  //这里需要找到temp的下一个位置与插入的node比较,比temp的下一个元素小,那就可以插入到temp后面
                break; //位置已经找到
            }else if(temp.next.no==node.no){
                flag=true;
                break; //不能添加重复的元素
            }
            temp=temp.next; //向后移
        }
        if(flag) System.out.println("不能添加重复编号的节点: "+node);
        else {
            node.next=temp.next;
            temp.next=node;
        }
    }

    /**
     * 修改节点数据
     * @param node
     */
    public void updateNode(Node node){
        if(head.next==null) System.out.println("链表为空,不能修改");
        Node temp=head.next;
        boolean flag=false;//表示是否找到修改的节点
        while (true){
            if(temp==null) break; //表示找到最后还是没有找到
            if(temp.no==node.no){
                flag=true;//表示找到了
                break;
            }
            temp=temp.next;//接着向后查找
        }
        if(flag) {
            temp.name=node.name;
        }else{
            System.out.println("未发现存在的节点 :"+node);
        }
    }

    /**
     * 删除节点
     * @param node
     */
    public void deleteNode(Node node){
        if(head.next==null) System.out.println("链表为空,不能删除");
        Node temp=head; //由于不能改变head的值,使用临时变量
        boolean flag=false;//表示未能找到删除节点
        while(true){
            if(temp.next==null){
                break; //表示未能找到当前删除的节点
            }
            if(temp.next.no==node.no){  //表示找到要删除的节点
                flag=true;
                break;
            }
            temp=temp.next;//找不到就向后找
        }
        if(flag){
            temp.next=temp.next.next;
        }else{
            System.out.println("未能找到删除的节点: "+node);
        }
    }

    /**
     * 获取链表有效节点个数
     * @return
     */
    public int getAllNodeNumber(){
        int num=0;
        if(head.next==null) return 0;
        Node temp=head.next;
        while (true){
            if(temp==null){
                break;
            }
            num++;
            temp=temp.next;
        }
        return num;
    }

    /**
     * 获取倒数第K个节点(思路:定义两个指针变量一开始指向头节点,让第一个first先走k-1步,然后第二个second跟第一个一起走,当第一个走到头后,输出第二个就是倒数第K个元素)
     */
    public void getLastK(int k){
        if(head.next==null) System.out.println("链表为空");
        Node first=head;
        Node second=head;
        for (int i = 0; i < k-1; i++) {
            if(first.next==null) return;
            first=first.next;
        }
        while(first.next!=null){
            first=first.next;
            second=second.next;
        }
        System.out.println(second);
    }

    /**
     * 用栈来反转链表
     */
    public void InverseList(){
        if(head.next==null) {
            System.out.println("链表为空,不能反转");
            return;
        }
        Node temp=head; //使用temp来遍历list
        Node newTemp=head; //使用newTemp来串新链表
        Stack<Node> stack=new Stack<>(); //用栈来保存链表所有数据
        while(temp.next!=null){ //循环加入栈中
            stack.push(temp.next);
            temp=temp.next;
        }
        while(!stack.empty()){ // 当栈不为空时,一直弹出,加到新节点后(改变原先顺序)
            newTemp.next=stack.pop();
            newTemp=newTemp.next;
        }
//        while (stack.size()>0){ //不改变原先顺序,直接打印出来
//            System.out.println(stack.pop());
//        }
        newTemp.next=null; //如果不设置最后一个节点的next域,那将会变成环形链表
    }

    /**
     * 使用头插法反转链表
     */
    public void reverse() {
        if (head.next == null || head.next.next == null)
            return ;
        Node cur=head.next;
        Node next=null;
        Node reserve=new Node(-1,"");
        while(cur!=null){
            next=cur.next;
            cur.next=reserve.next;
            reserve.next=cur;
            cur=next;
        }
        head.next=reserve.next;
    }

    /**
     * 将两个有序的链表合并
     * @param list1
     * @param list2
     * @return
     */
    public Node mergeList(Node list1,Node list2){
        if(list1==null) return list2; //如果一条链表为空,那就返回另一条链表
        if(list2==null) return list1;
        Node newNode=new Node(-1,""); //定义一个新链表头
        Node temp=newNode; //头不能变,所以定义临时变量
        while((list1!=null)&&(list2!=null)){ //当只要有一个变量的值为空就跳出循环
            if(list1.no>=list2.no){ //当list1.no>=list2.no
                temp.next=list2; //我们把小的连到头的后面,下同
                list2=list2.next;
            }
            else {
                temp.next=list1;
                list1=list1.next;
            }
            temp=temp.next; //临时变量向后移
        }
//        if(list1==null){
//            temp.next=list2;
//        }
//        else if (list2==null){
//            temp.next=list1;
//        }
        temp.next=list1==null?list2:list1; //当某一个链表的值为空时,就将另一条链表连入新表
        return newNode.next; //返回新链表的第一个值
    }

    /**
     * 递归合并链表
     * @param list1
     * @param list2
     * @return
     */
    public Node mergeListDigui(Node list1,Node list2){
        if(list1==null) return list2;
        if(list2==null) return list1;
        if(list1.no<list2.no){
            list1.next= mergeListDigui(list1.next,list2);
            return list1;
        }else {
            list2.next = mergeListDigui(list1, list2.next);
            return list2;
        }
    }


}

//测试方法
public class LinkListDemo {

    public static void main(String[] args) {
        Node node=new Node(1,"kaikai");
        Node node1=new Node(2,"kaikai");
        Node node2=new Node(4,"kaikai");
        LinkedListDemo list=new LinkedListDemo();
//        list.addOrder(node);
//        list.addOrder(node1);
//        list.addOrder(node2);
//        list.prtList(); //打印链表

        Node node3=new Node(2,"kaikai1");
        Node node4=new Node(3,"kaikai");
        Node node5=new Node(8,"kaikai");

        node.next=node1;
        node1.next=node2;

        node3.next=node4;
        node4.next=node5;
		
		//合并链表
        Node node6 = list.mergeListDigui(node, node4);
        while(node6!=null){
            System.out.println(node6);
            node6=node6.next;
        }


//        final int allNodeNumber = list.getAllNodeNumber();
//        System.out.println("链表的有效个数为: "+allNodeNumber);
//
//        System.out.println("链表反转后为: ");
//        list.reverse();
//        list.prtList();
//
//        System.out.println("得到链表倒数第K的节点为: ");
//        list.getLastK(3);

        
//
//        System.out.println("修改数据后为:");
//        Node node5=new Node(5,"kaikai55555");
//        list.updateNode(node5);
//        list.prtList();
//
//        System.out.println("删除数据后为:");
//        Node node6=new Node(5,"kaikai55555");
//        list.deleteNode(node6);
//        list.prtList();
    }
}

大佬们看着点喷 orz 给跪了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值