排序是非常重要的,在计算机科学中科学中应用十分广泛,这篇博客是对三种比较简单的排序算法:冒泡排序、选择排序、插入排序的总结。
冒泡排序
冒泡排序,顾名思义就是像冒泡一样对数据进行排序,从最底下冒泡,将最大的数据冒泡到最上面,这样最上面的数据就是排好序的了,接下来是对最上面的下面位置排序,以此类推,直到最下面的数据也排好序。所以,如果有 nElems 个数据的话,那么就需要排序 nElems - 1 个数据,最后一个自然也就排好序了。
基本思路是: 利用两个循环,外层循环控制要排序多少个数据,从最后一个数据开始排序,所以最后一个数据排完序之后将是最大的(也就是上面所说的最上面的数据),内层循环从下标为 0 的数据开始,与后一个数据比较,如果后一个数据小于前一个数据,则让它们交换位置,然后内层循环的下标自增,继续与后一个数据比较,重复上面的操作,直到到达外层循环的下标 - 1。下面的代码的实现函数:
public void bubbleSort() {
for(int k = nElems - 1; k > 0; k--)
for(int j = 0; j < k; j++)
if(a[j] > a[j + 1])
swap(j, j + 1);
}
private void swap(int one, int two) {
long temp = a[one];
a[one] = a[two];
a[two] = temp;
}
完整的 BubbleSortApp.java 代码:
class BubbleArr {
private long[] a;
private int nElems;
public BubbleArr(int max) {
a = new long[max];
nElems = 0;
}
public void insert(long value) {
a[nElems] = value;
nElems++;
}
public void display() {
for(int i = 0; i < nElems; i++)
System.out.print(a[i] + " ");
System.out.println("");
}
public void bubbleSort() {
for(int k = nElems - 1; k > 0; k--)
for(int j = 0; j < k; j++)
if(a[j] > a[j + 1])
swap(j, j + 1);
}
private void swap(int one, int two) {
long temp = a[one];
a[one] = a[two];
a[two] = temp;
}
}
public class BubbleSortApp {
public static void main(String[] args) {
int max = 100;
BubbleArr bArr = new BubbleArr(max);
bArr.insert(99);
bArr.insert(88);
bArr.insert(33);
bArr.insert(44);
bArr.insert(77);
bArr.insert(66);
bArr.insert(11);
bArr.insert(22);
bArr.insert(55);
bArr.insert(00);
System.out.println("Before sort:");
bArr.display();
bArr.bubbleSort();
System.out.println("After sort:");
bArr.display();
}
}
运行结果:
Before sort:
99 88 33 44 77 66 11 22 55 0
After sort:
0 11 22 33 44 55 66 77 88 99
选择排序
选择排序的思路是从最左边开始,将左边的数据先排好序,依次向右,最后将最右边的元素也排好序,这一过程是利用两个循环和一个保存每次最小数据下标的 min 变量。外层循环从下标 0 开始,直到 nElems - 1, 表示从左到右排序。min 的初值为外层循环的下标,表示先假设现在下标的数据最小,内层循环从外层循环的下标 + 1 开始,到 nElems - 1结束,每一个数据依次和下标为 min 的数据比较,如果小于下标为 min 的数据,则将 min 更新为内层循环目前的下标。最后两个循环运行完后,数据也就排好序了。下面是函数:
public void selectSort() {
int min;
for(int i = 0; i < nElems; i++) {
min = i;
for(int j = i + 1; j < nElems; j++)
if(a[min] > a[j])
min = j;
swap(i, min);
}
}
private void swap(int one, int two) {
long temp = a[one];
a[one] = a[two];
a[two] = temp;
}
下面是完整 SelectSortApp.java 代码:
class SelectArr {
private long[] a;
private int nElems;
public SelectArr(int max) {
a = new long[max];
nElems = 0;
}
public void insert(long value) {
a[nElems] = value;
nElems++;
}
public void display() {
for(int i = 0; i < nElems; i++)
System.out.print(a[i] + " ");
System.out.println("");
}
public void selectSort() {
int min;
for(int i = 0; i < nElems; i++) {
min = i;
for(int j = i + 1; j < nElems; j++)
if(a[min] > a[j])
min = j;
swap(i, min);
}
}
private void swap(int one, int two) {
long temp = a[one];
a[one] = a[two];
a[two] = temp;
}
}
public class SelectSortApp {
public static void main(String[] args) {
int max = 100;
SelectArr selectArr;
selectArr = new SelectArr(max);
selectArr.insert(33);
selectArr.insert(77);
selectArr.insert(88);
selectArr.insert(66);
selectArr.insert(22);
selectArr.insert(11);
selectArr.insert(99);
selectArr.insert(55);
selectArr.insert(00);
selectArr.insert(44);
System.out.println("Before sort:");
selectArr.display();
System.out.println("After sort:");
selectArr.selectSort();
selectArr.display();
}
}
运行结果:
Before sort:
33 77 88 66 22 11 99 55 0 44
After sort:
0 11 22 33 44 55 66 77 88 99
插入排序
插入排序的特点是左边的数据都是排好序的,右边的数据(从下标为 1 开始)保存在临时变量 temp 中,需要和左边的数据(左边数据是从右边数据的下标 - 1 开始)比较大小,如果小于左边的数据,则左边的数据右移覆盖到右边位置中,然后左边数据的下标减 1, 再和 temp 比较,如果小于左边的数据,则左边的数据右移覆盖到右边位置中,直到 temp 大于左边的数据或者到达第一个位置,停止,将 temp 放到该下标对应的位置。思路是利用两个循环和一个保存着 右边数据的临时变量 temp。下面是函数代码:
// 插入排序的函数
public void insertSort() {
long temp;
for(int outer = 1; outer < nElems; outer++) {
int inner = outer;
temp = a[outer];
while(inner - 1 >= 0 && a[inner - 1] > temp) {
a[inner] = a[inner - 1];
inner--;
}
a[inner] = temp;
}
}
完整的 InsertSortApp.java 代码:
class InsertArr {
private long[] a;
private int nElems;
public InsertArr(int max) {
a = new long[max];
nElems = 0;
}
public void insert(long value) {
a[nElems] = value;
nElems++;
}
public void display() {
for(int i = 0; i < nElems; i++)
System.out.print(a[i] + " ");
System.out.println("");
}
// 插入排序的函数
public void insertSort() {
long temp;
for(int outer = 1; outer < nElems; outer++) {
int inner = outer;
temp = a[outer];
while(inner - 1 >= 0 && a[inner - 1] > temp) {
a[inner] = a[inner - 1];
inner--;
}
a[inner] = temp;
}
}
}
public class InsertSortApp {
public static void main(String[] args) {
int max = 100;
InsertArr insertArr;
insertArr = new InsertArr(max);
insertArr.insert(99);
insertArr.insert(66);
insertArr.insert(88);
insertArr.insert(33);
insertArr.insert(22);
insertArr.insert(55);
insertArr.insert(66);
insertArr.insert(77);
insertArr.insert(11);
insertArr.insert(00);
System.out.println("Before sort:");
insertArr.display();
System.out.println("After sort:");
insertArr.insertSort();
insertArr.display();
}
}
运行结果:
Before sort:
99 66 88 33 22 55 66 77 11 0
After sort:
0 11 22 33 55 66 66 77 88 99
正常情况下,一般比较的都是对象,下面是对象排序,使用插入排序的代码
class Person {
private String lastName;
private String firstName;
private int age;
public Person(String last, String first, int a) {
lastName = last;
firstName = first;
age = a;
}
public void displayPerson() {
System.out.print(" Last name: " + lastName);
System.out.print(" First name: " + firstName);
System.out.println(", Age: " + age);
}
public String getLast() {
return lastName;
}
}
class ArrayInOb {
private Person[] a;
private int nElems;
public ArrayInOb(int max) {
a = new Person[max];
nElems = 0;
}
public void insert(String last, String first, int age) {
a[nElems] = new Person(last, first, age);
nElems++;
}
public void display() {
for(int i = 0; i < nElems; i++)
a[i].displayPerson();
}
public void insertionSort() {
int in, out;
for(out = 1; out < nElems; out++) {
Person temp = a[out];
in = out;
while(in - 1 >= 0 && a[in - 1].getLast().compareTo(temp.getLast()) > 0) {
a[in] = a[in - 1];
in--;
}
a[in] = temp;
}
}
}
class ObjectSortApp {
public static void main(String[] args) {
int max = 100;
ArrayInOb arr;
arr = new ArrayInOb(max);
arr.insert("Evans", "Patty", 24);
arr.insert("Smith", "Doc", 59);
arr.insert("Smith", "Lorraine", 37);
arr.insert("Smith", "Paul", 37);
arr.insert("Yee", "Tom", 43);
arr.insert("Hashimoto", "Sato", 21);
arr.insert("Stimson", "Henry", 29);
arr.insert("Velasquez", "Jose", 72);
arr.insert("Vang", "Minh", 22);
arr.insert("Creswell", "Lucinda", 18);
System.out.println("Before sorting: ");
arr.display();
arr.insertionSort();
System.out.println("After sorting: ");
arr.display();
}
}
运行结果:
Before sorting:
Last name: Evans First name: Patty, Age: 24
Last name: Smith First name: Doc, Age: 59
Last name: Smith First name: Lorraine, Age: 37
Last name: Smith First name: Paul, Age: 37
Last name: Yee First name: Tom, Age: 43
Last name: Hashimoto First name: Sato, Age: 21
Last name: Stimson First name: Henry, Age: 29
Last name: Velasquez First name: Jose, Age: 72
Last name: Vang First name: Minh, Age: 22
Last name: Creswell First name: Lucinda, Age: 18
After sorting:
Last name: Creswell First name: Lucinda, Age: 18
Last name: Evans First name: Patty, Age: 24
Last name: Hashimoto First name: Sato, Age: 21
Last name: Smith First name: Doc, Age: 59
Last name: Smith First name: Lorraine, Age: 37
Last name: Smith First name: Paul, Age: 37
Last name: Stimson First name: Henry, Age: 29
Last name: Vang First name: Minh, Age: 22
Last name: Velasquez First name: Jose, Age: 72
Last name: Yee First name: Tom, Age: 43
到此,三种简单排序已经说完了,其中插入排序是最复杂的,冒泡排序最简单。在大多数情况下,假设当数据量比较小或者基本上有序时,插入排序是三种中最好的选择。当数据量很少时,并且比较数据比交换数据更加省时的时候,可以选择用选择排序。