黑马java期末题目

第一题(15)

需求

  • 某小型商城系统的订单信息在素材下的orders.xml文件中,现在要求把xml中的订单信息,封装成一个一个的订单对象,将订单对象保存到ArrayList集合中。

具体功能点要求

1、定义订单类Order,创 建ArrayList集合,用于存储订单Order对象 (解析XML 4分,封装成对象2分)

2、请使用Stream流找出今天之前的订单,并遍历输出。(3分)

3、请使用Stream流找出集合中价格最贵的订流单,把这个订单的详细信息打印出来。(3分)

4、请使用Stream流遍历集合中的每个订单,要求按照价格降序输出每个订单的详情。(3分)

素材orders.xml,放在src目录下即可

<?xml version="1.0" encoding="UTF-8" ?>
<orders>
    <order id="1">
        <name>Java入门</name>
        <time>2023-12-22 09:23:11</time>
        <double>45.4</double>
    </order>

    <order id="2">
        <name>黑枸杞</name>
        <time>2023-12-28 13:33:23</time>
        <double>28.9</double>
    </order>

    <order id="3">
        <name>决明子</name>
        <time>2023-03-21 09:30:00</time>
        <double>36.5</double>
    </order>

    <order id="4">
        <name>菊花</name>
        <time>2023-05-11 19:30:00</time>
        <double>16.5</double>
    </order>
</orders>

新建Order.java订单类,是根据xml文件的属性和子元素来确定成员变量

import java.time.LocalDateTime;

public class Order {
    private int id;
    private String name;
    private LocalDateTime orderTime;
    private double price;

    public Order() {
    }

    public Order(int id, String name, LocalDateTime orderTime, double price) {
        this.id = id;
        this.name = name;
        this.orderTime = orderTime;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public LocalDateTime getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(LocalDateTime orderTime) {
        this.orderTime = orderTime;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "订单编号" + getId() +
                "   订单名:" + getName() +
                "   订单时间:" + getOrderTime() +
                "   价格:" + getPrice();
    }
}

新建一个订单的操作类OrderOperator.java,完成上面的需求

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

public class OrderOperator {
    public static void main(String[] args) throws Exception {
        ArrayList<Order> orderArrayList = new ArrayList<>();

        // 导入dom4j, 创建SAXReader的对象准备读取xml文件
        SAXReader saxReader = new SAXReader();
        // 读取xml文件成为一个Document对象 
        // OrderOperator.class.getResourceAsStream() 写一个‘/’,代表去src下找orders.xml,相对路径的写法
        Document document = saxReader.read(OrderOperator.class.getResourceAsStream("/orders.xml"));
        // 获得根元素
        Element root = document.getRootElement();
        //System.out.println(root.getName());

        // 解析string时间的解析器
        DateTimeFormatter formatter =
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 获得所有以及子元素
        List<Element> elements = root.elements();
        for (Element element : elements) {
            Order order = new Order();
            // 获得元素的属性值id
            order.setId(Integer.valueOf(element.attributeValue("id")));
            order.setName(element.elementText("name"));
            // 时间获取之后解析一下
            String time = element.elementText("time");
            // 2023-11-21 13:33:23
            LocalDateTime ldt = LocalDateTime.parse(time, formatter);
            // System.out.println(ldt);
            order.setOrderTime(ldt);
            order.setPrice(Double.valueOf(element.elementText("double")));
            orderArrayList.add(order);
        }
		
		// 下面的都是lambda表达式,filter是过滤,isBefor是找当前时间之前的
        orderArrayList.stream().filter(s -> s.getOrderTime().isBefore(LocalDateTime.now())).forEach(
                s -> System.out.println(s)
        );

        System.out.println("-----------------------------------");

        Order order = orderArrayList.stream().max((o1, o2) -> Double.compare(o1.getPrice(), o2.getPrice())).get();
        System.out.println(order);
        System.out.println("-----------------------------------");

		// 题目要求降序,则compare(o2.getPrice(), o1.getPrice())
		// 升序 compare(o1.getPrice(), o2.getPrice())
        orderArrayList.stream().sorted((o1, o2) -> Double.compare(o2.getPrice(), o1.getPrice())).forEach(
                s -> System.out.println(s)
        );
        // System.out.println("-----------------------------------");
    }
}

下图是结果显示:
在这里插入图片描述

第二题(10)

需求

  • 某个班级组织团建活动,班长给出了几个去处给大家选择,分别是 “农家乐” , “轰趴”,“野外拓展”,“健身房”,本次活动每个学生是可以多选的。

  • 现在有如下5名学生选择了如下去处。

张全蛋儿  农家乐,野外拓展
李二狗子  轰趴,野外拓展,健身房
翠花     野外拓展,
小帅     轰趴,健身房
有容     农家乐

具体的功能点如下:

1、请找出每个去处想去的人数是多少,并输出投票最多的去处是哪个。

2、请找出哪些人没有选择投票最多的去处,输出他们的名字。(本案例用不用stream流做都给分

比如:小帅,有容没有选择野外拓展。
用student.java封装了两个局部变量,存名字和想去的地方。

import java.util.ArrayList;

public class Student {
    private String name;
    private ArrayList<String> slectPoint;

    public Student() {
    }

    public Student(String name, ArrayList<String> slectPoint) {
        this.name = name;
        this.slectPoint = slectPoint;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ArrayList<String> getSlectPoint() {
        return slectPoint;
    }

    public void setSlectPoint(ArrayList<String> slectPoint) {
        this.slectPoint = slectPoint;
    }

    @Override
    public String toString() {
        String str = "姓名:" + name + " 选择的地方有:";
        for (int i = 0; i < slectPoint.size(); i++) {
            String temp = (i == slectPoint.size() - 1) ? "" : "、";
            str+=slectPoint.get(i) + temp;
        }
        return str;
    }
}

新建一个StudentOperator.java类来操作Student。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class StudentOperator {
    public static void main(String[] args) {
        ArrayList<Student> studentArrayList = new ArrayList<>();
        // 初始化
        initStudentList(studentArrayList);
        // System.out.println(studentArrayList);
        // 用两个数组模拟的map集合,可以直接用map集合,写的时候没想到
        String[] names = {"农家乐", "野外拓展", "轰趴", "健身房"};
        int[] countNames = {0, 0, 0, 0};
        // 找每个去处的人数 封装成一个函数
        findPointNumber(countNames, names, studentArrayList);
        //下面是找某个地方去的人数最多的(有可能有两个地方)
        int maxPointNumberIndex = 0;
        for (int i = 0; i < countNames.length; i++) {
            if(countNames[maxPointNumberIndex] < countNames[i]){
                maxPointNumberIndex = i;
            }
            System.out.println(names[i] + "想去的人数有:" + countNames[i]);
        }
        // 这是用来判断如果取得人数相同且最多
        ArrayList<String> popularPoint = new ArrayList<>();
        for (int i = 0; i < countNames.length; i++) {
            if(countNames[maxPointNumberIndex] == countNames[i]){
                popularPoint.add(names[i]);
            }
        }
        //System.out.println(popularPoint);
        System.out.println("--------------------------------");
        System.out.println("去的人数最多的地方有:");
        popularPoint.stream().forEach(s -> System.out.println(s));

        System.out.println("-------------------------------");
        System.out.println("如下一些人不想去人数多的地方:");
        studentArrayList.stream().filter(s -> {
            for (String s1 : popularPoint) {
                if(s.getSlectPoint().contains(s1)){
                    return false;
                }
            }
            return true;
        }).forEach(s -> System.out.println(s.getName()));
    }

    private static void findPointNumber(int[] countNames, String[] names, ArrayList<Student> studentArrayList) {
        for (Student student : studentArrayList) {
            for (String s : student.getSlectPoint()) {
                for (int i = 0; i < names.length; i++) {
                    if(s.equals(names[i])){
                        countNames[i]++;
                        break;
                    }
                }
            }
        }
    }

    private static void initStudentList(ArrayList<Student> studentArrayList) {
        //这里存数据还是用Collections.addAll()比较好
        ArrayList<String> point1 = new ArrayList<>();
        Collections.addAll(point1, "农家乐", "野外拓展", "轰趴");
        Student s1 = new Student("张全蛋儿", point1);
        studentArrayList.add(s1);
        ArrayList<String> point2 = new ArrayList<>();
        point2.add("轰趴");
        point2.add("健身房");
        Student s2 = new Student("李二狗子", point2);
        studentArrayList.add(s2);
        ArrayList<String> point3 = new ArrayList<>();
        point3.add("轰趴");
        point3.add("野外拓展");
        Student s3 = new Student("翠花", point3);
        studentArrayList.add(s3);
        ArrayList<String> point4 = new ArrayList<>();
        point4.add("野外拓展");
        point4.add("健身房");
        Student s4 = new Student("小帅", point4);
        studentArrayList.add(s4);
        ArrayList<String> point5 = new ArrayList<>();
        point5.add("农家乐");
        Student s5 = new Student("有容", point5);
        studentArrayList.add(s5);
    }
}

下图是输出结果:
在这里插入图片描述

第三题 (15)

需求

  • 黑马程序员教学管理系统的菜单信息如下(图1所示),菜单的详细数据存储在给的素材文件“系统菜单.txt”中
  • 在这里插入图片描述具体要实现的功能点如下所示

1、请从系统菜单.txt中读取这些菜单信息,将这些菜单信息在控制台展示成图1的样子(必须确保展示的顺序是正确的)

2、将正确的菜单顺序,写出到一个新文件**“系统菜单2.txt”**中保存起来,详细格式如下
在这里插入图片描述评分细则

  • 能把数据读取出来:3分
  • 能展示成控制台的样子:8分
  • 能写出去:4分。

系统菜单.txt

00010001-班级学员管理 
00030001-就业班管理
00030002-就业学员管理
0001-班级管理
00020001-班级每日反馈
00020002-班级入学测评
00010002-班级学员就业管理
0003-就业业务管理
00020003-班级讲师评分
00020004-班级授课视频
0002-教学业务管理
00020005-班级作息时间设置
00030003-学员面试记录
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;

public class operatorFile {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        try(
                // 用相对路径创建一个字符输入流
                Reader fr = new FileReader("case-lianxi\\src\\系统菜单.txt");
                BufferedReader br = new BufferedReader(fr);
                Writer fw = new FileWriter("case-lianxi\\src\\系统菜单2.txt");
                BufferedWriter bw = new BufferedWriter(fw);
                ) {
            String line;
            // 按行读
            while((line = br.readLine())!=null){
                list.add(line);
            }
            // 排序,可以对其按前面的数字来排序
            Collections.sort(list);
            for (String s : list) {
                String[] splitS = s.split("-");
                if(splitS[0].length() == 8){
                    System.out.print("\t");
                }
                System.out.println(splitS[1]);
            }

            // 写到文件中去  也可用打印流
            for (String s : list) {
                bw.write(s);
                bw.newLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

控制台输出:
在这里插入图片描述

第四题(20)

需求

  • 红包雨游戏,某企业有100名员工,员工的工号依次是1, 2,3, 4,…到100。现在公司举办了年会活动,活动中有一个红包雨环节,要求共计发出200个红包雨。其中小红包在[1 - 30] 元之间,总占比为80%,大红包[31-100]元,总占比为20%。

具体的功能点如下

1、系统模拟上述要求产生200个红包。

2、模拟100个员工抢红包雨,需要输出哪个员工抢到哪个红包的过程,活动结束时需要提示活动结束。

3、活动结束后,请1对100名员工按照所抢红包的总金额进行降序排序展示,例如:3号员工抢红包总计:293元、1号员工抢红包总计250元,…

将每个员工封装成一个employee.java类

package com.exercise.FinalExam.redBag;

public class Employee {
    private int id;
    private int redEnveNum;

    public Employee() {
    }

    public Employee(int id, int redEnveNum) {
        this.id = id;
        this.redEnveNum = redEnveNum;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getRedEnveNum() {
        return redEnveNum;
    }

    public void setRedEnveNum(int redEnveNum) {
        this.redEnveNum = redEnveNum;
    }

    @Override
    public String toString() {
        return id + "号员工抢到红包总计" + redEnveNum;
    }
}

实现一个EmployeeThread类,因为红包是同时抢的,所以要用线程,这里应该让线程继承Callable,会更方便。

import java.util.ArrayList;
import java.util.Random;

public class EmployeeThread extends Thread{
    // 红包
    private ArrayList<Integer> redEnve = new ArrayList<>();
    // 员工类
    private ArrayList<Employee> employeeArrayList = new ArrayList<>();
    private int index;
    private Random r = new Random();

    public EmployeeThread() {
    }

    public EmployeeThread(ArrayList<Integer> redEnve, ArrayList<Employee> employeeArrayList, int index) {
        this.redEnve = redEnve;
        this.employeeArrayList = employeeArrayList;
        this.index = index;
    }

    public ArrayList<Integer> getRedEnve() {
        return redEnve;
    }

    public void setRedEnve(ArrayList<Integer> redEnve) {
        this.redEnve = redEnve;
    }

    @Override
    public void run() {
        // 这里我限定了每个人最多能抢5个红包,如果用while(true)可能电脑性能问题,几个人集中抢了很多红包,很多人抢不到,结果不好
        for(int i = 0; i < 5; i++){
            // 用红包加锁,因为红包是所有线程操作的共同对象
            synchronized (redEnve) {
                if(redEnve.size() == 0){
                    break;
                }
                int value = r.nextInt(redEnve.size());
                System.out.println(employeeArrayList.get(index).getId()
                        + "抢到" + redEnve.get(value));
                employeeArrayList.get(index).setRedEnveNum(employeeArrayList.get(index).getRedEnveNum() + redEnve.get(value));
                redEnve.remove(value);
                try {
                    Thread.sleep(30);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

主函数redEnvelope.java类

import java.util.*;

public class redEnvelope {
    public static void main(String[] args) throws Exception {
        ArrayList<Employee> employeeArrayList = new ArrayList<>();
        // 把每个员工的编号保存
        for (int i = 1; i <= 100; i++) {
            Employee employee = new Employee();
            employee.setId(i);
            employeeArrayList.add(employee);
        }
        // System.out.println(employeeArrayList);
        // 生成红包雨
        Random r = new Random();
        ArrayList<Integer> redEnve = new ArrayList<>();
        for (int i = 1; i <= 200 * 0.8; i++) {
            int value = r.nextInt(30) + 1;  // r.nextInt(30) 0-29
            redEnve.add(value);
        }
        for (int i = 161; i <= 200; i++) {
            int value = r.nextInt(70) + 31;  // (0-69) + 31;
            redEnve.add(value);
        }
        // System.out.println(redEnve);
        // 打乱红包
        // 新建100个线程代表每个人 来同时抢红包
        Collections.shuffle(redEnve);
        // System.out.println(redEnve);
        // 存放100个线程,便于后面用join,让主线程先等一下
        List<EmployeeThread> threads = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            EmployeeThread thread = new EmployeeThread(redEnve, employeeArrayList, i);
            threads.add(thread);
            thread.start();
        }

        for (EmployeeThread thread : threads) {
            thread.join();
        }

        Collections.sort(employeeArrayList, (o1, o2) -> o2.getRedEnveNum() - o1.getRedEnveNum());
        // System.out.println(employeeArrayList);
        for (Employee employee : employeeArrayList) {
            System.out.println(employee);
        }
    }
}

结果如图:
在这里插入图片描述

第五题(24)

需求

在实际开发中,很多系统都要完成用户登录和注册功能,但需要注意的是,用户注册的登录名和密码必须是发送给服务端进行保存的,并且注册的登录名是不能重复的,同时登录也是需要到服务端进行认证的。

功能点具体要求

1、开发一个客户端,具备注册,和登录功能,除非用户输入exit,否则不退出这个界面。

2、注册功能要求:可以发送登录名和密码给服务端,服务端要响应是否注册成功的结果给客户端。如果注册没有问题,服务端需要将用户注册的登录名和密码保存到文件中去。(注:是什么文件,可自行确定

3、登录功能要求:用户输入登录名和密码,需要发送给服务端,服务端认证后需要把登录的结果发送给客户端接收。

评分细则

  • 能开发出客户端,并成功发送注册信息给服务端接收 4
  • 服务端能接收注册信息,并成功写出去到属性文件中去 9
  • 客户端能正确收到服务端响应的注册信息。 2
  • 客户端能成功发出登录信息,服务端能成功收到 3
  • 服务端能正确认证登录是否成功 4
  • 客户端能收到登录后的结果。 2

Client.java

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    private static Socket socket;
    private static DataOutputStream dos;
    private static DataInputStream dis;
    public static void main(String[] args) throws Exception {
        // 创建socket对象
        Client.socket = new Socket("127.0.0.1", 8888);
        // 从socket获取字节输出流
        OutputStream os = socket.getOutputStream();
        // 创建数据输出流
        Client.dos = new DataOutputStream(os);
        InputStream is = socket.getInputStream();
        Client.dis = new DataInputStream(is);

        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("客户端功能如下:");
            System.out.println("1、注册");
            System.out.println("2、登录");
            System.out.println("如果想退出,请输入exit");
            System.out.println("请输入你的选择:");
            String select = sc.next();
            switch (select){
                case "1":
                    register();
                    // 接收结果 会阻塞等待,一直等服务器的结果
                    String s = dis.readUTF();
                    System.out.println(s);
                    break;
                case "2":
                    login();
                    String s1 = dis.readUTF();
                    System.out.println(s1);
                    break;
                case "exit":
                    System.out.println("退出成功");
                    // dos.writeUTF("exit");
                    dos.close();
                    socket.close();
                    return;
            }
        }
    }

    private static void register() throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入要注册的用户名:");
        String username = sc.next();
        System.out.println("请输入密码:");
        String password = sc.next();
        // 发送给服务骑
        Client.dos.writeUTF("register");
        Client.dos.writeUTF(username);
        Client.dos.writeUTF(password);
        // 刷新一下,防止没刷出去
        Client.dos.flush();
    }

    private static void login() throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.next();
        System.out.println("请输入密码:");
        String password = sc.next();
        // 发送给服务骑
        Client.dos.writeUTF("login");
        Client.dos.writeUTF(username);
        Client.dos.writeUTF(password);
        Client.dos.flush();
    }
}

Server.java

import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println("=======服务器=======");
        // 注册端口
        ServerSocket serverSocket = new ServerSocket(8888);

        //创建线程池 如果多个用户过来每个人分配给一个线程池
        ExecutorService pool = new ThreadPoolExecutor(3,5,
                20, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        // 服务器端默认一直在线
        while (true) {
            // 等待客户端连接 这个是每个客户端要和服务器端取得连接,所以要放在循环里面,之前放在外面,所以一直出问题,报错
            Socket socket = serverSocket.accept();
            // 创建任务
            Runnable target = new ServerRunnable(socket);
            pool.execute(target);
        }
    }
}

ServerRunnable.java,是每个线程要处理的任务,实现了Runnable接口,重写了run方法。

import java.io.*;
import java.net.Socket;
import java.util.ArrayList;

public class ServerRunnable implements Runnable{
    private Socket socket;

    public ServerRunnable() {
    }

    public ServerRunnable(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try(
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                PrintStream ps = new PrintStream(new FileOutputStream("D:\\Java\\JavaProjects\\case-lianxi\\src\\unamepwd.txt", true));
                BufferedReader br = new BufferedReader(new FileReader("D:\\Java\\JavaProjects\\case-lianxi\\src\\unamepwd.txt"));
        ) {
            while (true){
                String s = dis.readUTF();
                String username = dis.readUTF();
                String password = dis.readUTF();
                String line;
                ArrayList<String> unpwds = new ArrayList<>();
                while((line = br.readLine())!=null){
                    unpwds.add(line);
                }
                boolean flag = false;
                if("register".equals(s)){
                    for (String unamepwd : unpwds) {
                        String[] unpwd = unamepwd.split(",");
                        String[] user = unpwd[0].split("=");
                        if(username.equals(user[1])){
                            flag = true;
                        }
                    }
                    if(flag == true){
                        // 写给客户端注册失败
                        dos.writeUTF("注册失败, 用户名重复");
                    }
                    else{
                        System.out.println(Thread.currentThread().getName() + "线程" + "username="+username + ", password="+password + ",注册成功");
                        dos.writeUTF("注册成功");
                        // 写到文件中
                        ps.println("username="+username + ", password="+password);
                    }
                }
                else if("login".equals(s)){
                    if(unpwds.size() == 0){
                        dos.writeUTF("当前无任何用户信息,无法登录!");
                    }
                    else {
                        for (String unamepwd : unpwds) {
                            String[] unpwd = unamepwd.split(",");
                            String[] user = unpwd[0].split("=");
                            String[] pass = unpwd[1].split("=");
                            if (username.equals(user[1]) && password.equals(pass[1])) {
                                flag = true;
                                break;
                            }
                        }
                        if (flag == true) {
                            System.out.println(Thread.currentThread().getName() +"username=" + username + ", password=" + password + ",登录成功");
                            dos.writeUTF("登录成功");
                        } else {
                            dos.writeUTF("登录失败,用户名或密码错误");
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.out.println(Thread.currentThread().getName() +"有人离线了~~");
            // e.printStackTrace();
        }
    }
}

上述代码可以实现简易的多客户端向服务器发起的通信,服务端也能将数据写回给客户端,建立的socket连接中既有数据输入流也有数据输出流,用于读写数据。

第六题 (16)

需求

  • 在素材demo6包下,有生成链表的代码,目前Test类中已经为您创建了两个链表,分别是链表 head1 -> 2 → 4 → 1,链表head24→ 1 → 3 。

具体功能点如下

  • 1、在MyLinkedList类中,开发一个sort方法,支持对链表进行升序排序,写完后需要分别测试对这两个链表排序,并分别遍历输出。

  • 2、在MyLinkedList类中,开发一个mergeSort方法,支持将这两个升序排序的链表,再次合并成一个新链表,要求新链表中的节点仍然是递增排序的。

    示例1:

    输入:head1 -> 2 → 4 → 1, head2 → 4 → 1 → 3
    返回:head3 -> 1->1->2->3->4->4

评分细则

  • 能正确排序并遍历链表:6分

  • 能合并并排序:10分
    MyLinkedList.java

import java.util.ArrayList;
import java.util.Collections;

// 继承比较接口,下面的sort就支持排序了 不然要强转
public class MyLinkedList<E extends Comparable> {
    // 封装一个链表
    Node<E> head = null;
    /**
     * 定义了一个私有的内部类,作为链表的结点。
     */
    public static class Node<E> {
        E data;
        Node<E> next;

        public Node(E data, Node<E> next) {
            this.data = data;
            this.next = next;
        }
    }

    public Node<E> add(E e) {
        if (head == null) {
            head = new Node(e, null);
        } else {
            // 往后面插入结点。(尾插法)
            Node<E> temp = head;
            // 让temp走到尾部结点
            while (temp.next != null) {
                temp = temp.next;
            }
            // 把当前结点创建出来,加入到尾部结点
            temp.next = new Node(e, null);
        }
        return head;
    }

	// 思路就是先把链表的值拿出来放集合中排序再放回去
    public Node<E> sort(Node<Integer> head1){
        ArrayList<E> linkedList = new ArrayList<>();
        Node<E> p = (Node<E>) head1;
        while(p != null){
            linkedList.add(p.data);
            p = p.next;
        }
        Collections.sort(linkedList);
        p = (Node<E>) head1;
        int index = 0;
        while(p != null){
            p.data = linkedList.get(index++);
            p = p.next;
        }
        return head;
    }

	// 这个也可以用上面sort类似的方法,但我是直接操作链表会复杂一点
    public Node<Integer> mergeSort(Node<Integer> list1, Node<Integer> list2){
    	if(list1 == null){
            return list2;
        }
        if(list2 == null){
            return list1;
        }
        sort(list1);
        sort(list2);
        Node<Integer> p = (Node<Integer>) list1;
        Node<Integer> q = (Node<Integer>) list2;
        Node<Integer> s = (Node<Integer>) list2;
        Node<Integer> pre = (Node<Integer>) list1;
        // 将q装在p里面
        while (p != null && q != null){
            if(p.data < q.data){
                pre = p;
                p = p.next;
            }
            else if(p.data == q.data){
                s = q.next;
                q.next = p.next;
                p.next = q;
                q = s;
            }
            else if(p.data > q.data){
                if(p == list1){
                    // 还在头,需要头插
                    s = q.next;
                    q.next = p;
                    p = q;
                    q = s;
                    list1 = p;
                }else {
                    s = q.next;
                    q.next = p;
                    pre.next = q;
                    q = s;
                    pre = pre.next;
                }
            }
        }
        if(p == null && q != null){
            pre.next = q;
        }
        return list1;
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        // 第一个链表:
        MyLinkedList<Integer> list1 = new MyLinkedList<>();
        list1.add(2);
        list1.add(4);
        list1.add(1);
        // 第一个链表的头结点:head1
        MyLinkedList.Node<Integer> head1 = list1.head;

        // 第二个链表:
        MyLinkedList<Integer> list2 = new MyLinkedList<>();
        list2.add(5);
        list2.add(0);
        list2.add(3);
        // 第二个链表的头结点:head1
        MyLinkedList.Node<Integer> head2 = list2.head;

        MyLinkedList<Integer> list = new MyLinkedList<>();
        // 功能1:在MyLinkedList类中,开发一个sort方法,对两个链表分别排序,并分别遍历输出
        // 链表其实是有一个头结点的
        list.sort(head1);
        MyLinkedList.Node<Integer> p = head1;
        while (p != null){
            System.out.println(p.data);
            p = p.next;
        }
        list.sort(head2);
        MyLinkedList.Node<Integer> q = head2;
        while (q != null){
            System.out.println(q.data);
            q = q.next;
        }

        // 功能2:在MyLinkedList类中,开发一个mergeSort方法,支持将这两个升序排序的链表,合并成一个新链表,要求新链表中的节点仍然是递增排序的。
        // ,然后对新链表遍历输出
        System.out.println("----------------");
        MyLinkedList.Node<Integer> mergeSort = list.mergeSort(head1, head2);
        MyLinkedList.Node<Integer> t = mergeSort;
        while (t != null){
            System.out.println(t.data);
            t = t.next;
        }
    }
}
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值