单向链表实现(java代码)

单向链表实现以及常见的面试题收录(java代码)

在这里插入图片描述
在这里插入图片描述

Java代码
package com.bingym.linkedlist;

import java.util.Stack;

public class SingleLinkedListByOrder {
    //实现单向链表功能:链表的添加add(可以按照编号index进行插入),链表内容的打印
    //内部需要包含一个节点类:内部类/外部类都可以
    //定义单向链表的属性
    private Node head =new Node(0,"");//该头结点不包含任何信息,只是作为单向链表的头结点标志,默认head的next域没有赋值,初始化为null

    public Node getHead() {
        return head;
    }

    //定义节点的添加方法:根据节点的index顺序进行节点的添加
    public void addByOrder(Node node) {
        //定义一个辅助指针变量:表示头结点head,因为头结点不能进行改变
        Node temp = head;
        //定义一个flag标志:表示新节点的编号在已存在的链表中是否存在
        boolean flag = false;
        //遍历链表
        while (true) {
            if (temp.next == null) {//表示当前链表为空
                break;
            }
            if (temp.next.index > node.index) {//说明当前节点的下一个节点的index值大于新添加节点的index值,则直接在此处进行新节点的添加操作
                break;
            }else if (temp.next.index == node.index) {//说明当前节点的下一个节点的index值等于新添加节点的index值,则说明该index的节点已经存在,将flag置为true
                flag = true;
                break;
            }
            //此时上面条件都不满足,说明此时节点的index值小于新添加节点的index值,将temp节点向后平移
            temp = temp.next;
        }
        //while循环以后,即找到了新节点添加的位置
        if (flag) {
            System.out.printf("您好,您想添加的index = %d的节点链表中已经存在,请添加其他节点\n",node.index);
        }else {
            //temp即为next域即为新添加节点的位置
            //将新节点的next域指向temp节点的next域
            node.next = temp.next;
            //再将temp节点的next域指向新节点
            temp.next = node;
        }
    }

    //定义链表数据的显示操作
    public void list() {
        //首先在遍历之前判断链表是否为空
        //抽取一个方法isEmpty()
        if (isEmpty()) {
            System.out.println("当前链表为空,没有节点元素可以进行显示");
            return;
        }
        //否则说明链表存在节点数据
        Node temp = head.next;
        while (true) {
            //判断当前节点是否到达链表的最后一个节点
            if (temp == null) {
                System.out.println();
                break;
            }
            System.out.print(temp + "-->");
            //将节点向后平移
            temp = temp.next;
        }
    }

    //判断链表是否为空
    private boolean isEmpty() {
        return head.next == null;
    }

    //根据传入节点的信息进行节点修改
    public void update(Node newNode) {
        //首先判断链表是否为空
        if (isEmpty()) {
            System.out.println("当前链表为空,无法找到修改节点信息");
            return;
        }
        //若节点不为空,则进行节点的搜索工作
        //定义查找标记flag
        boolean flag = false;
        Node temp = head.next;
        while (true) {
            if (temp == null) {
                break;
            }
            if (temp.index == newNode.index) {
                flag = true;
                break;
            }
            temp = temp.next;//继续进行查找
        }
        //while循环结束
        if (flag) {
            temp.data = newNode.data;
        }else {
            //没有找到
            System.out.printf("您好,您所要更新的index = %d的节点信息在链表中未找到\n",newNode.index);
        }
    }

    //根据节点的index值删除对应的节点
    public void remove(int index) {
        if (isEmpty()) {
            System.out.println("当前链表为空,无法进行删除操作");
            return;
        }
        boolean flag = false;
        Node temp = head;
        while (true) {
            if (temp.next == null) {
                break;
            }
            if (temp.next.index == index) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        //此时若找到,temp的下一个节点即为要删除的节点
        if (flag) {
            temp.next = temp.next.next;
        }else {
            System.out.printf("您好,您所要删除的index = %d的节点信息在链表中未找到\n",index);
        }
    }

    //根据节点的index获取指定的节点信息
    public void find(int index) {
        if (isEmpty()) {
            System.out.println("当前链表为空");
        }
        boolean flag = false;
        Node temp = head.next;
        while (true) {
            if (temp == null) {
                break;
            }
            if (temp.index == index) {
                flag = true;
                break;
            }
            temp = temp.next;
        }

        if (flag) {
            System.out.println("您查找的的编号为" + index + "的节点信息为:" + temp);
        }else {
            System.out.println("您查找的编号为" + index + "节点信息不存在");
        }
    }
}


class Node {
    //定义节点的属性
    //data域,next域,编号index
    public int index;
    public String data;
    public Node next;

    public Node(int index, String data) {
        this.index = index;
        this.data = data;
    }

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

单向链表常见的面试题
面试题1:获取单向链表有效节点的个数
//面试题1:查找链表有效节点的个数:不包括head
    public int getSize() {
        if (isEmpty()) {
            return 0;
        }
        Node temp = head;
        int size = 0;
        while (true) {
            if (temp.next == null) {//到达链表的最后一个节点
                break;
            }
            size++;
            temp = temp.next;
        }
        return size;
    }
面试题2:查找链表中倒数第K个节点的信息
//面试题2:获取链表倒数第K个节点的信息
    public  Node findLastIndex(int k) {
        //首先需要通过getSize()方法获取当前链表的有效节点的长度
        //查找倒数第K个:即获取正序的第size - K:即有5个节点,倒数第3个,即正序的第2个
        //找不到返回null
        if (isEmpty()) {
            return null;
        }
        int size = getSize();
        Node temp = head.next;
        if (k <= 0 || k > size) {
            return null;
        }
        for (int i = 0; i < size - k; i++) {
            temp = temp.next;
        }
        return temp;
    }
面试题3:实现单向链表的反转(腾讯)

在这里插入图片描述

//面试题3:实现单链表的反转操作
    public void reverseLinkList() {
        if (head.next == null || head.next.next == null) {
            //此时链表为空或者只要一个节点元素,反转以后链表不发生任何变化
            return;
        }
        //定义一个新的头结点reverseHead,一个辅助指针变量指向当前节点,一个辅助指针变量指向当前节点的下一个节点
        Node cur = head.next;
        Node next = null;
        Node reverseHead = new Node(0,"");
        //遍历原链表
        while (cur != null) {//说明当前链表没有遍历结束
            next = cur.next;
            cur.next = reverseHead.next;//将当前节点的next指向新头结点的next域[第一次cur.next = null]
            reverseHead.next = cur;//将新头结点next指向新头结点
            cur = next;//将cur节点进行向后平移
        }
        //遍历结束,新头结点指向的链表为原链表的反转链表
        //此时将原头结点的next指向新头结点的next即最终完成原链表的反转
        head.next = reverseHead.next;
    }
面试题4:将单向链表实现逆向打印输出

在这里插入图片描述

//面试题4:实现单链表的逆向打印
    //方式1:先将链表进行反转操作,在进行遍历打印
    //方式2:利用栈的特性,先进后出,遍历单链表,将其依次入栈,然后再将栈中的数据进行出栈操作,不会破坏原有链表的结构
    public void reversePrint() {
        if (isEmpty()) {
            System.out.println("{}");
            return;
        }
        //创建一个节点的空栈
        Stack<Node> stack = new Stack<>();
        Node temp = head.next;
        while (temp != null) {
            stack.push(temp);
            temp = temp.next;
        }
        //进行出栈打印工作
        while (stack.size() > 0) {
            System.out.print(stack.pop() + "-->");
        }
    }
面试题5:将两个有序的单向链表合并成一个依旧有序的单向链表

在这里插入图片描述

面试题5:将两个有序的单向链表进行合并,合并以后的链表依旧保持有序性
    //    //需要创建一个新的单向链表,用来存储合并以后的单链表数据
    //    //依次遍历两个单链表,将其中的节点按照index顺序进行添加
    public static SingleLinkedListByOrder mergeLinkedList(Node head1,Node head2) {
        //首先判断两个链表是否为空
        //如果两个链表都为空,直接返回null
        //如果两个链表其中一个为空,则合并以后的链表即为两个非空的链表
        if (head1.next == null && head2.next == null) {
            return null;
        }
        Node temp1 = head1.next;
        Node temp2 = head2.next;
        Stack<Node> stack = new Stack<>();
        SingleLinkedListByOrder linkedList = new SingleLinkedListByOrder();
        //依次遍历
        while (temp1 != null) {
            stack.push(temp1);
            temp1 = temp1.next;
        }
        while (temp2 != null) {
            stack.push(temp2);
            temp2 = temp2.next;
        }
        //将栈中的所有节点按照index顺序进行添加到新的节点中
        while (stack.size() > 0) {
            linkedList.addByOrder(stack.pop());
        }
        return linkedList;
    }
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值