**
利用compareTo方法进行字符串比较排序
**
排序算法
创建学生类,包含两个属性:姓名和学号。给出构造函数,输入参数为学生学号,限制为整型类型,范围在[0,999]之间。姓名由3位字符组成,由该学生的学号采用线性映射的方式获取得到,线性映射函数为(见表1)
要求输入一个范围在[0,999]之间的整数,通过随机产生的方式生成n个满足上述要求的学生对象。并按照以下三种不同的排序方式完成所有对象的顺序输出:
(a) 按照学号的大小顺序完成顺序输出,即给出两个学生s和t,对应学号分别为:m和n,若满足m>n,则要求先输出t后输出s;
(b) 按照学生对应学号的十位、个位、百位的大小优先顺序完成顺序输出,即
给出两个学生s和t,对应学号分别为:m和n,若m的十位数大于n的十位数,则先输出m,若两者相等,再比较m和n的个位数,相应小的对象先输出;若两位学生的十位、个位均相等,最后比较两个学号的百位数,相应小的先输出。如两个学生的学号分别为:045和418,由于第二个学生的学号十位数1小于第一个学生的十位数4,需要先输出第二个学生对象;
(c ) 按照学生对应学号的个位、百位、十位的大小优先顺序完成顺序输出,即给出两个学生s和t,对应学号分别为:m和n,若m的个位数大于n的个位数,则先输出m,若两者相等,再比较m和n的百位数,相应小的对象先输出;若两位学生的个位、百位均相等,最后比较两个学号的十位数,相应小的先输出。如两个学生的学号分别为:248和418,由于两位学生的个位数相等,需要再比较两个学号的百位数,而需要先输出第一个学生对象。
程序源代码如下:
package sunhao;
import java.util.Scanner;
abstract class CompareTo{ //定义一个抽象类和抽象方法
abstract public void compare(String [] str); //该方法用于比较字符串的大小
}
class Compare extends CompareTo{ //继承上面抽象类并重写父类的abstract方法
public void compare(String [] m){ //三位数学号的字符串作为参数传入
for(int i=0;i<m.length;i++) {
for(int j=0;j<i;j++) {
String str=String.valueOf(m[i]);
String str1=String.valueOf(m[j]);
int w=str.compareTo(str1); //等长字符串比较
if(w<0) { //按从小到大排序
String temp=m[i];
m[i]=m[j];
m[j]=temp;
}
}
}
}
}
class Compare1 extends CompareTo{ //按十个百位进行比较
public void compare(String [] m){
String [] n=new String[m.length];
for(int r=0;r<m.length;r++) {
int sno=Integer.parseInt(m[r]);
int a=sno/100;
int b=(sno%100)/10;
int c=sno%10;
int snoo=b*100+c*10+a; //将原来的学号变成十个百位顺序
n[r]=String.format("%03d", snoo);
}
for(int i=0;i<m.length;i++) {
for(int j=0;j<i;j++) {
String str=String.valueOf(n[i]);
String str1=String.valueOf(n[j]);
int w=str.compareTo(str1);
if(w<0) {
String temp=n[i];
n[i]=n[j];
n[j]=temp;
}
}
}
for(int t=0;t<m.length;t++) {
int sno=Integer.parseInt(n[t]);
int a=sno/100;
int b=(sno%100)/10;
int c=sno%10;
int snoo=c*100+a*10+b; //比较完再将学号恢复
m[t]=String.format("%03d", snoo);
}
}
}
class Compare2 extends CompareTo{ 按个百十位进行比较
public void compare(String [] m){
String [] n=new String[m.length];
for(int r=0;r<m.length;r++) {
int sno=Integer.parseInt(m[r]);
int a=sno/100;
int b=(sno%100)/10;
int c=sno%10;
int snoo=c*100+a*10+b;
n[r]=String.format("%03d", snoo);
}
for(int i=0;i<m.length;i++) {
for(int j=0;j<i;j++) {
String str=String.valueOf(n[i]);
String str1=String.valueOf(n[j]);
int w=str.compareTo(str1);
if(w<0) {
String temp=n[i];
n[i]=n[j];
n[j]=temp;
}
}
}
for(int t=0;t<m.length;t++) {
m[t]=n[t];
int sno=Integer.parseInt(m[t]);
int a=sno/100;
int b=(sno%100)/10;
int c=sno%10;
int snoo=b*100+c*10+a;
m[t]=String.format("%03d", snoo);
}
}
}
class Repeat{ //随机生成不重复的学号
public void repeat(int [] sno){
int i=0;
while(true) { //去除重复学号
boolean flag=true;
int no=(int)(Math.random()*1000); //随机生成0-999之间的数
for(int j=0;j<sno.length;j++) {
if(sno[j]==no) {
flag=false;
break;
}
}
if(flag) {
sno[i]=no;
i++;
}
if(i>sno.length-1) {
break;
}
}
}
}
class Student{ //定义一个学生类
String sname; //学生的姓名
int sno; //学生的学号
Student(String ssno){ //构造函数
int sno=Integer.parseInt(ssno);
String [] t= {"A","B","C","D","E","F","G","H","I","J"}; //定义一个字符串数组
int a=sno/100; //将三位数学号拆开(a代表百位)
int b=(sno%100)/10; //b代表十位
int c=sno%10; //c代表个位
System.out.println(" "+t[a]+t[b]+t[c]); //根据学生学号与姓名的映射关系,输出该学号对应的学生姓名
}
}
public class Test{ //主类
public static void main(String args[]) {
Scanner sc=new Scanner(System.in); //Scanner类用于用户的输入
System.out.println("请输入学生个数:");
try{ //try用于捕获用户输入时的异常(如非数字),并来提示用户重新输入
int number=sc.nextInt(); //输入学生的个数
if(number>=0&&number<=999) { //学生的个数应为0-999之间
int [] sno=new int[number]; //为这些学生创建一个学号数组,存放学号(学号唯一)
Repeat re=new Repeat(); //对象的声明与实例化
re.repeat(sno); //调用Repeat类中的repeat方法
String [] ssno=new String[number]; //存放三位数学号
System.out.println("----------------------------------------------------------");
System.out.println("(a)按照学号的大小顺序完成顺序输出:");
System.out.println("序号 "+"学号 "+"姓名");
for(int k=0;k<sno.length;k++) { //将随机生成的学号全部变成三位数的字符串
ssno[k]=String.format("%03d", sno[k]);//0表示前面补0;digit表示要保留的数字位数;d表示参数为正数类型
}
Compare com=new Compare();
com.compare(ssno); //按顺序比较
for(int r=0;r<sno.length;r++) { //输出结果
System.out.print(r+1); //序号
System.out.print(" "+ssno[r]); //学号
Student stu=new Student(ssno[r]); //姓名
}
System.out.println("----------------------------------------------------------");
System.out.println("(b)按照学生对应学号的十位、个位、百位的大小优先顺序完成顺序输出:");
System.out.println("序号 "+"学号 "+"姓名");
for(int k=0;k<sno.length;k++) {
ssno[k]=String.format("%03d", sno[k]);
}
Compare1 com1=new Compare1();
com1.compare(ssno);
for(int r=0;r<sno.length;r++) {
System.out.print(r+1);
System.out.print(" "+ssno[r]);
Student stu1=new Student(ssno[r]);
}
System.out.println("----------------------------------------------------------");
System.out.println("(c)按照学生对应学号的个位、百位、十位的大小优先顺序完成顺序输出:");
System.out.println("序号 "+"学号 "+"姓名");
for(int k=0;k<sno.length;k++) {
ssno[k]=String.format("%03d", sno[k]);
}
Compare2 com2=new Compare2();
com2.compare(ssno);
for(int r=0;r<sno.length;r++) {
System.out.print(r+1);
System.out.print(" "+ssno[r]);
Student stu2=new Student(ssno[r]);
}
}else { //当输入不在0-999之间进行提醒
System.out.println("请输入0-999之间的数字!(包括0和999)");
}
}catch(Exception e) { //捕获异常并提醒
System.out.println("亲,您输入的不是数字。请输入0-999之间的数字!(包括0和999)");
}
}
}
运行结果:
请输入学生个数:
6
----------------------------------------------------------
(a)按照学号的大小顺序完成顺序输出:
序号 学号 姓名
1 117 BBH
2 140 BEA
3 222 CCC
4 726 HCG
5 777 HHH
6 807 IAH
----------------------------------------------------------
(b)按照学生对应学号的十位、个位、百位的大小优先顺序完成顺序输出:
序号 学号 姓名
1 807 IAH
2 117 BBH
3 222 CCC
4 726 HCG
5 140 BEA
6 777 HHH
----------------------------------------------------------
(c)按照学生对应学号的个位、百位、十位的大小优先顺序完成顺序输出:
序号 学号 姓名
1 140 BEA
2 222 CCC
3 726 HCG
4 117 BBH
5 777 HHH
6 807 IAH
小结:
(1)Math.random()方法的使用:
Math.random()会随机生成[0,1)之间的随机数,一般情况下会在Math.Random()上乘以一个数,如乘以n。这样我们就可以生成[0,n)之间的随机数。如果用int进行取整的话,那么我们就可以产生[0,n)之间的正整数。包含0,不包含n。
(2)Java中的compareTo方法,返回比较前后的两个字符串的ASCII的差值。
a.等长字符串比较:参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的ASCII差值。
a = “abc”;
b = “bac”;
a.compareTo(b)//-1
a = “abc”;
b = “acb”;
a.compareTo(b)//-1
b.不等长字符串比较:
两个字符串首字母不同,则该方法返回首字母的ASCII的差值
a = “abc”;
b = “bcdfg”;
a.compareTo(b)//-1
参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的ASCII差值
a = “abc”;
b = “abedfg”;
a.compareTo(b)//-2
两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值
a = “abcde”;
b = “abcd”;
a.compareTo(b)//1