快速排序及其优化

package com.zc.algorithm;

public class QuickSort {
    //快速排序:挖坑法
    public int partition(int[] arr, int left, int right)
    {
        if(left<right)
        {
            int temp = arr[left];
            while(left<right)
            {
                //如果右边的数大于基数temp,则向左移动
                while(left<right&&arr[right] >= temp)
                {
                    right--;
                }
                //如果不大于,则把右边的数赋值给左边
                arr[left] = arr[right];
                //如果左边的数小于基数,则向右移动
                while(left<right&&arr[left] <= temp)
                {
                    left++;
                }
                //如果左边的数大于基数,则左边的数赋值给右边
                arr[right] = arr[left];
            }
            arr[left]=temp;
        }
        
        return left;
    }
 public int[] QSort(int[] arr, int left, int right)
 {
     int[] newArr = arr;
     if(left < right)
     {
     int pivot = partition(newArr, left, right);
     QSort(newArr,left,pivot-1);
     QSort(newArr, pivot+1,right);
     }
     return newArr;
 }
 //快速排序优化1:三数取中法,将数组中的开头、结尾和中间的数做比较,把最大的放在末尾,然后把最小的放在中间,第二大的放在开头,解决数组中部分有序的问题
 public void MedianOfThree(int[] arr, int left, int right)
 {
     int mid = left+(left+right);
     if(arr[left] > arr[right])//把最大值放在数组的末尾
     {
         swap(arr, left, right);
     }
     if(arr[mid]> arr[right])//把最大值放在数组的末尾
     {
         swap(arr, mid, right);
     }
     if(arr[mid]>arr[left])//把最小值放在中间
     {
         swap(arr, mid, left);
     }
 }
 //交换
 public void swap(int[] arr, int left, int right)
 {
         int temp = arr[left];
         arr[left] = arr[right];
         arr[right] = temp;
 }
 public int[] QSort_MedianOfThree(int[] arr, int left, int right)
 {
     //[1]先进行数字调换
     MedianOfThree(arr,left,right);//将中间数放到开头
     int[] newArr = arr;
     if(left < right)
     {
     int pivot = partition(newArr, left,right);
     QSort(newArr,left,pivot-1);
     QSort(newArr, pivot+1,right);
     }
     return newArr;
 }
 //快速排序优化2:三数取中+插入排序
 public int[] insertSort(int[] arr)
 {
     int j = 0;
     for(int i = 1; i< arr.length; i++)
     {
         int temp = arr[i];
         for( j = i-1; j >=0&&arr[j]>temp;j--)
         {
             arr[j+1] = arr[j];
         }
         arr[j+1] = temp;
     }
     return arr;
 }
 public int[] QSort_Insert(int[] arr, int left, int right)
 {
     //如果数组的长度小于10,则采用插入排序
     if(right - left +1 < 10)
     {
         return insertSort(arr);
     }
     //[1]先进行数字调换
     MedianOfThree(arr,left,right);//将中间数放到开头
     int[] newArr = arr;
     if(left < right)
     {
     int pivot = partition(newArr, left,right);
     QSort(newArr,left,pivot-1);
     QSort(newArr, pivot+1,right);
     }
     return newArr;
 }
 
  //快速排序优化3:三数取中+插排+聚集相同元素,解决数组中部分重复的问题
 public int[] QsortThreeInsertGather(int[] arr, int low, int high)
 {
     if(high - low+1<10)
     {
         return insertSort(arr);
     }
     //三数取中
     MedianOfThree(arr, low, high);
     int first = low;
     int last = high;
     int left = low;
     int right = high;
     int leftLength = 0;
     int rightLength = 0;
     int key = arr[first];
     while(first < last)
     {
         while(first < last&&arr[last]>=key)
         {
             if(arr[last] == key)
             {
                 swap(arr, last, right);
                 right--;
                 rightLength++;
             }
             last--;
         }
         arr[first] = arr[last];
         while(first<last&& arr[first]<=key)
         {
             if(arr[first] == key)
             {
                 swap(arr, first,left);
                 left++;
                 leftLength++;
             }
             first++;
         }
         arr[first] = key;
     }
    int i = first - 1;
    int j =low;
    while(j < left&&arr[i]!=key)
    {
        swap(arr,i,j);
        i--;
        j++;
    }
    i =last+1;
    j = high;
    while(j>right&&arr[i]!=key)
    {
        swap(arr,i,j);
        i++;
        j--;
    }
    QsortThreeInsertGather(arr,low,first-leftLength-1);
    QsortThreeInsertGather(arr,first+rightLength+1,high);
    return arr;
 }
}

posted @ 2019-04-17 19:59  keep-the-faith  阅读(198)  评论(0编辑  收藏  举报