1,排序依据的规则:
一般来说,排序的目的是将一些数据依照某种特定的要求或原则排成递增或递减的顺序。而排序的过程中需要对键进行比较,主要依据以下三个规则:
1,键为数值类型(整数,实数)时:以数值大小为依据;
2,键为非中文的字符串类型时:ASCII码;
3,键为中文字符串时:GB简体码,BIG5繁体码,电信码.....
而用来比较两者大小时,在java中,我们可以使用Comparator 接口。其中提供的方法:
2,排序方法:
若按是否涉及数据的内外存交换来分类,可以分为:
内部排序(整个文件都放在内存中,排序时不涉及内外存交换);
外部排序(涉及数据的内外存交换)
内存排序又分为:
插入排序,选择排序,交换排序,归并排序,分配排序(基于地址)
3,插入排序
每次将一条待排序的记录按其键的大小插入到前面已经排好序的子序列中的适当位置。
1),直接插入排序:
1,比较数组的前两个数据并排序;
2,将第三个未排序的数据R[i]与已排好序的子序列R[j](j = 0, 1)比较,并插入合适位置;
3,重复步骤2,直到最后一个数据被插入合适位置。
//一维数组排序(从小到大)
package Arry;
public class Sorting {
public static void straight_Insertion_Sort(int[] number){ //直接插入排序
int temp;
for(int i = 1;i < number.length;i++){ //未排序的数据
temp = number[i];
int j;
for(j = i-1;j >= 0;j--){ //前面已排好序的子序列
if(number[j] > temp){
number[j+1] = number[j];
}
else{
break;
}
}
number[j+1] = temp;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 对学号进行排序(直接插入排序法)
*/
int number[] = {1003, 2564, 4783, 2354, 8512, 1052};
straight_Insertion_Sort(number);
System.out.println("学号排序结果:");
for(int i = 0;i < number.length;i++){
System.out.print(number[i] + " ");
}
}
}
2),二分插入排序:
二分插入排序是直接插入排序的一种优化。当数据较多时,二分插入排序的效率会远大于直接插入排序。
与直接插入排序相同的是,二分法也将数组分成左右两个部分,左边是经过排序后的子序列,右边是待排序的数据。而与其不同的是,待排序的数据会先与有序子序列的中间值R[middle]相比较。也就是说,二分排序法的排序步骤是这样的:
1,当待排序数据R[i]小于子序列R[j]时,先将该数据保存起来:
int temp = R[i];
2,先找到子序列的最左值,最右值的位置:
left = 0; //最左边从第一个元素开始
right = i-1; //最右边位,从待排序数据的前一位开始
3,当最左值不大于最右值时,找到中间值的位置:
middle = (left + right)/2;
4,将中间值与待排序值进行比较,如果相等直接推出循环;如果小于中间值,就在中间值左边的子序列中重复步骤2;如果大于中间值,就在其右边的子序列中重复步骤2。
5,当找到插入位置left后,将left开始向右的所有数据向后移动一位。
//一维数组排序(从小到大)
package Arry;
public class Sorting {
public static void binary_Sort(int[] credit){ //二分插入排序
for(int i = 1;i < credit.length;i++){ //未排序的子序列
if(credit[i] < credit[i-1]){
int temp = credit[i];
//查找插入位置
int left = 0;
int middle = 0;
int right = i-1;
while(left <= right){
middle = (left + right)/2;
if(temp == credit[middle]){
left = middle;
break;
}
else if(temp < credit[middle]){
right = middle - 1;
}
else{
left = middle + 1;
}
}
//待插入位置是left,从left开始,元素统一右移
for(int j = i-1; j >= left;j--){
credit[j+1] = credit[j];
}
credit[left] = temp;
}
}
}
public static void main(String[] args) {
/*
* 对学分进行排序(二分插入排序法)
*/
int credit[] = {5, 7, 9, 3, 1};
binary_Sort(credit);
System.out.println("学分排序结果:");
for(int i = 0;i < credit.length;i++){
System.out.print(credit[i] + " ");
}
}
}
注意:二分排序法的比较次数与待排序序列的初始状态无关,只取决于记录的个数。
3),希尔排序
希尔排序又称缩小增量排序,也是插入排序的一种,并且是前两种插入排序的又一改进。其主要思想为,将一无序序列分割成数个无序子序列,并针对每个子序列分别进行插入排序。然而很遗憾的是,希尔排序并不稳定。
步骤:
1,
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中。
例:
序列:39 80 76 41 13 29 50 78 30 11 100 7 41 86
d1 = 5 (取第一个增量为5)
得到的子序列为:{39, 29, 100},{80, 50, 7},{76, 78, 41},{41, 30, 86},{13, 11}
2,进行第一趟排序,得到结果:
29 7 41 30 11 39 50 76 41 13 100 80 78 86
3,取第二个小于d1的增量d2,重复步骤1,2
d2 = 3
4,取最后一个增量d3,重复步骤1,2
d3 = 1
//一维数组排序(从小到大)
package Arry;
public class Sorting {
public static void shell_Sort(String[] name_01){ //希尔排序
int d = 1; //增量
while(d < name_01.length){
d = d*3 + 1;
}
for(int i = 1;i < name_01.length;i++){
for(int j = i;j >= d;j -= d){
String temp = name_01[j];
int com = temp.compareTo(name_01[j-d]);
if(com < 0){
name_01[j-d+1] = name_01[j-d];
}
else{
break;
}
name_01[j-d+1] = temp;
}
}
}
public static void main(String[] args) {
/*
* 对姓名(英文)进行排序(希尔排序法)
*/
String name_01[] = {"zhangsan","lisi","wangwu","zhaoliu"};
shell_Sort(name_01);
System.out.println("姓名(英文)排序结果:");
for(int i = 0;i < name_01.length;i++){
System.out.print(name_01[i] + " ");
}
System.out.println();
}
}
4,交换排序
交换排序的基本思想是,两两比较待排序记录的键,发现两个记录的次序相反时进行交换,直到没有反序的记录为止。
1),冒泡排序
冒泡排序是一种应用极多的排序方法,也是一种很典型的交换排序。由于每一趟比较时,小的数据都会像气泡一样慢慢上移,所以给这个算法起了这个形象的名字。那么,它的具体步骤是什么呢?
1,从整个数列的第一对数据开始比较,如果小的数据在后面,则交换俩个数据的位置;
2,重复步骤1,直到交换进行到最后一对数据;
3,此时,最后一个数就是当前数列中最大的数,记录下这个数的位置;
4,从当前数列的第一对数据开始,重新执行步骤1,除了最后一个数据。
5,持续重复步骤4,直到没有数据需要比较为止。