简单排序

一旦建立了一个数据库之后,就可能需要根据某些需求对数据进行不同方式的排序。

计算机和人类的的区别就是计算机不能向人这样通览所有的数据,它只能根据计算机的“比较”操作原理,在同一时间对两个队员进行比较。在人类看来很简单的事情,计算机的算法却不能看到全景,因此它只能一步一步的解决具体问题和遵循一些简单的规则。
      下面说的几个算法都包括下面的两个步骤,这两个步骤循环执行,知道全部数据有效为止:
      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. 在大多数情况下,假设当数据量比较小或者基本有序时,插入排序算法是三种简单排序算法中在最好的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值