第三章 简单排序

一、概要
     三种简单的排序:冒泡排序、选择排序、插入排序。

二、冒泡排序
     假设由n个队员,并且根据所站的位置从左到右分别给每一个队员编号,从0到n-1。
     冒泡排序的过程如下:
     从队列的最左边开始,比较第0号和第1号,如果左边的队员比右边高,则交换两个队员。否则不做任何事。然后右移一个位置,比较第1号和第2号,重复上诉步骤,直到最后一个队员。这个属于第一轮冒泡,能够把最高的队员放在最右边。然后进行第二轮,依然从第0号开始,这一轮排序到n-2号队员。重复进行上诉操作,直到无需再排序了。

三、冒泡排序代码

class ArrayBub {
     private long[] a;
     private int nElems;

     public ArrayBub(int max) {
          a = new long[max];
          nElems = 0;
     }

     public void insert(long value) {
          a[nElems++] = value;
     }

     public void display() {
          for(int i = 0;i < nElems;i++) {
               System.out.print(a[i] + “   “);
          }
     }

     //排序算法
     public void bubbleSort() {
          int out;
          int in;
          
          for(out = nElems -1;out > 1;out—)
               for(in = 0;in < out;i++) {
                    if (a[in] > a[in+1])
                         swap(in, in+1);
     }

     private void swap(int one, int two) {
          long temp = a[one];
          a[one] = a[two];
          a[two] = temp;
     }
}

class BubbleSortApp {
     public static void main(String[] args) {
          int maxSize = 100;
          ArrayBub arr = new ArrayBub(maxSize);
         
          arr. insert(77);
          arr. insert(27);
          arr. insert(71);
          arr. insert(44);
          arr. insert(23);
          arr. insert(10);
          arr. insert(87);
          arr. insert(99);
          arr. insert(32);
 
          arr.display();

          arr.bubbleSort();
          arr.display();
     }
}
     冒泡算法的思路是要将最小的数据项放在数组的最开始(下标为0),并将最大的数据项放在数组的最后(下标为nElems-1),内层从数组的最开始算起,每次循环加一进行比较排序,外层从nElems-1开始,每次循环减一进行每一轮排序。

四、不变性
     在许多算法中,有些条件在算法执行时时不变的。这些条件称为不变性。在冒泡算法中,它的不变性就是out右边的所有数据项是有序的。
     在调试算法的时候,我们可以反复检查它的不变性是否为真,如果不是,就说明出错了。

五、冒泡排序的效率
     可以发现,如果有n个数据项,第一趟排序中有n-1次比较,第二趟排序中有n-2次比较,如此类推:
     (n-1)+(n-2)+(n-3)+…+1=n*(n-1)/2
      与n平方成正比,因此冒泡排序的效率为O(N^2)

六、选择排序
     同样是为球队排序,排序从球员队列的最左边开始,记录下最左边球员的身高,然后开始用下一个的球员身高和它相比较,如果这个球员更矮,则纪录下新的最矮纪录,然后继续看下一个球员,直到全部球员比较结束。然后纪录到身高最矮的球员和最左边的球员调换位置。接下来,从第二个球员开始,重复上诉步骤,直到最后一个球员。
     
七、选择排序代码

class ArraySel {
     private long[] a;
     private int nElems;

     public ArraySel(int max) {
          a = new long[max];
          nElems = 0;
     }

     public void insert(long value) {
          a[nElems++] = value;
     }

     public void display() {
          for(int i = 0;i < nElems;i++) {
               System.out.print(a[i] + “   “);
          }
     }

     //选择算法
     public void selectionSort() {
          int out;
          int in;
          int 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);
          }
     }

     private void swap(int one, int two) {
          long temp = a[one];
          a[one] = a[two];
          a[two] = temp;
     }
}

class SelectSortApp {
     public static void main(String[] args) {
          int maxSize = 100;
          ArraySel arr = new ArraySel(maxSize);
         
          arr. insert(77);
          arr. insert(27);
          arr. insert(71);
          arr. insert(44);
          arr. insert(23);
          arr. insert(10);
          arr. insert(87);
          arr. insert(99);
          arr. insert(32);
 
          arr.display();

          arr.selectionSort();
          arr.display();
     }
}

八、不变性
     在选择排序中,下标小于或等于out的位置的数据项总是有序的。

九、选择排序的效率
     选择排序改进了冒泡排序的缺点,将交换次数从O(N^2)减少到O(N),但是比较次数仍然是O(N^2),因此二者的时间效率相同,但是选择排序无疑是更快的。

十、插入排序
     在大多数情况下,简单排序中,插入排序是最快的一种。
     假设队伍前一半已经排序好了,这个时候,在队伍中间有一个作为标记的队员,TA左边的所有队员已经是有序的,这时只要找到“被标记”队员在左边有序队列中合适的位置,就可以了。因此,我们先让“被标记”队员站出来,和左边有序队伍中最右边的那个队员比较,如果“被标记”队员更矮,那么最右边的队员右移一位,然后“被标记”队员继续和有序队伍右边倒数第二个队员比较,同样的规则,直到发现被比较的队员比“被标记”队员要矮,那么此时空出来的位置就是“被标记”的队员的。按照这个规则,我们就是从队伍的第一个依次标记到最后一个。

十一、插入排序的代码


class ArrayIns {
     private long[] a;
     private int nElems;

     public ArrayIns(int max) {
          a = new long[max];
          nElems = 0;
     }

     public void insert(long value) {
          a[nElems++] = value;
     }

     public void display() {
          for(int i = 0;i < nElems;i++) {
               System.out.print(a[i] + “   “);
          }
     }

     //插入算法
     public void insertSort() {
          int out;
          int in;
          
          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;
           }
     }
}

class InsertSortApp {
     public static void main(String[] args) {
          int maxSize = 100;
          ArraySel arr = new ArraySel(maxSize);
         
          arr. insert(77);
          arr. insert(27);
          arr. insert(71);
          arr. insert(44);
          arr. insert(23);
          arr. insert(10);
          arr. insert(87);
          arr. insert(99);
          arr. insert(32);
 
          arr.display();

          arr.insertSort();
          arr.display();
     }
}

十二、插入排序中的不变性
     插入排序中,比out下标小的数据项都是局部有序的。

十三、插入排序的效率
     1+2+3+…+N-1=N*(N-1)/2,第一趟最多比较一次,第二趟最多比较两次。。。然而在每一趟排序发现插入点之前,平均只有全体数据项的一半真的进行了比较,因此应该是N*(N-1)/4。总体而言,插入排序的算法,比冒泡排序快一倍,比选择排序略快。
       
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值