快速排序

快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为 "基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

C语言:

#include <stdio.h>
int a[100] = { 1, 2, 8, 7, 9, 5, 6, 4, 3, 66, 77, 33, 22, 11 };
 
/* 输出数组前n各元素 */
void prt(int n) {
    int i;
    for (i = 0; i < n; i++) {
        printf("%d\t", a[i]);
    }
    printf("\n");
}
 
/* 数据交换 */
void swap(int *a, int *b)
{
    int tmp;
    tmp = *a; *a = *b; *b = tmp;
}
 
void quick_sort(int a[], int left, int right)
{
    int i = left + 1, j = right;
    int  key = a[left];
 
    if (left >= right) return;
 
    /* 从i++和j--两个方向搜索不满足条件的值并交换  *
     * 条件为:i++方向小于key,j--方向大于key      */
    while (1) {
       while (a[j] > key) j--;
       while (a[i] < key&&i<j) i++;
       if(i >= j) break;
       swap(&a[i],&a[j]);
       if(a[i]==key)j--;
       else  i++;
    }
 
    /* 关键数据放到‘中间’ */
    swap(&a[left],&a[j]);
 
    if(left  < i - 1)   quick_sort(a, left, i - 1);
    if(j + 1 < right)  quick_sort(a, j + 1 , right);
 
}
 
int main(void) {
 
    /* 排序与输出 */
    quick_sort(a, 0, 13);
    prt(14);
 
    return 0;
}

C#:

public static void Sort(int[] numbers)
        {
            Sort(numbers, 0, numbers.Length - 1);
        }
 
        private static void Sort(int[] numbers, int left, int right)
        {
            if (left < right)
            {
                int middle = numbers[(left + right) / 2];
                int i = left - 1;
                int j = right + 1;
                while (true)
                {
                    while (numbers[++i] < middle) ;
 
                    while (numbers[--j] > middle) ;
 
                    if (i >= j)
                        break;
 
                    Swap(numbers, i, j);
                }
 
                Sort(numbers, left, i - 1);
                Sort(numbers, j + 1, right);
            }
        }
 
        private static void Swap(int[] numbers, int i, int j)
        {
            int number = numbers[i];
            numbers[i] = numbers[j];
            numbers[j] = number;
        }


JAVA:

import java.util.Comparator;
import java.util.Random;
 
public class Quicksort {
    public static final Random RND = new Random();
 
    private static void swap(Object[] array, int i, int j) {
        Object tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
 
    private static <E> int partition(E[] array, int begin, int end, Comparator<? super E> cmp) {
        int index = begin + RND.nextInt(end - begin + 1);
        E pivot = array[index];
        swap(array, index, end);        
        for (int i = index = begin; i < end; ++ i) {
            if (cmp.compare(array[i], pivot) <= 0) {
                swap(array, index++, i);
            }
        }
        swap(array, index, end);        
        return (index);
    }
 
    private static <E> void qsort(E[] array, int begin, int end, Comparator<? super E> cmp) {
        if (end > begin) {
            int index = partition(array, begin, end, cmp);
            qsort(array, begin, index - 1, cmp);
            qsort(array, index + 1,  end,  cmp);
        }
    }
 
    public static <E> void sort(E[] array, Comparator<? super E> cmp) {
        qsort(array, 0, array.length - 1, cmp);
    }
 
}
 
/*
 * more efficient implements for quicksort. <br />
 * use left, center and right median value (@see #median()) for the pivot, and
 * the more efficient inner loop for the core of the algorithm.
 */
class Sort {
 
     public static final int CUTOFF = 11;
 
    /**
     * quick sort algorithm. <br />
     * 
     * @param arr an array of Comparable items. <br />
     */
     public static <T extends Comparable<? super T>> void quicksort( T[] arr ) {
         quickSort( arr, 0, arr.length - 1 );
     }
 
 
     /**
      * get the median of the left, center and right. <br />
      * order these and hide the pivot by put it the end of
      * of the array. <br />
      * 
      * @param arr an array of Comparable items. <br />
      * @param left the most-left index of the subarray. <br />
      * @param right the most-right index of the subarray.<br />
      * @return T
      */
      public static <T extends Comparable<? super T>> T median( T[] arr, int left, int right ) {
 
                int center = ( left + right ) / 2;
 
                if ( arr[left].compareTo( arr[center] ) > 0 )
                        swapRef( arr, left, center );
                if ( arr[left].compareTo( arr[right] ) > 0 )
                        swapRef( arr, left, right );
                if ( arr[center].compareTo( arr[right] ) > 0 )
                        swapRef( arr, center, right );
 
                swapRef( arr, center, right - 1 );
                return arr[ right - 1 ];
      }
 
     /**
      * internal method to sort the array with quick sort algorithm. <br />
      * 
      * @param arr an array of Comparable Items. <br />
      * @param left the left-most index of the subarray. <br />
      * @param right the right-most index of the subarray. <br />
      */
      private static <T extends Comparable<? super T>> void quickSort( T[] arr, int left, int right ) {
                if ( left + CUTOFF <= right  ) {
                        //find the pivot
                        T pivot = median( arr, left, right );
 
                        //start partitioning
                        int i = left, j = right - 1;
                        for ( ; ; ) {
                                while ( arr[++i].compareTo( pivot ) < 0 ) ;
                                while ( arr[--j].compareTo( pivot ) > 0 ) ;
                                if ( i < j )
                                        swapRef( arr, i, j );
                                else
                                        break;
                        }
 
                        //swap the pivot reference back to the small collection.
                        swapRef( arr, i, right - 1 );
 
                        quickSort( arr, left, i - 1 );          //sort the small collection.
                        quickSort( arr, i + 1, right );         //sort the large collection.
 
                } else {
                        //if the total number is less than CUTOFF we use insertion sort instead (cause it much more efficient).
                        insertionSort( arr, left, right );
                }
      }
 
 
      /**
       * method to swap references in an array.<br />
       * 
       * @param arr an array of Objects. <br />
       * @param idx1 the index of the first element. <br />
       * @param idx2 the index of the second element. <br />
       */
      public static <T> void swapRef( T[] arr, int idx1, int idx2 ) {
                T tmp = arr[idx1];
                arr[idx1] = arr[idx2];
                arr[idx2] = tmp;
      }
 
 
      /**
       * method to sort an subarray from start to end
       *                with insertion sort algorithm. <br />
       * 
       * @param arr an array of Comparable items. <br />
       * @param start the begining position. <br />
       * @param end the end position. <br />
       */
      public static <T extends Comparable<? super T>> void insertionSort( T[] arr, int start, int end ) {
                int i;
                for ( int j = start + 1; j <= end; j++ ) {
                        T tmp = arr[j];
                        for ( i = j; i > start && tmp.compareTo( arr[i - 1] ) < 0; i-- ) {
                                arr[ i ] = arr[ i - 1 ];
                        }
                        arr[ i ] = tmp;
                }
      }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值