码迷,mamicode.com
首页 > 编程语言 > 详细

排序算法

时间:2015-08-16 18:12:12      阅读:120      评论:0      收藏:0      [点我收藏+]

标签:

1.冒泡排序

  1. 比较相邻的两个元素。如果第一个比第二个大,就交换他们两个。
  2. 后移一位,对后面每一对相邻元素作同样的比较,一直比较到队列的最右端,此时最大值已经位于最右端了。
  3. 重新回归到最左端开始第二趟排序,再次从左到右两两比较。当碰到上次排定的元素后(已经排定的值无需再参与后面的排序了),就返回到最左端开始下一趟排序。
  4. 不断执行这个过程,直到所有值都排定。
时间复杂度:O(n*n)
   /**
     * 冒泡排序
     * @param arr
     */
    public void bubbleSort(int[] arr){
        for (int out = arr.length-1; out >1 ; out--) {
            for (int in = 0; in < out; in++) {
                if(arr[in] > arr[in+1]){
                    swap(arr, in, in+1);
                }
            }
        }
    }
    private void swap(int[] arr, int aIndex, int bIndex){
        int temp = arr[aIndex];
        arr[aIndex] = arr[bIndex];
        arr[bIndex] = temp;
    }

2.选择排序

  1. 设定一个标志位(从位置0开始)。
  2. 从标志位开始线性向后遍历列表,找出最小值,与标志位所在位置的数值交换。
  3. 标志位后移一位。继续第2步的操作。直到标志位到达队列的最后一位,此时已完成排序。

时间复杂度:O(n*n)

特点:改进了冒泡排序,将交换次数从O(n*n)减少到O(n),但是比较次数仍为O(n*n)

 /**
     * 选择排序
     * @param arr
     */
    public void selectSort(int[] arr){
        int minIndex;
        for (int out = 0; out < arr.length -1; out++) {
            minIndex = out;
            for (int in = out+1; in < arr.length; in++) {
                if(arr[minIndex] > arr[in]){
                    minIndex = in;
                }
            }
            swap(arr, out, minIndex);
        }
    }

    private void swap(int[] arr, int aIndex, int bIndex){
        int temp = arr[aIndex];
        arr[aIndex] = arr[bIndex];
        arr[bIndex] = temp;
    }

3.插入排序

  ⒈ 从第一个元素开始,该元素可以认为已经被排序
  ⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描
  ⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置
  ⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  ⒌ 将新元素插入到下一位置中
  ⒍ 重复步骤2~5

时间复杂度:O(n*n)

特点:虽然时间复杂度仍为O(n*n),但是一般情况下,要比冒泡排序快一倍,比选择排序还要快点。如果比较操作的代价比交换操作大的话,可以采用二分查找法来减少比较操作的数目。

  /**
     * 插入排序
     * @param arr
     */
    public void insertSort(int[] arr, int left, int right){
        int in;
        int markedNum;
        for (int out = left+1; out <= right; out++) {
            in = out;
            markedNum = arr[out];
            while(in > left && arr[in] >= markedNum){
                arr[in]= arr[in-1];
                in--;
            }
            arr[in] = markedNum;
        }
    }

 

4.归并排序

  1. 假设序列共有n个元素。
  2. 将序列每相邻两个数字进行归并操作(merge),形成floor(n/2)个序列,排序后每个序列包含两个元素
  3. 将上述序列再次进行相邻两个的归并,形成floor(n/4)个序列,每个序列包含四个元素
  4. 重复步骤2,直到所有的序列都归并成一个,即完成了排序。

时间复杂度:O(n log n

 /**
     * 归并排序
     * @param arr
     */
    public void mergeSort(int[] arr, int low, int high){
        if(low == high) {
            return;
        }else{
            int mid = (low + high)/2;
            mergeSort(arr,low,mid);
            mergeSort(arr,mid+1,high);
            merge(arr,high,mid,low);
        }
    }

    private void merge(int[] arr, int high, int mid, int low){
        int arrLen = arr.length;
        int[] newArr = new int[arrLen];
        int lowFlag= low;
        int highFlag = mid+1;
        int i = 0;
        int totalNum = high - low +1;
        while (lowFlag <= mid && highFlag <= high){
            if(arr[lowFlag] < arr[highFlag]){
                newArr[i++] = arr[lowFlag];
                lowFlag++;
            }else{
                newArr[i++] = arr[highFlag];
                highFlag++;
            }
        }

        while(lowFlag <= mid){
            newArr[i++] = newArr[lowFlag++];
        }

        while(highFlag <= high){
            newArr[i++] = newArr[highFlag++];
        }

        for (int j = 0; j <totalNum; j++) {
            arr[j+low] = newArr[j];
        }
    }

4.希尔排序

  1. 设置增量为h
  2. 将间隔为h的元素进行插入排序,从而使数据能够大跨度的移动。
  3. 完成一趟排序后,减小数据间的间隔n再进行排序。一般为(h = (h-1)/3)
  4. 重复步骤2,直到完成间隔为1的排序,算法结束。

时间复杂度:大约为技术分享技术分享

特点:希尔排序是直接插入排序算法的一种改进,减少了其复制的次数,速度要快很多。 原因是,当n值很大时数据每一趟排序需要的个数很少,但数据项的距离很长。当n值减小时每一趟需要和动的数据增多,此时已经接近于它们排序后的最终位置。

/**
     * 希尔排序
     * @param arr
     */
    public void shellSort(int[] arr){
        int h = 1;
        int arrLen = arr.length;
        int temp;
        int in;
        while(h < arrLen/3){
            h = h * 3 + 1;
        }

        while(h > 0){
            for (int i = h; i < arrLen; i++) {
                temp = arr[h];
                in = i;
                while(in>h-1 && arr[in-h] >= temp){
                    arr[in] = arr[in - h];
                    in -=h;
                }
                arr[in] = temp;
            }
            h = (h-1)/3;
        }
    }

5.快速排序

  1. 找出一个元素(理论上可以随便找一个)作为基准(pivot)。
  2. 对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。
  3. 递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正确位置,排序完成

时间复杂度:O(N*logN)

 /**
     * 快速排序
     * @param arr
     * @param left
     * @param right
     */
    public void quickSort(int[] arr, int left, int right){
        int size = right - left + 1;
        if(size < 10){
            insertSort(arr, left, right);
        }else{
            if(left >= right){
                return;
            }else{
                int mid = midOf3(arr, left, right);
                int partition = partitionIt(arr, left, right, mid);
                quickSort(arr, left, partition-1);
                quickSort(arr, partition + 1, right);
            }
        }

    }

    private int midOf3(int[] arr, int left, int right){
        int mid = (left + right)/2;
        if(arr[left] > arr[mid]){
            swap(arr, left, mid);
        }
        if(arr[left] > arr[right]){
            swap(arr, left, right);
        }
        if(arr[mid] > arr[right]) {
            swap(arr, mid, right);
        }
        swap(arr, mid, right-1);
        return arr[right -1];
    }

    private int partitionIt(int[] arr, int left, int right, int pivot){
        int rightFlag = right;
        int leftFlag = left-1;
        while(true){
            while(rightFlag > 0 && arr[rightFlag --] > pivot);
            while(arr[leftFlag ++ ] < pivot);
            if(leftFlag >= rightFlag) {
                break;
            }else{
                swap(arr, leftFlag, rightFlag);
            }
        }
        swap(arr, leftFlag, right);
        return leftFlag;
    }

 

 

 

 
 

排序算法

标签:

原文地址:http://www.cnblogs.com/happySmily/p/4734317.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!