zoukankan      html  css  js  c++  java
  • 常见排序算法--简单排序

    本文包括:

    1.选择排序

    2.冒泡排序/双向冒泡排序

    3.插入排序

    1.选择排序

    选择排序是一种最为直观的排序方法。每次循环从数组中选择出一个最小或者最大的元素,按顺序重新放入数组中,直到所有的戴排序元素都排序完成。

    public void selectSort(int[] a){
            int temp=0;
            for(int i=0;i<a.length-1;i++){
                for(int j=i+1;j<a.length;j++){
                    if(a[j]<a[i]){
                        temp = a[j];
                        a[j] = a[i];
                        a[i] = temp;
                    }
                }
            }
        }

    从代码不难看出,选择排序的过程是:第一次循环,遍历数组找出数组中最小的数字,放入a[0],第二次循环,找出剩下数组中最小的数字放入a[1]一次类推。

    所以,选择排序的时间复杂度为O(n^2),如果n较大,则效率会非常低。

    2.冒泡排序

    冒泡排序也是较为简单的一种排序方法,之所以叫冒泡排序,是因为排序的手法会使数字浮到数组顶端而得名。

    冒泡排序的手法是:比较相邻的两个元素,如果相邻的两个元素的顺序是错误的,则将他们交换;然后继续比较下一组相邻的元素。直到所有需要排列的元素都排序完成。

    public void bubbSort(int[] a){
            int temp=0;
            for(int i=0;i<a.length-1;i++){
                for(int j=a.length-1;j>i;j--){
                    if(a[j]<a[j-1]){
                        temp = a[j];
                        a[j] = a[j-1];
                        a[j-1] = temp;
                    }
                }
            }
        }

    从代码我们可以看出来:冒泡排序是用层循环,外侧循环的意义是在于,循环n次,每次冒泡都冒出最小的节点依次放在数组的最前面。第二层循环的意义是在于,进行冒泡操作,每次比较相邻的两个元素,将较小的元素,像数组头方向移动。

    因此我们可以看出冒泡排序的时间复杂度为O(n^2),如果n较大,则效率会非常低,如果数组是有序的,即进行一次冒泡扫描发现移动的关键次数为最小时,说明数组已经有序,此时的时间复杂度为O(n)。

    双向冒泡排序:

    传统的冒泡排序要么是从左向右进行,要么从右向左进行,每次都只对数组一头的元素进行扫描排序。

    而双向冒泡排序首先从前往后把最大数移到最后,然后反过来从后往前把最小的一个数移动到数组最前面,这一过程就是第一轮,然后重复这一过程,最终就会把整个数组从小到大排列好。

    public void bubbSort2(int[] a){
            int left =1 ;
            int right = a.length -1;
            int t=0;
            while(left<=right){
                for(int i=right;i>=left;i--){
                    if(a[i]<a[i-1]){
                        int temp;
                        temp = a[i];
                        a[i] = a[i-1];
                        a[i-1] = temp;
                        t = i;//记录上一次交换的下标
                    }
                }
                left = t+1; //t+1中间乱序部分的最左端
                for(int i=left;i<right+1;i++){
                    if(a[i]<a[i-1]){
                        int temp;
                        temp = a[i];
                        a[i] = a[i-1];
                        a[i-1] = temp;
                        t = i;//记录上一次交换的下标
                    }
                }
                right = t-1;//t-1为中间乱序部分的最右端
            }
        }

    从代码看来,双向冒泡排序会比普通冒泡排序减少很多次循环。因为双向排序时数组的两头都排序好了,我们只需要处理数组的中间部分即可,普通冒泡排序只有一头的元素是排好序的。

    虽然双向冒泡排序有些改进,但是不能大幅度的提升效率,这是由于冒泡排序的基本过程所确定的。

    3.插入排序

    插入排序的基本方法是,每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

    public void insertSort(int[] a){
            for(int i=1;i<a.length;i++){
                int temp = a[i],j=i    ;
                if(a[j-1]>temp){
                    while(j>=1&&a[j-1]>temp){//找到新元素合适的位置
                        a[j] = a[j-1];//前一个覆盖后一个
                        j--;
                    }
                }
                a[j]=temp; //插入元素
            }
        }

    直接插入排序最好的时间复杂度为O(n),平均时间复杂度为O(n^2)。同样的,如果n过于大的时候,直接插入排序的效率会很低。

    插入排序改进思路和冒泡排序一样,我们也可以对于直接插入排序进行改进。在直接插入排序中我们每次插入元素的时候,都是挨个遍历前面所有元素,这样遍历的效率并不高。

    因为插入的数组是已经排好序的有序数组,所以我们自然而然的想到了折半插入的方法,这样可以减少比较的次数。

    不过虽然折半插入会减少元素比较的次数,但因为是插入数组,所以,只是减少元素的比较次数,元素移动的个数依然没有改变,时间复杂度依然是O(n^2)。

  • 相关阅读:
    spring cloud-zuul的Filter详解
    Hibernate day01
    JAVA中几种常用的RPC框架介绍
    乐观锁和悲观锁的区别(最全面的分析)
    Redis、Memcache和MongoDB的区别
    Hessian整合Spring
    Hessian的使用以及理解
    sso单点登录系统原理与实现
    zookeeper原理(转)
    Nginx的负载均衡的几种方式
  • 原文地址:https://www.cnblogs.com/yfsmooth/p/4718151.html
Copyright © 2011-2022 走看看