快速排序

快速排序

快速排序是一种基于分治法的排序算法,通过选择一个枢轴元素(或说参考值,从数组中选择的元素)将数组划分为子数组。

在划分数组时使小于枢轴的元素保留在左侧,大于枢轴的元素位于枢轴的右侧。每轮划分后,继续对左右子数组使用相同的方法进行划分,直持续到每个子数组都只包含一个元素。此时,元素已经排好序,将元素组合起来就是一个有序的数组。

-w600

快速排序工作流程

1.选择一个枢轴元素(参考值) 这里选数组的最右边的元素 -w400

2.重排数组 以2为枢轴元素,重排后的数组比2小的在它左边,比2大的在它右边,如下图: -w400

重排过程:

  1. 定义一个固定索引指针指向枢轴元素,并定义两个指针(快、慢双指针)都指到左边的第1个元素索引上,然后用指针指向的元素与枢轴元素进行比较; -w400

  2. 如果快指针指向的元素大于枢轴元素,就把快指针往后挪1个位置,继续下一次与枢轴元素比较,此时慢指针还保持在原来的位置上; -w400

  3. 继续迭代,快指针继续不断与枢轴元素比较挪移,直到快指针指的元素小于枢轴元素,就交换快慢指针所指向的元素,交换后快、慢就都同时往后挪1位置; -w400

  4. 重复 2、3这一过程,快指针元素大于枢轴元素就只挪快指针;小于枢轴元素就交换快慢指针元素并把快慢指针都往后挪; -w400

  5. 直到快指针到达最后一个元素的位置; -w400

  6. 最后交换枢轴元素与慢指针元素; -w400

3.划分子数组 一次遍历交换后,以原枢轴元素为界线,再分别对左右子数组做1、2操作(即1.选择数组最右边元素作为子数组的枢轴元素;2.重排子数组); -w600

左子数组划分重排过程 -w600

右子数组划分重排过程 -w600

复杂度

|Time Complexity|| |—|—| |Best | O(nlog n) | |Worst | O(n^2) | |Average | O(nlog n) | |Space Complexity | O(log n) | |Stability | NO |

代码实现

Swift实现

import Foundation

func quickSort(array: inout Array<Int>) {
    if(array.count <= 1){
        return
    }
    
    //找一个参考值base
    guard let base = array.first else { return }
    //分配左右两块区
    var left = [Int](https://luowei.github.io/list/)
    var right = [Int](https://luowei.github.io/list/)
    //遍历
    for i in  1 ..< array.count {
        //把大于base的放到右边区块,小于等于base的放到左边区块
        if array[i] > base {
            right.append(array[i])
        }else{
            left.append(array[i])
        }
    }
    
    //再分别对左区与右区的数据进行同样的划分,直全部划分完
    quickSort(array: &left)
    quickSort(array: &right)
    
    //把参考值,左右两边的数据拼起来
    array = left + [base] + right
}


// MARK: - 快速排序,又称划分交换排序(partition-exchange sort)
// 划分交换的方式排序更省空间
func partitionExchangeSort(array:inout [Int],low:Int,hight:Int) {
    if(low < hight){
        //划分出一个参考值,小于参考值放左边,大于参考值的放右边
        let pi:Int = partition(array: &array, low: low, hight: hight)
        //对参考值左边的列表 递归调用快排方法
        partitionExchangeSort(array: &array, low: low, hight: pi - 1)
        //对参考值右边的列表 递归调用快排方法
        partitionExchangeSort(array: &array, low: pi + 1, hight: hight)
    }
    
}

//划分操作:比基准值小的摆放在基准前面,比基准值大的摆在基准的后面
func partition(array:inout [Int],low:Int,hight:Int) -> Int{
    //选最右边的作为基准值(参考值)
    let pivot = array[hight]
    
    //i用于指向一个更大的元素
    var i = low - 1
    
    //遍历并与参考值比较,注意这里运行了双指针技巧,i与j
//    for i in low ..< hight - 1 {
    for j in stride(from: low, to: hight, by: 1) {
        if array[j] <= pivot {
            //如果pivot值小,就把array[j]与(i+1位置)互换,相当于把j指针指的数挪到前面去,i指针指的数挪到后面
            i += 1
            array.swapAt(i, j)
        }
    }
    
    //遍历完后,把最尾部的参考值互换到(i+1)指针指的位置,这样就保证了(i+1)前面的元素肯定是小于Pivot的,其后面的数肯定是大于Pivot的
    array.swapAt(i+1, hight)
    
    return i + 1;
}


//打印
func printQuickSort(_ array:inout [Int]){
    //quickSort(array: &array)
    partitionExchangeSort(array: &array, low: 0, hight: array.count-1)
    print(array)
}

var arr:[Int] = [3, 2, 5, 7, 1, 5, 4, 8, 11, 0]
printQuickSort(&arr)

Python实现

# Quick sort in Python

# function to find the partition position
def partition(array, low, high):

  # choose the rightmost element as pivot
  pivot = array[high]

  # pointer for greater element
  i = low - 1

  # traverse through all elements
  # compare each element with pivot
  for j in range(low, high):
    if array[j] <= pivot:
      # if element smaller than pivot is found
      # swap it with the greater element pointed by i
      i = i + 1

      # swapping element at i with element at j
      (array[i], array[j]) = (array[j], array[i])

  # swap the pivot element with the greater element specified by i
  (array[i + 1], array[high]) = (array[high], array[i + 1])

  # return the position from where partition is done
  return i + 1

# function to perform quicksort
def quickSort(array, low, high):
  if low < high:

    # find pivot element such that
    # element smaller than pivot are on the left
    # element greater than pivot are on the right
    pi = partition(array, low, high)

    # recursive call on the left of pivot
    quickSort(array, low, pi - 1)

    # recursive call on the right of pivot
    quickSort(array, pi + 1, high)


data = [8, 7, 2, 1, 0, 9, 6]
print("Unsorted Array")
print(data)

size = len(data)

quickSort(data, 0, size - 1)

print('Sorted Array in Ascending Order:')
print(data)

Java实现

// Quick sort in Java

import java.util.Arrays;

class Quicksort {

  // method to find the partition position
  static int partition(int array[], int low, int high) {
    
    // choose the rightmost element as pivot
    int pivot = array[high];
    
    // pointer for greater element
    int i = (low - 1);

    // traverse through all elements
    // compare each element with pivot
    for (int j = low; j < high; j++) {
      if (array[j] <= pivot) {

        // if element smaller than pivot is found
        // swap it with the greatr element pointed by i
        i++;

        // swapping element at i with element at j
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
      }

    }

    // swapt the pivot element with the greater element specified by i
    int temp = array[i + 1];
    array[i + 1] = array[high];
    array[high] = temp;

    // return the position from where partition is done
    return (i + 1);
  }

  static void quickSort(int array[], int low, int high) {
    if (low < high) {

      // find pivot element such that
      // elements smaller than pivot are on the left
      // elements greater than pivot are on the right
      int pi = partition(array, low, high);
      
      // recursive call on the left of pivot
      quickSort(array, low, pi - 1);

      // recursive call on the right of pivot
      quickSort(array, pi + 1, high);
    }
  }
}

// Main class
class Main {
  public static void main(String args[]) {

    int[] data = { 8, 7, 2, 1, 0, 9, 6 };
    System.out.println("Unsorted Array");
    System.out.println(Arrays.toString(data));

    int size = data.length;

    // call quicksort() on array data
    Quicksort.quickSort(data, 0, size - 1);

    System.out.println("Sorted Array in Ascending Order: ");
    System.out.println(Arrays.toString(data));
  }
}

C 实现

// Quick sort in C

#include <stdio.h>

// function to swap elements
void swap(int *a, int *b) {
  int t = *a;
  *a = *b;
  *b = t;
}

// function to find the partition position
int partition(int array[], int low, int high) {
  
  // select the rightmost element as pivot
  int pivot = array[high];
  
  // pointer for greater element
  int i = (low - 1);

  // traverse each element of the array
  // compare them with the pivot
  for (int j = low; j < high; j++) {
    if (array[j] <= pivot) {
        
      // if element smaller than pivot is found
      // swap it with the greater element pointed by i
      i++;
      
      // swap element at i with element at j
      swap(&array[i], &array[j]);
    }
  }

  // swap the pivot element with the greater element at i
  swap(&array[i + 1], &array[high]);
  
  // return the partition point
  return (i + 1);
}

void quickSort(int array[], int low, int high) {
  if (low < high) {
    
    // find the pivot element such that
    // elements smaller than pivot are on left of pivot
    // elements greater than pivot are on right of pivot
    int pi = partition(array, low, high);
    
    // recursive call on the left of pivot
    quickSort(array, low, pi - 1);
    
    // recursive call on the right of pivot
    quickSort(array, pi + 1, high);
  }
}

// function to print array elements
void printArray(int array[], int size) {
  for (int i = 0; i < size; ++i) {
    printf("%d  ", array[i]);
  }
  printf("\n");
}

// main function
int main() {
  int data[] = {8, 7, 2, 1, 0, 9, 6};
  
  int n = sizeof(data) / sizeof(data[0]);
  
  printf("Unsorted Array\n");
  printArray(data, n);
  
  // perform quicksort on data
  quickSort(data, 0, n - 1);
  
  printf("Sorted array in ascending order: \n");
  printArray(data, n);
}

C++ 实现

// Quick sort in C++

#include <iostream>
using namespace std;

// function to swap elements
void swap(int *a, int *b) {
  int t = *a;
  *a = *b;
  *b = t;
}

// function to print the array
void printArray(int array[], int size) {
  int i;
  for (i = 0; i < size; i++)
    cout << array[i] << " ";
  cout << endl;
}

// function to rearrange array (find the partition point)
int partition(int array[], int low, int high) {
    
  // select the rightmost element as pivot
  int pivot = array[high];
  
  // pointer for greater element
  int i = (low - 1);

  // traverse each element of the array
  // compare them with the pivot
  for (int j = low; j < high; j++) {
    if (array[j] <= pivot) {
        
      // if element smaller than pivot is found
      // swap it with the greater element pointed by i
      i++;
      
      // swap element at i with element at j
      swap(&array[i], &array[j]);
    }
  }
  
  // swap pivot with the greater element at i
  swap(&array[i + 1], &array[high]);
  
  // return the partition point
  return (i + 1);
}

void quickSort(int array[], int low, int high) {
  if (low < high) {
      
    // find the pivot element such that
    // elements smaller than pivot are on left of pivot
    // elements greater than pivot are on righ of pivot
    int pi = partition(array, low, high);

    // recursive call on the left of pivot
    quickSort(array, low, pi - 1);

    // recursive call on the right of pivot
    quickSort(array, pi + 1, high);
  }
}

// Driver code
int main() {
  int data[] = {8, 7, 6, 1, 0, 9, 2};
  int n = sizeof(data) / sizeof(data[0]);
  
  cout << "Unsorted Array: \n";
  printArray(data, n);
  
  // perform quicksort on data
  quickSort(data, 0, n - 1);
  
  cout << "Sorted array in ascending order: \n";
  printArray(data, n);
}

版权所有,转载请注明出处 luowei.github.io.