一旦建立了一个数据库之后,就可能需要根据某些需求对数据进行不同方式的排序。
计算机和人类的的区别就是计算机不能向人这样通览所有的数据,它只能根据计算机的“比较”操作原理,在同一时间对两个队员进行比较。在人类看来很简单的事情,计算机的算法却不能看到全景,因此它只能一步一步的解决具体问题和遵循一些简单的规则。
下面说的几个算法都包括下面的两个步骤,这两个步骤循环执行,知道全部数据有效为止:
1. 比较两个数据项
2. 交换两个数据项,或者复制其中的一个
冒泡排序:
冒泡排序的算法运行起来非常的慢,但是在概念上它是排序算法中最简单的。
冒泡排序咋执行的过程中,基本要遵循以下的规则:
1. 比较俩个数据
2. 如果左边的数据大于右边的数据,则两个数据交换位置
3. 向右移动一个位置,比较下面两个队员
下面是相关的代码:
public void bubbleSort() {
int out, in;
for (out = nElems-1; out>1; out--) {
for (in=0; in<out; in++)
if (a[in] > a[in+1])
swap(in, in+1);
}
}
这个算法是要将最小数据放在数组的最开始,并将最大的数据项放在数组的最后。
冒泡的效率:
一般来说,数组中有N个数据项,则第一趟排序中有N-1次比较,第二趟中有N-2次,以此类推,这种序列的求和公式如下:
(N-1)+(N-2)+(N-3)+…+1=N*(N-1)/2
当N为10的时候,N*(N-1)/2等于45。这样算法做了N2/2次比较。因为数据只有在需要交换的时候才会进行交换,所以交换的次数小于比较的次数,如果数据是随机交换的那么大概有一半的数据需要交换,所以交换的次数大约为N2/4次。
交换和比较都和N2成正比,由于常数不算在大O表示法中,所以可以认为冒泡排序运行需要O(N2)时间级别。
选择排序:
选择排序改进了冒泡排序,将必要的交换次数O(N2)减到了O(N),不幸的是比较次数仍然为O(N2)。但是选择排序仍然为大记录量的排序提出了一个非常重要的改进,因为这些大量的记录需要在内存中移动,这就使得交换时间和比较时间相比起来,交换的时间更加重要。
下面是选择排序的核心代码:
public void selectionSort() {
int out, in, min;
for (out=0; out<nElems-1; out++) {
min = out;
for (in=out+1; in<nElems; in++) {
if (a[in] < a[min])
min = in;
}
swap(out, min);
}
}
外层循环用循环变量out,从数组的开头开始向高位增长。内层循环用循环变量in,从out所指的位置开始,同样是向右移位。在每一个in的新位置,数据项a[in]和a[min]进行比较。如果a[in]更小,则min被赋值为in的值。在内层循环的最后,min指向最小的数据项,然后交换out和min指向的数组数据项。
选择排序的效率:
选择排序和冒泡排序执行了相同的比较次数。N值很大时,比较的次数是主要的,所以结论是选择排序和冒泡排序一样运行了O(N2)时间。但是选择排序无疑更快,因为它进行的交换少得多。
插入排序:
在大多数的情况下,插入排序是目前比较快的算法,虽然插入排序算法仍然需要O(N2)的时间,但是在一般情况下,它要比冒泡排序快一倍,比选择排序还要快一点。
首先为了更好的理解插入排序,OK,假设我们现在有一个数组,这个数组的左边一半的部分是局部有序的,但是右边一半的部分是无序的,然后我们开始排序,首先将右边一半无序的数据中找到最左边的那个,那个暂时被称为是被标记的数据,然后将其从右边的数组中拿出来,开始插入左边的数组,被标记的数据向左移动,之前有序的数据向右移动,当把最后一个比被标记的人还大的数据移位之后,这个移动就停止了, 插入也就结束了。现在,局部有序的部分多了一个数据,而未排序的部分少了一个数据。重复这个过程,直到所有未排序的数据都被插入到有序部分中合适的位置。
下面是插入排序的核心代码:
public void insertionSort() {
int in, out;
for (out = 1; out < nElems; out++) {
long temp = a[out];
in = out;
while (in > 0 && a[in-1] >= temp) {
a[in] = a[in-1];
--in;
}
a[in] = temp;
}
}
在外层的for循环中,out变量从1开始,向右移动。它标记了未排序部分的最左端的数据。而在内层的while循环中,in变量从out变量开始,向左移动,直到temp变量小于in所指的数组数据项,或者它已经不能再往左移动为止。while循环的每一趟都向右移动了已排序的数据项。
插入排序的效率:
复制的次数大致等于比较的次数。然而,一次复制与一次交换的时间耗费不同,所以相对于随机数据,这个算法比冒泡排序快一倍,比选择排序略快。在任意的情况下,对于随机数据进行插入排序也需 要O(N2)的时间级。
几种简单排序之间的比较:
1. 一般情况下几乎不太使用冒泡排序算法。它过于简单了,然而当数据量很小的时候它会有些应用价值。
2. 选择排序肃然把交换次数降到了最低但比较的次数仍然很大。当数据量很小,并且交换数据相对于比较数据更加耗时的情况下,可以应用选择排序。
3. 在大多数情况下,假设当数据量比较小或者基本有序时,插入排序算法是三种简单排序算法中在最好的选择。