对数组x进行排序
一,冒泡排序Bubble Sort
不要用冒泡排序,它非常没效率。
每趟排序遵循这样的规则:
1,从最左边开始比较相邻两个元素。
2,如果左边元素小,就交换两个元素的位置。
3,向右移动一个位置,比较相邻两个元素的大小。
这样一直比较到数组最右边。使得最大的元素已经移动到了最右边。
再从左往右开始第二趟排序、第三趟。。。
直到排序完成。
每趟排序需要N-1、N-2、N-3。。。1次比较。总共N(N-1)/2次
交换和比较次数都和N^2成正比,最坏运行时间和平均运行时间都是O(N^2)
二,选择排序Selection Sort
在待排序的数组中,每次选出最小或最大的元素。
用pos来标记最小元素的位置。最初pos指向x[i]。遍历x[i+1]到最后一个元素,每次都将x[pos]和它们进行比较,如果有更小的,pos就指向新的最小值的位置。这样最终找到最小值x[pos],将x[pos]和x[i]交换位置。
public static void selectionSort(int[] x) {
// Make x [0 . . . i] sorted and <= x [i + 1] . . .x [x.length –1]:
for (int i = 0; i < x.length - 1; i++) {
int pos = i;
for (int k = i + 1; k < x.length; k++)
if (x[k] < x[pos])
pos = k;
swap(x, i, pos);
} // for i
}
选择排序比冒泡要快。
三,插入排序
从数组x左边开始,x[1]和x[0]比较,看插入到x[0]之前还是之后。
x[2]和已经排好序的x[0]、x[1]比较,找到x[2]的插入位置。
......
x[i]和已经排好序的x[0]、x[1]、x[2]...x[i-1]比较,找到x[i]的插入位置。
如果用off表示开始插入排序的索引值,用len表示将被排序的元素数量,上述过程可表示为外循环
for(int i=off;i<off+len;i++){
x[i]和已经排好序的x[off]、x[off+1]、...x[i-2]、x[i-1]比较,找到x[i]的插入位置。
}
for循环中的比较过程可用一个内循环表示。x这个内循环从右往左进行,x[i]先和x[i-1]比较,如果x[i]小,则交换x[i]和x[i-1]的位置,x[i]向左移动,再和x[i-2]比较......直到x[i]不小于某元素为止。这样实现了从小到大的排序
for(int j=i;j>off&&x[j]<x[j-1];j--){
swap(x,j,j-1);
}
完整的代码就是:
public static void insertSort(int[] x, int off, int len) {
for (int i = off; i < off + len; i++) {
for (int j = i; j > off && x[j] < x[j - 1]; j--) {
swap(x, j, j - 1);
}
}
}
private static void swap(int x[], int a, int b) {
int tmp = x[a];
x[a] = x[b];
x[b] = tmp;
}
插入排序的最坏时间和平均时间是O(n^2),最坏循环次数是n(n-1)/2,但是平均循环次数是n(n-1)/4。插入排序的速度比冒泡要快一倍,比选择要稍快。
在Java集合框架中,插入排序用于元素个数小于7的子数组排序。
上述程序用于比较整数数组。可以改写成对对象进行排序,用comparator比较。
public static void selectionSort (T [ ] x, Comparator comp){
// Make x [0 . . . i] sorted and <= x [i + 1] . . .x [x.length –1]:
for (int i = 0; i < x.length –1; i++){
int pos = i;
for (int k = i + 1; k < x.length; k++)
if (comp.compare (x [k], x [pos]) < 0)
pos = k;
swap (x, i, pos);
} // for i
}