数据结构课设-学生成绩管理系统

帮朋友写了个java数据结构课设,记录一下

本次课设用到的文件,密码d315

学生成绩管理系统

    • 问题描述
    • 实验要求
    • 上代码

问题描述

现有学生成绩信息文件1(1.txt),内容如下:
数据结构课设-学生成绩管理系统_第1张图片
学生成绩信息文件2(2.txt),内容如下:
数据结构课设-学生成绩管理系统_第2张图片

实验要求

试编写一管理系统,要求如下:

(1)实现对两个文件数据进行合并,生成新文件3.txt,(去重)

(2)抽取出三科成绩中有补考的学生并保存在一个新文件4.txt

(3)对合并后的文件3.txt中的数据按总分降序排序(至少采用两种排序方法实现必须包含一个时间复杂为nlog2n)

(4)输入一个学生姓名后,能查找到此学生的信息并输出结果(至少采用两种查找方法实现)

(5)要求使用结构体,链或数组等实现上述要求.

上代码

首先是学生的javabean,根据题目要求设置了几个私有属性,姓名,学号,成绩等,顺手添加了他的get和set方法.

因为要求第二条需要判断是否挂科我添加了 re_exam() 方法判断是否补考

在读取文件的同时还需要去重,自然而然的想到了集合,但是使用HashSet需要重写equals方法和hashCode方法,之前使用hashset都是存一些整型字符串之类的,这一次存自己定义的对象还费了一番周折

toString方法我也改了一下,主要是为了输出到文档上方便对齐(对齐也不好看)

构造方法我使用list作为参数,在主类里面list中将会含有读取到的所有信息,方便创建对象(自然也要留一个无参的构造方法)

package com.jiashi.test;

import java.io.Serializable;
import java.util.ArrayList;

public class student implements Serializable {
    private String name; //姓名

    private String snum;//学号

    private Integer chinese;//语文

    private Integer math;//数学

    private Integer english;//英语

    private Integer score;//总分

    public boolean re_exam() {//判断是否补考
        if (chinese >= 60 && math >= 60 && english >= 60) {
            return false;
        } else {
            return true;
        }
    }

    //类的构造方法
    public student(ArrayList<String> list) {
        this.name = list.get(0);
        this.snum = list.get(1);
        this.chinese = Integer.parseInt(list.get(2));
        this.math = Integer.parseInt(list.get(3));
        this.english = Integer.parseInt(list.get(4));
        this.score = chinese + math + english;
    }
    
	public student() {
        
    }
    //toString方法
    @Override
    public String toString() {
        return name + "   " + 
        		snum + "   " + 
        		chinese + "     " + 
        		math + "      " + 
        		english + "     " + 
        		score;
    }

    //复写hashCode方法
    @Override
    public int hashCode() {
        int prim = 31;


        int resultCode = prim * (prim + 1) + snum.hashCode();


        return resultCode;
    }

    //复写equals方法
    @Override
    public boolean equals(Object obj) {
        if(!(obj instanceof student)) {
            // instanceof 已经处理了obj = null的情况
            return false;
        }
        student stuObj = (student) obj;
        // 地址相等
        if (this == stuObj) {
            return true;
        }
        // 如果两个对象姓名、年龄、性别相等,我们认为两个对象相等
        if (stuObj.getName().equals(this.name) 
        && stuObj.getSnum().equals(this.snum)) {
            return true;
        } else {
            return false;
        }
    }

    public String getSnum() {
        return snum;
    }

    public void setSnum(String snum) {
        this.snum = snum;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }

    public String getName() {
        return name;
    }

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


    public Integer getChinese() {
        return chinese;
    }

    public void setChinese(Integer chinese) {
        this.chinese = chinese;
    }

    public Integer getMath() {
        return math;
    }

    public void setMath(Integer math) {
        this.math = math;
    }

    public Integer getEnglish() {
        return english;
    }

    public void setEnglish(Integer english) {
        this.english = english;
    }
}

然后是主类,主要有如下几个方法

  1. readFile
    该方法旨在从文件中读取数据,由于其按行读取的特性,我选择使用BufferedReader,我在IDE上面使用UTF-8读取我桌面上的文件产生了乱码,于是将InputStreamReader的第二个构造参数传为GBK,乱码就被解决了(大概是编码问题);

    在读取文件中每一行的文件时,需要过滤首行和行与行之间的空隙,我使用split将字符串分解为数组,但是正则不太会用,这就导致我在信息行的数组里面多了好多空格的元素,无奈之下将数组中空格过滤,然后添加到list中(顺序存储很好用),然后利用list作为参数创建student对象;然后将对象存入hashset中

  2. writeFile
    写出文件就要省事多了,将排序好的list传入,遍历的时候PrintWriter直接按行写出即可

  3. 排序算法和查找算法
    在此就不过多赘述,篇幅较大

  4. main
    当上面的函数都写好了之后,事情就变得简单多了,读取文件存到HashSet中,然后遍历到list里面方便排序,遍历的过程中顺手做个判断,挂科的也存起来,然后使用写好的排序算法排序,然后打印.

    然后是查找学生,用Scanner读取查找的姓名,当输入不为quit时不跳出查找的循环,查到就打印出来,查不到就不打印.这里使用循环方便用户多次查找,而不是查找一次

另外,我的读写文件路径是我的桌面,不同用户自行修改

package com.jiashi.test;


import java.io.*;
import java.util.*;

public class Application {

    //使用hashset来去重
    protected static HashSet<student> students = new HashSet<student>();

    //读取文件的方法
    public static void readFile(String path) throws IOException {
        FileInputStream fis = new FileInputStream(path);
        //设置GBK编码防止乱码,如果在其他设备乱码可以改成UTF-8试试
        InputStreamReader isr = new InputStreamReader(fis, "GBK");
        BufferedReader br = new BufferedReader(isr);

        /*
         * BufferedReader提供了按行读取方法
         * String readLine()
         * 连续读取若干字符,直到读取到换行符位置,并将
         * 换行符之间读取的字符以一个字符串返回,若返回值为null
         * 则表示读取到末尾
         * 注意:该字符串不包含最后的换行符
         */

        //从流中读取到的字符串
        String line = null;
        //将字符串截取为数组存在这里
        String[] split = null;
        //过滤数组,将有用信息存在这里
        ArrayList<String> list = new ArrayList<>();

        while ((line = br.readLine()) != null) {
            split = line.split("\\ ");
            //读取到的文件行与行之间有空数组,下面判断滤去第一行和空行
            if (split.length != 1 && !"姓名".equals(split[0])) {
                int j = 0;
                for (int i = 0; i < split.length; i++) {
                    //过滤数组中的空格
                    if (!"".equals(split[i])) {
                        //将数据存入list
                        list.add(split[i]);
                    }
                }
                //使用list创建学生对象,存入hashset
                students.add(new student(list));
                //清除list中的上一组数据
                list.clear();
            }
        }
        //关闭流
        br.close();
    }

    public static void writeFile(String path, ArrayList<student> list) throws IOException {
        /*
         * 提供了多种构造方法
         * 其中有两个可以直接
         * 对文件进行写出操作的构造方法
         *
         * PrintWriter(File file)
         * PrintWriter(String path)
         */
        PrintWriter pw = new PrintWriter(path, "GBK");
        pw.println("姓名   学号   语文   数学   英语   总分");
        for (student s : list) {
            //遍历list并写出
            pw.println(s);
        }
        System.out.println("写出完毕 ");
        //关闭流
        pw.close();
    }

    //冒泡排序
    public static ArrayList<student> bubbleSort(ArrayList<student> list) {
        student temp;
        //一共比较length-1轮
        for (int i = 0; i < list.size() - 1; i++) {
            //一次比较length-1-i次
            for (int j = 0; j < list.size() - 1 - i; j++) {
                if (list.get(j).getScore() < list.get(j + 1).getScore()) {
                    temp = list.get(j + 1);
                    list.set(j + 1, list.get(j));
                    list.set(j, temp);
                }
            }
        }
        return list;
    }

    //快速排序
    public static ArrayList<student> fastSort(ArrayList<student> list) {
        quickSort(list, 0, list.size() - 1);
        return list;
    }

    //快速排序子方法
    public static void quickSort(ArrayList<student> list, int start, int end) {
        if (start < end) {
            //把第0个元素当做标准元素
            student stard = list.get(start);
            //记录需要排序的下标
            int low = start;
            int high = end;
            //循环找出比标准数分数大的元素和比标准数分数小的元素
            while (low < high) {
                //右边分数比标准数小
                while (low < high && stard.getScore() >= list.get(high).getScore()) {
                    high--;
                }
                //使用右边的元素替换左边的元素
                list.set(low, list.get(high));
                //右边分数比标准数大
                while (low < high && stard.getScore() <= list.get(low).getScore()) {
                    low++;
                }
                list.set(high, list.get(low));
            }
            //把标准元素赋给low==high的位置
            list.set(low, stard);
            //处理所有小于标准数的数字
            quickSort(list, start, low);
            //处理所有大于标准数的数字
            quickSort(list, low + 1, end);
        }
    }

    //线性查找
    public static void lineSearch(String name) {
        System.out.println("线性查找:");
        for (student s : students) {
            if (s.getName().equals(name)) {
                System.out.println("姓名   学号   语文   数学   英语   总分");
                System.out.println(s);
            }
        }
    }

    //二分查找
    public static void binarySearch(ArrayList<student> list, String str) {
        System.out.println("二分查找");
        //二分查找要按顺序,所以用compareTo来排序一下
        student temp;
        for (int i = 0; i < list.size() - 1; i++) {
            for (int j = 0; j < list.size() - 1 - i; j++) {
                if (list.get(j).getName().compareTo(list.get(j + 1).getName()) > 0) {
                    temp = list.get(j + 1);
                    list.set(j + 1, list.get(j));
                    list.set(j, temp);
                }
            }
        }

        int low = 0;
        int height = list.size() - 1;
        int mid;
        while (low <= height) {
            mid = (low + height) / 2;
            if (list.get(mid).getName().compareTo(str) > 0) {
                height = mid - 1;
            } else if (list.get(mid).getName().compareTo(str) < 0) {
                low = mid + 1;
            } else if (list.get(mid).getName().compareTo(str) == 0) {
                System.out.println("姓名   学号   语文   数学   英语   总分");
                System.out.println(list.get(mid));
                break;
            }
        }
    }

    public static void main(String[] args) {

        //读取两个文件的内容
        try {
            readFile("C:\\Users\\Excalibur\\Desktop\\1.txt");
            readFile("C:\\Users\\Excalibur\\Desktop\\2.txt");
        } catch (Exception e) {
            e.printStackTrace();
        }

        ArrayList<student> list = new ArrayList<>();
        ArrayList<student> list_re = new ArrayList<>();
        //因为要排序,所以把元素从hashset->list
        for (student s : Application.students) {
            list.add(s);
            //将挂科的存一下
            if (s.re_exam()) {
                list_re.add(s);
            }
        }
        //快速排序产生的list
        ArrayList<student> fast = fastSort(list);

        try {
            //使用快速排序打印3.txt
            writeFile("C:\\Users\\Excalibur\\Desktop\\3.txt", fast);
            //使用冒泡排序打印4.txt
            writeFile("C:\\Users\\Excalibur\\Desktop\\4.txt", bubbleSort(list_re));
        } catch (IOException e) {
            e.printStackTrace();
        }

        //读取键盘
        Scanner scanner = new Scanner(System.in);
        String str = "";
        //当没输入quit就一直循环,这样可以查好多次
        while (!"quit".equals(str)) {
            System.out.println("-------------------------------------------");
            System.out.print("请输入待查找的学生姓名,输入quit退出:");
            str = scanner.nextLine();
            if (!"quit".equals(str)) {
                //线性查找
                lineSearch(str);
                //二分查找
                binarySearch(fast, str);
            }
            System.out.println("-------------------------------------------");
        }
    }
}

对于大佬来说这个可能很简单,希望可以帮到哪位做课设的学弟学妹

码字不易,点个赞再走吧

你可能感兴趣的:(java,数据结构)