排序算法类的模板
主要用于定义辅助函数:
1、less()方法对元素进行比较
private static boolean less(Comparable v, Comparable w){
return v.compareTo(w) < 0;
}
2、exch()方法将元素交换位置
private static void exch(Comparable[] a, int i, int j){
Comparable t = a[i];
a[j] = a[i];
a[i] = t;
}
3、show()方法打印字符数组的内容
private static void show(Comparable[] a){
for(int i = 0; i < a.length; i++){
StdOut.print(a[i] + " ");
}
StdOut.println();
}
comparable接口和compareTo()方法
public class XXX implements Comparable<XXX>{
public int compareTo(XXX that){
...
}
}
compareTo()方法中定义目标类型对象的自然次序:
v.compareTo(w)有如下三种可能:
①v < w, 返回负整数
②v = w, 返回0
③v > w, 返回正整数
选择排序
public static void SelectionSort(Comparable[] a){
//将a[]按升序排列
int N = a.length;
for(int i = 0; i < N; i++){
int min = i; // 记录第i小元素位置,即要交换的位置
for(int j = i; j < N; j++){
if(less(a[j], a[min])) min = j; // 逐个比较
}
exch(a, i, min);
}
}
1、基本思想
①找到数组中最小的元素,并与数组的第一个元素交换位置(如果第一个元素就是最小元素那么就和自己交换)
②在剩下的元素中找到最小元素,并与数组的第二个元素交换位置
③循环反复,直至整个数组排序
2、算法特点
①运行时间和输入无关。无论数组是否已经排序,其运行时间不变。
②数据移动最少。交换次数和数组的大小是线性关系。其余排序算法都不具备这个特征。
③索引左侧的元素都是有序的,且不会访问索引左侧的元素。
3、算法分析
时间复杂度:O()
原址排序
插入排序
public static void InsertionSort(Comparable[] a){
int N = a.length;
for(int i = 1; i < N; i++){
for(int j = 1; j > 0 && less(a[j], a[j-1]); j--){
exch(a, j, j-1);
}
}
}
1、基本思想
为了给要插入的元素腾出空间,需要将其余所有元素在插入之前都向右移动一位。
2、算法特点
①时间取决于输入中元素的初始顺序,适用于部分有序的数组和小规模数组
②不会访问索引的右侧元素,当前索引左边的所有元素都是有序的
3、算法分析
时间复杂度:O()
原址排序
希尔排序
public static void ShellSort(Comparable[] a){
int N = a.length;
int h = 1;
while(h < N/3) h = 3 * h + 1;
while(h >= 1){
for(int i = h; i < N; i++){
for(int j = i; j >= h && less(a[j], a[j-1]); j -= h) exch(a, j, j-h)
}
h = h/3;
}
}
1、基本思想
使数组中任意间隔为h的元素都是有序的。交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。
2、特点
①权衡了子数组的规模和有序性
②无法准确描述对于乱序数组的性能特征,但希尔排序比插入排序和选择排序要快得多