单链表练习题

单链表练习(方便起见,使用下面这个链表)

注释部分就是练习题所在位置


public class SingleLinkedListDemo {
    public static void main(String[] args) {
        SingleLinkedList s1 = new SingleLinkedList();
        Node n1 = new Node(1,"xiao");
        Node n2 = new Node(2,"biao");
        Node n3 = new Node(3,"diao");

        s1.addByOrder(n1);
        s1.addByOrder(n3);
        s1.addByOrder(n2);
        System.out.println("添加");
        s1.list();

        // 测试逆序打印
        System.out.println("逆序打印");
        reversePrint(s1.getNode());
        System.out.println("逆序打印后原来链表的数据");
        s1.list();


        System.out.println("修改");
        Node n4 = new Node(3,"Xdiao");
        s1.updata(n4);
        s1.list();

        System.out.println("删除");
        s1.del(3);
        s1.list();

        // 求单链表中有效节点的个数
        System.out.println(getLength(s1.getNode()));

        // 测试一下是否得到了倒数第k个节点
        Node res = findeLastIndexNode(s1.getNode(),1);

        // 测试一下单链表的反转
        System.out.println("反转单链表");
        reversetList(s1.getNode());
        s1.list();
    }
/*    // 1.获取单链表的节点个数(如果是带头节点的链表,不需要统计头节点)
    public static int getLength(Node head){
        if (head.next == null){
            return 0;
        }
        int length = 0;
        // 辅助节点
        Node temp = head.next;
        while (temp != null){
            length++;
            temp = temp.next;// 遍历
        }
        return length;
    }
    // 2.查找单链表中倒数第k个节点
    // 思路:
    // 1. 编写一个方法,用来接受head节点,同时接受一个index
    // 2. index 表示是倒数第index个节点
    // 3. 先把链表从头到位遍历,得到链表的总的长度
    // 4. 得到size后,我们从链表的第一个开始遍历(size - index)个,就可以得到
    // 5. 如果找到就返回节点,否则返回空
    public static Node findeLastIndexNode(Node head, int index){
        // 判断为空,返回null
        if (head.next == null){
            return null;
        }
        // 第一个遍历得到链表的长度(节点个数)
        int size = getLength(head);
        // 第二遍遍历,size-index 位置, 就是我们倒数的第K个节点
        // 先做一个index校验
        if (index <= 0 || index > size){
            return null;
        }
        // 定义一个辅助变量
        Node cur = head.next;
        for (int i = 0; i < size - index; i++){
            cur = cur.next;
        }
        return cur;
    }

    // 3.将单链表进行反转
    public static void reversetList(Node head){
        // 如果当前列表为空,或者只有一个节点,无需反转,直接返回
        if (head.next == null || head.next.next == null){
            return;
        }
        // 定义一个而辅助的指针,帮助我们遍历原来的链表
        Node cur = head.next;
        // 指向当前节点的下一个
        Node next = null;
        Node reverseHead = new Node(0,"");
        // 遍历原来的链表
        while (cur != null){
            next = cur.next; // 暂时保存当前节点的下一个
            cur.next = reverseHead.next; // 将cur的下一个节点指向新的链表的头补
            reverseHead.next = cur; // 将节点连接上新的链表上
            cur = next; // 让cur后移
        }
        // 将head.next 指向 reverseHead,实现反转
        head.next = reverseHead.next;
    }
    // 4.逆序打印链表,使用栈
    public static void reversePrint(Node head){
        // 判断空链表,直接返回
        if (head.next == null){
            return;
        }
        // 创建一个栈,将各个节点压入栈
        Stack<Node> stack = new Stack<>();
        Node cur = head.next;
        // 将链表的所有节点压入栈
        while (cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        // 将栈中的元素出栈使用pop
        while (stack.size() > 0){
            System.out.println(stack.pop()); // stack的特点是先进后出
        }
*/    }
}
// 定义一个SingleLinkedList
class SingleLinkedList{
    // 先初始化一个头节点
    private Node head = new Node(0,"");
    // 获取头节点
    public Node getNode(){
        return head;
    }
    // 添加节点
    public void addByOrder(Node node){
        Node temp = head;
        boolean flag = false; // 添加的元素是否存在
        while(true){
            if (temp.next == null){
                break;
            }
            if (temp.next.no > node.no){
                break;
            } else if (temp.next.no == node.no){
                flag = true;
                break;
            }
            // 如果没找到最后
            temp = temp.next;
        }
        if (flag == false){
            node.next = temp.next;
            temp.next = node;

        }else{
            System.out.println("编号存在");
        }
    }


    // 修改链表
    public void updata(Node node){
        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.no = node.no;
            temp.name = node.name;
        }else {
            System.out.println("不存在");
        }
    }

    // 删除链表
    public void del(int no){
        Node node = head.next;
        boolean flag = false;
        while (true){
            if (node == null){
                break;
            }
            if (node.next.no == no){
                flag = true;
                break;
            }
            node = node.next;
        }
        if (flag){
            node.next = node.next.next;
        }else{
            System.out.println("编号不存在");
        }
    }
    // 显示链表
    public void list(){
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        Node temp = head.next;
        while (true){
            if (temp == null){
                break;
            }
            System.out.println(temp.toString());
            temp = temp.next;
        }
    }


}
// 定义一个Node 对象
class Node{
    public String name;
    public int no;
    // 指向下一个
    public Node next;

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

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

获取单链表的节点个数(如果是带头节点的链表,不需要统计头节点

    // 获取单链表的节点个数(如果是带头节点的链表,不需要统计头节点)
    public static int getLength(Node head){
        if (head.next == null){
            return 0;
        }
        int length = 0;
        // 辅助节点
        Node temp = head.next;
        while (temp != null){
            length++;
            temp = temp.next;// 遍历
        }
        return length;
    }

获取单链表倒数第k个元素

 // 2.查找单链表中倒数第k个节点
    // 思路:
    // 1. 编写一个方法,用来接受head节点,同时接受一个index
    // 2. index 表示是倒数第index个节点
    // 3. 先把链表从头到位遍历,得到链表的总的长度
    // 4. 得到size后,我们从链表的第一个开始遍历(size - index)个,就可以得到
    // 5. 如果找到就返回节点,否则返回空
    public static Node findeLastIndexNode(Node head, int index){
        // 判断为空,返回null
        if (head.next == null){
            return null;
        }
        // 第一个遍历得到链表的长度(节点个数)
        int size = getLength(head);
        // 第二遍遍历,size-index 位置, 就是我们倒数的第K个节点
        // 先做一个index校验
        if (index <= 0 || index > size){
            return null;
        }
        // 定义一个辅助变量
        Node cur = head.next;
        for (int i = 0; i < size - index; i++){
            cur = cur.next;
        }
        return cur;
    }

链表的反转(腾讯面试题)

思路:

  1. 先去创建定义一个节点,reverseHead = new Node()
  2. 从头到尾遍历原来的链表,每遍历一个节点,就将其取出,并放进新的链表
  3. 原来的链表的head.next = reverseHead.next
// 将单链表进行反转
    public static void reversetList(Node head){
        // 如果当前列表为空,或者只有一个节点,无需反转,直接返回
        if (head.next == null || head.next.next == null){
            return;
        }
        // 定义一个而辅助的指针,帮助我们遍历原来的链表
        Node cur = head.next;
        // 指向当前节点的下一个
        Node next = null;
        Node reverseHead = new Node(0,"");
        // 遍历原来的链表
        while (cur != null){
            next = cur.next; // 暂时保存当前节点的下一个
            cur.next = reverseHead.next; // 将cur的下一个节点指向新的链表的头补
            reverseHead.next = cur; // 将节点连接上新的链表上
            cur = next; // 让cur后移
        }
        // 将head.next 指向 reverseHead,实现反转
        head.next = reverseHead.next;
    }

###从尾到头打印链表(百度面试)

思路:

  1. 上面的题是逆序打印单链表
  2. 方式一:先将单链表进行反转操作,然后遍历打印即可,这样的问题是会破坏原来的单链表的结构,不建议
  3. 方式2:可以利用这个数据结构,将各个节点压入栈中,然后利用栈的先进后出的特点,就实现了逆序打印
// 先简单了解下什么叫做栈
import java.util.Stack;

// 演示栈Stack的基本使用
public class TeskStack {
    public static void main(String[] args) {
        Stack<String> stack = new Stack<>();
        // 入栈
        stack.add("jack");
        stack.add("tom");
        stack.add("smith");
        // 出栈
        while (stack.size() > 0){
            // pop就是Stack的将栈顶部数据取出的方法
            System.out.println(stack.pop());
        }
    }
}

// 4.逆序打印链表,使用栈
    public static void reversePrint(Node head){
        // 判断空链表,直接返回
        if (head.next == null){
            return;
        }
        // 创建一个栈,将各个节点压入栈
        Stack<Node> stack = new Stack<>();
        Node cur = head.next;
        // 将链表的所有节点压入栈
        while (cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        // 将栈中的元素出栈使用pop
        while (stack.size() > 0){
            System.out.println(stack.pop()); // stack的特点是先进后出
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值