Java-对象数组及其排序、查找算法


数组

用数组存储对象

在前面我们已经对数组的创建和引用进行了介绍。接下来主要介绍数组存储对象、查找对象、删除对象及常用的排序算法。

数组元素可以是任何类型(只要所有元素具有相同的类型),除了基本数据类型,数组的元素也可以是类的对象,这样的数组称之为对象数组。

对数组的初始化分为静态初始化和动态初始化两种。

  • 静态初始化:在声明和定义数组的同时对数组元素进行初始化;
BankAccount[] accounts={new BankAccount("zhang",100.00)},
new BankAccount("li",2380.00),new BankAccount("wang",500.00);
  • 动态初始化:使用运算符new为数组分配空间,对于基本类型的数组,其格式如下;
type arrayName[]=new type[arraySize};
type[] arrayName=new type[arraySize];

对于对象数组,使用运算符new只是为数组本身分配空间,并没有对数组的元素进行初始化。即数组元素都为空,此时不能访问数组的任何元素,必须对数组元素进行初始化后,才能访问。因此对于对象数组,需要经过两步;

首先给数组分配空间,数组的每个元素只是对象的一个饮用。

type arrayName[]=new type[arraySize];

然后给每一个数组元素分配空间,并将其引用赋值给对应的数组元素。

arrayName[0]=new type(paramList);
...
arrayName[arraySize-1]=new type(paramList);

用数组存储一个班的学生信息

首先声明学生类Stude;

  • 属性包括 学号(id)、姓名(name)、英语成绩(eng)、数学成绩(math)、计算机成绩(comp)、总成绩(sum)。
  • 方法包括 构造方法、get方法、set方法、toString方法、equals方法、compare方法、sum方法。
import java.io.*;
public class Student {
    private String id;
    private String name;
    private int eng;
    private int math;
    private int comp;
    private int sum;
    //构造方法
    public Student(String id,String name,int eng,int math,int comp){
        this.id=id;
        this.name=name;
        this.eng=eng;
        this.math=math;
        this.comp=comp;
        sum();//计算总成绩
    }
    public Student(Student s){
        this.id=s.id;
        this.name=s.name;
        this.eng=s.eng;
        this.math=s.math;
        this.comp=s.comp;
        sum();//计算总成绩
    }
    public void setId(String id){
        this.id=id;
    }
    public void setName(String name){
        this.name=name;
    }
    public void setEng(int eng){
        this.eng=eng;
        sum();
    }
    public void setMath(int math){
        this.math=math;
        sum();
    }
    public void setComp(int comp){
        this.comp=comp;
        sum();
    }
    public String getId(){
        return id;
    }
    public String getName(){
        return name;
    }
    public int getEng(){
        return eng;
    }
    public int getMath(){
        return math;
    }
    public int getComp(){
        return comp;
    }
    public int getSum(){
        return sum;
    }
    void sum(){
        this.sum=eng+math+comp;
    }
    @Override//表示覆盖父类方法
    public String toString(){
        return getId()+"\t"+getName()+"\t"+getEng()+"\t"+getMath()+"\t"+getComp()+"\t"+getSum();
    }
    @Override
    public boolean equals(Object x){
        if(this.getClass() !=x.getClass()){
            return false;
        }
        Student b=(Student) x;
        return (this.getId().equals(b.getId()));
    }
    //比较成绩大小,当前对象成绩比参数对象成绩大返回1,相等时返回0,其他返回-1
    public int compare(Student A){
        if(this.getSum()>A.getSum()){
            return 1;
        }
        else if(this.getSum()==A.getSum()){
            return 0;
        }else{
            return -1;
        }
    }
}

接下来声明班级类;

  • 属性包括 班级名称(name)、容量(capacity)、学生(students)、实际人数(size)。
  • 方法包括 构造方法、get方法、set方法、toString方法。

为了能够将Student类对象持久化,也就是存储到磁盘,应使其加入串行化协议,实现Serializable接口。

public class StudentClass implements Serializable{
    private String name;
    static int capacity=40;
    private Student students[];
    private int size;

    public StudentClass(String name,int size){
        this.name=name;
        this.size=size;
        students=new Student[capacity];
    }
    public String getName(){
        return name;
    }
    public int getCapacity(){
        return capacity;
    }
    public Student [] getStudents(){
        return students;
    }
    public int getSize(){
        return size;
    }
    public void setName(String name){
        this.name=name;
    }
    public void setCapacity(int capacity){
        this.capacity=capacity;
    }
    public void setSize(int size){
        if(size>capacity){
            System.out.println("size为"+size+",+不能超过"+capacity);
            return;
        }
        this.size=size;
    }
    public void setStudents(Student...students){
        for(int i=0;i<size;i++){
            this.students[i]=new Student(students[i]);
        }
        this.size=students.length;
    }
    @Override
    public String toString(){
        String s;
        s="班级:"+name+"\t"+"容量"+capacity+"\t"+"实际人数:"+size+"\n\n";
        s=s+"学号"+"\t"+"姓名"+"\t"+"英语"+"\t"+"数学"+"\t"+"计算机"+"\t"+"总成绩\n";
        for(int i=0;i<size;i++){
            s=s+students[i].getId()+"\t"+students[i].getName()+"\t"+students[i].getEng()+"\t"
                    +students[i].getMath()+"\t"+students[i].getComp()+"\t"+students[i].getSum()+"\n";
        }
        return s;
    }
}

接下来编写主函数进行测试;

import java.io.*;
public class Tester {
    public static void main(String args[]){
        Student students[];
        StudentClass aClass=new StudentClass("java 0101",5);
        students=new Student[aClass.getSize()];
        for(int i=0;i<aClass.getSize();i++){
            students[i]=new Student(getAStudent(i+1));
        }
        //StudentClass的setStudents方法形参为可变长参数,传入实参为数组
        aClass.setStudents(students);
        String sss=aClass.toString();
        System.out.println(aClass);
        //将学生信息保存到stu.ser中
        try{
            FileOutputStream fo=new FileOutputStream("stu.ser");
            ObjectOutputStream so=new ObjectOutputStream(fo);
            for(Student s:students){
                so.writeObject(s);
            }
            so.close();
        }catch (Exception e){
            System.out.println(e);
        }
    }
    public static Student getAStudent(int i){
        Student studenti;
        System.out.println("输入第"+i+"个学生的信息:");
        System.out.println("学号:");
        String id=Keyboard.getString();
        System.out.println("姓名:");
        String name=Keyboard.getString();
        System.out.println("英语成绩:");
        int eng=Keyboard.getInteger();
        System.out.println("数学成绩:");
        int math=Keyboard.getInteger();
        System.out.println("计算机成绩:");
        int comp=Keyboard.getInteger();
        studenti=new Student(id,name,eng,math,comp);
        return studenti;
    }
}
输入输出结果://前面省略输入

班级:java 0101	容量40	实际人数:5

学号	姓名	英语	数学	计算机	总成绩
01	李红	88	76	60	224
02	李四	78	67	80	225
03	张三	86	80	75	241
04	麦子	70	68	75	213
05	何为	80	90	78	248

数组的增、删、查、改

在StudentClass类中增加常用方法;

查找

顺序查找,又叫穷举法;其基本思想就是对所存储的数据从第一项开始,依次与所要查找的数据进行比较,直到找到该数据或将全部元素都查找完还没有找到该数据为止。

//顺序查找
    public int find(String id){
        for (int i=0;i<size;i++){
            if(students[i].getId().equals(id))
                return i;
        }
        return -1;
    }

增加

在数组末尾增加一个学生对象。

//增加一个学生
    public boolean add(Student aStudent){
        if(size==capacity) return false;//没有空间,不能增加
        if(find(aStudent.getId())>=0) return false;//此学号已存在,不能增加
        //增加操作
        this.students[size]=new Student(new String(aStudent.getId()),new String(aStudent.getName()),aStudent.getEng(),aStudent.getMath(),aStudent.getComp());
        size++;
        return true;
    }

删除

//删除一个学生
    public boolean del(Student aStudent){
        int pos=find(aStudent.getId());
        if(pos==-1){
            return false;//此学号不存在,不能删除
        }
        //将此学生从数组中删除
        //将数组元素students[pos+1]..students[size-1]依次向前移动一个位置
        //且size的值增加1
        for (int i=pos+1;i<size;i++){
            students[i-1]=students[i];
        }
        size--;
        return true;
    }
    //已知学号,删除一个学生
    public boolean del(String id){
        int pos=find(id);
        if(pos==-1){
            return false;//此学号不存在,不能删除
        }
        //将此学生从数组中删除
        //将数组元素students[pos+1]..students[size-1]依次向前移动一个位置
        //且size的值减1
        for (int i=pos+1;i<size;i++){
            students[i-1]=students[i];
        }
        size--;
        return true;
    }

测试代码

Tester2.java
下面编写测试类对新增加的查找、增加及删除方法进行测试。

import java.io.*;
public class Tester2 {
    public static void main(String args[]){
        Student students[]=new Student[5];
        //从文件stu.ser中读取学生信息
        try{
            FileInputStream fi=new FileInputStream("stu.ser");
            ObjectInputStream si=new ObjectInputStream(fi);
            for(int i=0;i<5;i++){
                students[i]=(Student) si.readObject();
            }
            si.close();
        }catch (Exception e){
            System.out.println(e);
        }

        StudentClass aClass=new StudentClass("java0101",5);
        aClass.setStudents(students);
        System.out.println(aClass);
        //查找
        for(int i=0;i<2;i++){
            System.out.print("输入要查找的学号:");
            String id=Keyboard.getString();
            if(aClass.find(id)<0){
                System.out.println("不存在!");
            }else{
                System.out.println("存在!");
            }
        }
        //增加
        for (int i=0;i<2;i++){
            Student aStudent=getAStudent(6+i);
            if(aClass.add(aStudent)){
                System.out.println("增加成功!");
            }else{
                System.out.println("不能增加!");
            }
        }
        //删除
        for (int i=0;i<2;i++){
            System.out.print("输入要删除的学号");
            String id=Keyboard.getString();
            if(aClass.del(id)){
                System.out.println("已删除!");
            }else{
                System.out.println("不存在!");
            }
        }
        System.out.println(aClass);
    }
    public static Student getAStudent(int i){
        Student studenti;
        System.out.println("输入第"+i+"个学生的信息:");
        System.out.print("学号:");
        String id=Keyboard.getString();
        System.out.print("姓名:");
        String name=Keyboard.getString();
        System.out.print("英语成绩:");
        int eng =Keyboard.getInteger();
        System.out.print("数学成绩:");
        int math =Keyboard.getInteger();
        System.out.print("计算机成绩:");
        int comp =Keyboard.getInteger();
        studenti=new Student(id,name,eng,math,comp);
        return studenti;
    }
}
班级:java0101	容量40	实际人数:5

学号	姓名	英语	数学	计算机	总成绩
01	李红	88	76	60	224
02	李四	78	67	80	225
03	张三	86	80	75	241
04	麦子	70	68	75	213
05	何为	80	90	78	248

输入要查找的学号:02
存在!
输入要查找的学号:06
不存在!
输入第6个学生的信息:
学号:06
姓名:麻子
英语成绩:78
数学成绩:90
计算机成绩:60
增加成功!
输入第7个学生的信息:
学号:07
姓名:小亮
英语成绩:56
数学成绩:95
计算机成绩:89
增加成功!
输入要删除的学号03
已删除!
输入要删除的学号04
已删除!
班级:java0101	容量40	实际人数:5

学号	姓名	英语	数学	计算机	总成绩
01	李红	88	76	60	224
02	李四	78	67	80	225
05	何为	80	90	78	248
06	麻子	78	90	60	228
07	小亮	56	95	89	240

Process finished with exit code 0

另外修改,大家可以自行尝试书写。

对数组元素进行排序

选择排序

选择排序的基本思想是先在未排序序列中选一个最小元素,作为已排序子序列,然后再重复地从未排序的子序列中选取一个最小元素,把它加到已经排序的序列中,作为已排序子序列的最后一个元素,直到把未排序子序列中的元素处理完为止。

//选择排序算法
    public void selectionSort(){
        Student temp;
        for(int i=0;i<size-1;i++){
            for(int j=i+1;j<size;j++){
                if(students[j].compare(students[i])>0){
                    temp=students[i];
                    students[i]=students[j];
                    students[j]=temp;
                }
            }
        }
    }

测试类代码;

import java.io.*;
public class SortTester {
    public static void main(String args[]){
        Student students[]=new Student[5];
        //从文件stu.ser中读出学生信息
        try{
            FileInputStream fi=new FileInputStream("stu.ser");
            ObjectInputStream si=new ObjectInputStream(fi);
            for(int i=0;i<5;i++){
                students[i]=(Student) si.readObject();
            }
            si.close();
        }catch (Exception e){
            System.out.println(e);
        }
        StudentClass aClass=new StudentClass("java0101",5);
        aClass.setStudents(students);
        System.out.println(aClass);
        //选择排序
        aClass.selectionSort();
        System.out.println("选择排序后的结果:\n");
        System.out.println(aClass);
    }
}
班级:java0101	容量40	实际人数:5

学号	姓名	英语	数学	计算机	总成绩
01	李红	88	76	60	224
02	李四	78	67	80	225
03	张三	86	80	75	241
04	麦子	70	68	75	213
05	何为	80	90	78	248

选择排序后的结果:

班级:java0101	容量40	实际人数:5

学号	姓名	英语	数学	计算机	总成绩
05	何为	80	90	78	248
03	张三	86	80	75	241
02	李四	78	67	80	225
01	李红	88	76	60	224
04	麦子	70	68	75	213

插入排序

插入排序是将待排序的数据按一定的规则逐一插入到已排序序列中合适位置处,直到将全部数据都插入为止。插入的规则不同,便形成了不同的插入排序算法。其中,算法最简单的为直接插入排序算法。

直接插入排序方法先以未排序元素的第一个元素作为已排序子序列,然后从原来的第二个元素起,将各个元素逐一插入到已排序子序列中合适的位置,直到把所有的元素都插入为止。

//插入排序算法
public void insertSort(){
    Student temp;
    for(int i=1;i<size;i++){
        temp=students[i];
        int j=i-1;
        while(j>-1 && temp.compare(students[j])>0){
            students[j+1]=students[j];
            j--;
        }
        students[j+1]=temp;
    }
}

测试代码可以参照选择排序测试代码来写。

查找算法

前面我们已经看到了顺序查找算法非常简单,但在大数据量中进行查找时,效率较低。在未排序的数组中进行查找,只能使用顺序查找方法。对于已排序的数组,我们可以采用二分查找,提高查找效率。

public class SortedIntArray {
    private int capacity;
    private Integer[] rep;
    private int size;
    //构造方法
    public SortedIntArray(int n){
        capacity=n;
        rep=new Integer[capacity];
    }
    //无参的构造方法
    public SortedIntArray(){
        this(100);
    }
    //二分查找
    private int search(int i, int lower, int upper){
        int index=lower;
        if(upper>=lower){
            int mid=(upper+lower)/2;
            int cur=rep[mid].intValue();
            if(cur==i){
                index=mid;
            }else if(cur<i){
                index=search(i,mid+1,upper);
            }else{
                index=search(i,lower,mid-1);
            }
        }
        return index;
    }
    public int search(int i){
        return search(i,0,size-1);
    }
    //在数组中插入一个元素
    public SortedIntArray insert(int i){
        int index=search(i);
        for (int j=size;j>index;--j){
            rep[j]=rep[j-1];
        }
        rep[index]=i;
        ++size;
        return this;
    }
    //在数组中删除一个元素。只删除查到的第一个元素
    public SortedIntArray remove(int i){
        int index=search(i);
        if(rep[index]==i){
            --size;
            for(int j=index;j<size;++j){
                rep[j]=rep[j+1];
            }
        }
        return this;
    }
    @Override
    public String toString(){
        String toReturn="";
        for(int i=0;i<size;++i){
            toReturn+=rep[i].toString()+", ";
        }
        return toReturn;
    }
    //主方法
    static public void main(String[] args){
        SortedIntArray anArray=new SortedIntArray();
        anArray.insert(4).insert(9).insert(7).insert(1).insert(3).insert(2).insert(8).insert(7);
        System.out.println(anArray);
        anArray.remove(1).remove(8).remove(7).remove(3);
        System.out.println(anArray);
    }
}
输出结果:
1, 2, 3, 4, 7, 7, 8, 9, 
2, 4, 7, 9, 

二维数组

二维数组常用来表示二维表,即以行(rows)及列(columns)的方式来表示数据;

二维数组的声明方式;

type arrayName[][];
type [][] arrayName;
public class TableTester {
    public static void main(String args[]){
        int myTable[][]={{23,45,66,34,21,67,79},
                {45,15,19,46,98,63,88},
                {98,82,65,90,20,15,25},
                {55,44,55,77,22,44,33}
        };
        //使用增强for循环显示二维表;
        for(int row[]:myTable){
            for(int col:row){
                System.out.print(col+" ");
            }
            System.out.println();
        }
        //计算累加和最大的行号
        int sum,max,maxRow=0;
        max=0;
        for(int row=0;row<4;row++){
            sum=0;
            for(int col=0;col<7;col++){
                sum+=myTable[row][col];
            }
            if(sum>max){
                max=sum;
                maxRow=row;
            }
        }
        System.out.println("Row "+maxRow+" has the highest sum of "+max);
    }
}
输出结果;
23 45 66 34 21 67 79 
45 15 19 46 98 63 88 
98 82 65 90 20 15 25 
55 44 55 77 22 44 33 
Row 2 has the highest sum of 395
  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

他是只猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值