zoukankan      html  css  js  c++  java
  • 排序:冒泡排序 快速排序

     排序的稳定性和复杂度

          不稳定:

          选择排序(selection sort)— O(n2)

          快速排序(quicksort)— O(nlogn) 平均时间, O(n2) 最坏情况; 对于大的、乱序串列一般认为是最快的已知排序

          堆排序 (heapsort)— O(nlogn)

          希尔排序 (shell sort)— O(nlogn)

          基数排序(radix sort)— O(n·k); 需要 O(n) 额外存储空间 (K为特征个数)

          稳定:

          插入排序(insertion sort)— O(n2)

          冒泡排序(bubble sort) — O(n2)

          归并排序 (merge sort)— O(n log n); 需要 O(n) 额外存储空间

          二叉树排序(Binary tree sort) — O(nlogn); 需要 O(n) 额外存储空间

          计数排序  (counting sort) — O(n+k); 需要 O(n+k) 额外存储空间,k为序列中Max-Min+1

          桶排序 (bucket sort)— O(n); 需要 O(k) 额外存储空间

    -----------------------------每种排序的原理和实现----------------------------

    1、冒泡排序

    冒泡排序(Bubble Sort)是一种典型的交换排序算法,通过交换数据元素的位置进行排序。

    一、算法基本思想

    (1)基本思想

    冒泡排序的基本思想就是:从无序序列头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)的数据元素交换到了无序队列的队尾,从而成为有序序列的一部分;下一次继续这个过程,直到所有数据元素都排好序。

    算法的核心在于每次通过两两比较交换位置,选出剩余无序序列里最大(小)的数据元素放到队尾。

    (2)运行过程

    冒泡排序算法的运作如下:

    1、比较相邻的元素。如果第一个比第二个大(小),就交换他们两个。

    2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大(小)的数。

    3、针对所有的元素重复以上的步骤,除了最后已经选出的元素(有序)。

    4、持续每次对越来越少的元素(无序元素)重复上面的步骤,直到没有任何一对数字需要比较,则序列最终有序。

    (3)示例

    二、算法实现(核心代码)

    Java实现:

    public static void bubble_sort(int[] arr) {
      int i, j, temp, len = arr.length;
      for (i = 0; i < len - 1; i++){
        for (j = 0; j < len - 1 - i; j++)
          if (arr[j] > arr[j + 1]) {
            temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
          }
      }
    }

    冒泡排序的性能分析和算法优化(外层循环优化)

    问题:

    有的冒泡经过第一轮的交换已经是有序的了,如:2 1 3 4。数据越多的时候越慢,非常不适合大数据的排序

    解决办法

    如果用一个flag来判断一下,当前数组是否已经有序,如果有序就退出循环,这样可以明显的提高冒泡排序的性能。

    复制代码
    package bubbleSort;
    
    import java.util.Arrays;
    
    import org.junit.Test;
    
    /**
     * 冒泡排序的性能分析和算法优化(外层循环优化)
     * @author dell
     *
     */
    public class BubbeSort02 {
    
        @Test
        public void test1(){
            boolean flag = true;
            int[] arr = {2,1,3,4,5};
            int temp;
            for (int i = 0; i < arr.length-1; i++) {
                for (int j = 0; j < arr.length-1-i; j++) {
                    if(arr[j]>arr[j+1]){
                        temp=arr[j];
                        arr[j]=arr[j+1];
                        arr[j+1]=temp;
                        flag=false;
                    }
                }
                if(!flag){
                    //没有发生交换则退出循环;
                    break;
                }
            }
            System.out.println(Arrays.toString(arr));
        }
    }
    复制代码

    冒泡排序第二种优化(内层循环优化)

    复制代码
        /**
         * 冒泡排序的性能分析和算法优化(内层循环优化)
         */
        @Test
        public void test2(){
            
            int[] arr = {22,1,10,5};
            
            //标记最后一次交换的位置
            
            
            for (int i = 0; i < arr.length-1; i++) {
                int flag = 0;
                int temp;
                for (int j = 0; j < arr.length-i-1; j++) {
                    if(arr[j]>arr[j+1]){
                        temp=arr[j];
                        arr[j]=arr[j+1];
                        arr[j+1]=temp;
                        //当位置发生改变,flag的值就发生变化
                        flag=1;
                    }
                }
                //判断标志位flag有没有发生变化,没有就直接结束内层循环
                if(flag==0){
                    return;
                }
            }
            System.out.println(Arrays.toString(arr));
        }
    }

     -----------------------------------快速排序--------------------------

    一、算法基本思想

    选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。

    一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值来说,左右两边就是有序的了。

    接着分别比较左右两边的序列,重复上述的循环。

    二、算法实现(核心代码)

    Java实现:

    public class FastSort{
    
         public static void main(String []args){
            System.out.println("Hello World");
            int[] a = {12,20,5,16,15,1,30,45,23,9};
            int start = 0;
            int end = a.length-1;
            sort(a,start,end);
            for(int i = 0; i<a.length; i++){
                 System.out.println(a[i]);
             }
            
         }
         
         public void sort(int[] a,int low,int high){
             int start = low;
             int end = high;
             int key = a[low];
             
             
             while(end>start){
                 //从后往前比较
                 while(end>start&&a[end]>=key)  //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                     end--;
                 if(a[end]<=key){
                     int temp = a[end];
                     a[end] = a[start];
                     a[start] = temp;
                 }
                 //从前往后比较
                 while(end>start&&a[start]<=key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                    start++;
                 if(a[start]>=key){
                     int temp = a[start];
                     a[start] = a[end];
                     a[end] = temp;
                 }
             //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
             }
             //递归
             if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
             if(end<high) sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
         }
         
    }

    -----------------------------------选择排序---------------------------

    a) 原理:每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是:每一趟在n-i+1(i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。基于此思想的算法主要有简单选择排序、树型选择排序和堆排序。(这里只介绍常用的简单选择排序)

    b) 简单选择排序的基本思想:给定数组:int[] arr={里面n个数据};第1趟排序,在待排序数据arr[1]~arr[n]中选出最小的数据,将它与arrr[1]交换;第2趟,在待排序数据arr[2]~arr[n]中选出最小的数据,将它与r[2]交换;以此类推,第i趟在待排序数据arr[i]~arr[n]中选出最小的数据,将它与r[i]交换,直到全部排序完成。

    c) 举例:数组 int[] arr={5,2,8,4,9,1};

    -------------------------------------------------------

    第一趟排序: 原始数据:5  2  8  4  9  1

    最小数据1,把1放在首位,也就是1和5互换位置,

    排序结果:1  2  8  4  9  5

    -------------------------------------------------------

    第二趟排序:

    第1以外的数据{2  8  4  9  5}进行比较,2最小,

    排序结果:1  2  8  4  9  5

    -------------------------------------------------------

    第三趟排序:

    除1、2以外的数据{8  4  9  5}进行比较,4最小,8和4交换

    排序结果:1  2  4  8  9  5

    -------------------------------------------------------

    第四趟排序:

    除第1、2、4以外的其他数据{8  9  5}进行比较,5最小,8和5交换

    排序结果:1  2  4  5  9  8

    -------------------------------------------------------

    第五趟排序:

    除第1、2、4、5以外的其他数据{9  8}进行比较,8最小,8和9交换

    排序结果:1  2  4  5  8  9

    -------------------------------------------------------

    注:每一趟排序获得最小数的方法:for循环进行比较,定义一个第三个变量temp,首先前两个数比较,把较小的数放在temp中,然后用temp再去跟剩下的数据比较,如果出现比temp小的数据,就用它代替temp中原有的数据。具体参照后面的代码示例,相信你在学排序之前已经学过for循环语句了,这样的话,这里理解起来就特别容易了。

    代码示例:

    //选择排序
    public class SelectionSort {
        public static void main(String[] args) {
            int[] arr={1,3,2,45,65,33,12};
            System.out.println("交换之前:");
            for(int num:arr){
                System.out.print(num+" ");
            }        
            //选择排序的优化
            for(int i = 0; i < arr.length - 1; i++) {// 做第i趟排序
                int k = i;
                for(int j = k + 1; j < arr.length; j++){// 选最小的记录
                    if(arr[j] < arr[k]){ 
                        k = j; //记下目前找到的最小值所在的位置
                    }
                }
                //在内层循环结束,也就是找到本轮循环的最小的数以后,再进行交换
                if(i != k){  //交换a[i]和a[k]
                    int temp = arr[i];
                    arr[i] = arr[k];
                    arr[k] = temp;
                }    
            }
            System.out.println();
            System.out.println("交换后:");
            for(int num:arr){
                System.out.print(num+" ");
            }
        }
    
    }

    -----------------------------插入排序---------------------------------------

     https://blog.csdn.net/qq_28081081/article/details/80594386

  • 相关阅读:
    Openstack的项目管理方案
    Openstack的web管理端相关
    Openstack安全规则说明
    Openstack命令行删除虚拟机硬件模板flavor
    [转]java中的Static class
    [转]Activitys, Threads, & Memory Leaks
    [转]How to Leak a Context: Handlers & Inner Classes
    [原]Android打包之Eclipse打多渠道包
    [转]ubuntu下整合eclipse和javah生成jni头文件开发android的native程序
    Nao 类人机器人 相关资料
  • 原文地址:https://www.cnblogs.com/zhou-test/p/9796323.html
Copyright © 2011-2022 走看看