算法熟记-排序系列-快速排序

1. 简述

    假设待排序数组为 int array[], 数组长度为n。快速排序是一个递归得方法。
    当n==1的时候,停止排序。
    当n>1的时候,首先选择数组中得一个元素作为基准,然后,把小于这个基准得元素放到这个基准的左边,把大于这个基准得元素放到这个元素得右边。
    具体实现下面进行简单得说明,假设array[0]作为基准:
    首先,存储基准得值,int tmp=array[0];
    然后,两个指针,int left=0; int right = n-1;
    bool flag_left = false; // 初始从右边开始                                
    while(left < right) {
        if(flag_left == true) {
            如果当前值小于基准,则left++;
            否则,array[right]=array[left]; right--; flag_left = false;
        }       
        else {
             如果当前值大于基准,则right--;
             否则,array[left]=array[right]; left++; flag_left = true;

        }

    } 
    array[left] = tmp;
    上面这段代码中,当轮到left指针执行时,right指针向的位置是可以使用的。当轮到right指针执行时,left指针指向的位置是可以使用的。
    初始时,备份了array[0],left指针指向的位置是可以使用 得,因此从右边开始。
    最后,递归排序array[0]-array[left-1]和array[left+1]-array[n-1]两个部分的数组。
2. 复杂度

    平均时间复杂度是O(N*logN)。当数组本身已经有序得情况下,需要比较得次数是N*N次。为了解决这样的问题,可以使用乱数快速排序,即每次基准是随即选择的。
    稳定性属于非稳定排序。因为在与基准的比较过程中的交换很可能打破已有的顺序。

3. 代码    

void quick_sort(int array[], int n) {
  
if(n <= 1)
    
return;
  
int tmp = array[0];
  
int left = 0int right = n-1;
  
bool left_flag = false;
  
while(left < right) {
    
if(left_flag == true) { // 当前left指针
      if(array[left] < tmp) {
        left
++;
      }
      
else {
        array[right] 
= array[left];
        right
--;
        left_flag 
= false;
      }
    }
    
else { // 当前right指针
      if(array[right] > tmp) {
        right
--;
      }
      
else {
        array[left] 
= array[right];
        left
++;
        left_flag 
= true;
      }
    }
  } 
  array[left] 
= tmp;
  quick_sort(array, left); 
// array[0]-array[left-1]
  quick_sort(array+left+1, n-left-1); // array[left+1], array[n-1]
}

    实际上,快速排序是作为冒泡排序的改进提出来的,很多实现都是通过元素交换实现的,上面的代码是改进后的,更加有效率,把元素交换变成了元素的赋值。
    一般来说,交换排序包括:冒泡排序和快速排序。
    下面贴一个快速排序使用交换元素的实现:
   

void quicksort(int arr[],int beg,int end) {
  if (end  >= beg + 1) {
    
int piv = arr[beg], k = beg + 1, r = end;
    // 从基准(array[0])右边的元素开始扫描,对于小于基准的元素跳过,对于大于基准的元素,交换到右边的位置上去,缩减右边的位置。
    // 当右边可以交换的位置与当前元素重叠了,结束循环
    
while (k < r) {
      if (arr[k] < piv) 
        k
++;
      
else
        swap(
&arr[k], &arr[r--]);
    }
    // 交换基准
    
if (arr[k] < piv){
      swap(&arr[k],&arr[beg]);
      quicksort(arr, beg, k);
      quicksort(arr, r, end);                    
    }
    else {
      
if (end - beg == 1)
      
return;
      swap(
&arr[--k],&arr[beg]);
      quicksort(arr, beg, k);
      quicksort(arr, r,   end);                  
    }
  }
}

4. 参考资料

    维基百科-快速排序    http://en.wikipedia.org/wiki/Quicksort

posted @ 2011-06-08 15:58  xiaodongrush  阅读(363)  评论(1编辑  收藏  举报