详解快速排序

相信我们在没接触过排序知识之前,一定会觉得快速排序非常具有魅力,不因别的单纯快排这个名字就让人不明觉厉,但是了解一个算法不应该只知道code,了解思想,应用非常重要。

在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

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

快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。

快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快,而且效率高!它是处理大数据最快的排序算法之一了。虽然 Worst Case 的时间复杂度达到了 O(n²),但是人家就是优秀,在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好,可是这是为什么呢,我也不知道。好在我的强迫症又犯了,查了 N 多资料终于在《算法艺术与信息学竞赛》上找到了满意的答案:

快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。

1. 算法步骤

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

2. 动图演示

代码实现

JavaScript

实例

function quickSort(arr, left, right) {
   var len = arr.length,
       partitionIndex,
       left = typeof left != 'number' ? 0 : left,
       right = typeof right != 'number' ? len - 1 : right;

   if (left return arr;
}

function partition(arr, left ,right) {     // 分区操作
   var pivot = left,                      // 设定基准值(pivot)
       index = pivot + 1;
   for (var i = index; i if (arr[i] return index-1;
}

function swap(arr, i, j) {
   var temp = arr[i];
   arr[i] = arr[j];
   arr[j] = temp;
}
function partition2(arr, low, high) {
 let pivot = arr[low];
 while (low while (low  pivot) {
     --high;
   }
   arr[low] = arr[high];
   while (low return low;
}

function quickSort2(arr, low, high) {
 if (low let pivot = partition2(arr, low, high);
   quickSort2(arr, low, pivot - 1);
   quickSort2(arr, pivot + 1, high);
 }
 return arr;
}

Python

实例

def quickSort(arr, left=None, right=None):
   left = 0 if not isinstance(left,(int, float)) else left
   right = len(arr)-1 if not isinstance(right,(int, float)) else right
   if left return arr

def partition(arr, left, right):
   pivot = left
   index = pivot+1
   i = index
   while  i if arr[i] return index-1

def swap(arr, i, j):
   arr[i], arr[j] = arr[j], arr[i]

Go

实例

func quickSort(arr []int) []int {
       return _quickSort(arr, 0, len(arr)-1)
}

func _quickSort(arr []int, left, right int) []int {
       if left return arr
}

func partition(arr []int, left, right int) int {
       pivot := left
       index := pivot + 1

       for i := index; i if arr[i] return index - 1
}

func swap(arr []int, i, j int) {
       arr[i], arr[j] = arr[j], arr[i]
}

C++

实例

//严蔚敏《数据结构》标准分割函数
Paritition1(int A[], int low, int high) {
  int pivot = A[low];
  while (low while (low = pivot) {
      --high;
    }
    A[low] = A[high];
    while (low return low;
}

void QuickSort(int A[], int low, int high) //快排母函数
{
  if (low 

Java

实例

public class QuickSort implements IArraySort {

   @Override
   public int[] sort(int[] sourceArray) throws Exception {
       // 对 arr 进行拷贝,不改变参数内容
       int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

       return quickSort(arr, 0, arr.length - 1);
   }

   private int[] quickSort(int[] arr, int left, int right) {
       if (left return arr;
   }

   private int partition(int[] arr, int left, int right) {
       // 设定基准值(pivot)
       int pivot = left;
       int index = pivot + 1;
       for (int i = index; i if (arr[i] return index - 1;
   }

   private void swap(int[] arr, int i, int j) {
       int temp = arr[i];
       arr[i] = arr[j];
       arr[j] = temp;
   }

}

PHP

实例

function quickSort($arr)
{
   if (count($arr) return $arr;
   $middle = $arr[0];
   $leftArray = array();
   $rightArray = array();

   for ($i = 1; $i $arr); $i++) {
       if ($arr[$i] > $middle)
           $rightArray[] = $arr[$i];
       else
           $leftArray[] = $arr[$i];
   }
   $leftArray = quickSort($leftArray);
   $leftArray[] = $middle;

   $rightArray = quickSort($rightArray);
   return array_merge($leftArray$rightArray);
}

C

实例

typedef struct _Range {
   int start, end;
} Range;

Range new_Range(int s, int e) {
   Range r;
   r.start = s;
   r.end = e;
   return r;
}

void swap(int *x, int *y) {
   int t = *x;
   *x = *y;
   *y = t;
}

void quick_sort(int arr[], const int len) {
   if (len return; // 避免len等於負值時引發段錯誤(Segment Fault)
   // r[]模擬列表,p為數量,r[p++]為push,r[--p]為pop且取得元素
   Range r[len];
   int p = 0;
   r[p++] = new_Range(0, len - 1);
   while (p) {
       Range range = r[--p];
       if (range.start >= range.end)
           continue;
       int mid = arr[(range.start + range.end) / 2]; // 選取中間點為基準點
       int left = range.start, right = range.end;
       do {
           while (arr[left] while (arr[right] > mid) --right; //檢測基準點右側是否符合要求
           if (left while (left if (range.start if (range.end > left) r[p++] = new_Range(left, range.end);
   }
}

递归法

实例

void swap(int *x, int *y) {
   int t = *x;
   *x = *y;
   *y = t;
}

void quick_sort_recursive(int arr[], int start, int end) {
   if (start >= end)
       return;
   int mid = arr[end];
   int left = start, right = end - 1;
   while (left while (arr[left] while (arr[right] >= mid && left if (arr[left] >= arr[end])
       swap(&arr[left], &arr[end]);
   else
       left++;
   if (left)
       quick_sort_recursive(arr, start, left - 1);
   quick_sort_recursive(arr, left + 1, end);
}

void quick_sort(int arr[], int len) {
   quick_sort_recursive(arr, 0, len - 1);
}

C++

函数法

sort(a,a + n);// 排序a[0]-a[n-1]的所有数.

迭代法

实例

// 参考:http://www.dutor.net/index.php/2011/04/recursive-iterative-quick-sort/
struct Range {
   int start, end;
   Range(int s = 0, int e = 0) {
       start = s, end = e;
   }
};
template  // 整數或浮點數皆可使用,若要使用物件(class)時必須設定"小於"("大於"(>)、"不小於"(>=)的運算子功能
void quick_sort(T arr[], const int len) {
   if (len return; // 避免len等於負值時宣告堆疊陣列當機
   // r[]模擬堆疊,p為數量,r[p++]為push,r[--p]為pop且取得元素
   Range r[len];
   int p = 0;
   r[p++] = Range(0, len - 1);
   while (p) {
       Range range = r[--p];
       if (range.start >= range.end)
           continue;
       T mid = arr[range.end];
       int left = range.start, right = range.end - 1;
       while (left while (arr[left] while (arr[right] >= mid && left if (arr[left] >= arr[range.end])
           std::swap(arr[left], arr[range.end]);
       else
           left++;
       r[p++] = Range(range.start, left - 1);
       r[p++] = Range(left + 1, range.end);
   }
}

递归法

实例

template
void quick_sort_recursive(T arr[], int start, int end) {
   if (start >= end)
       return;
   T mid = arr[end];
   int left = start, right = end - 1;
   while (left while (arr[left] while (arr[right] >= mid && left if (arr[left] >= arr[end])
       std::swap(arr[left], arr[end]);
   else
       left++;
   quick_sort_recursive(arr, start, left - 1);
   quick_sort_recursive(arr, left + 1, end);
}
template  //整數或浮點數皆可使用,若要使用物件(class)時必須設定"小於"("大於"(>)、"不小於"(>=)的運算子功能
void quick_sort(T arr[], int len) {
   quick_sort_recursive(arr, 0, len - 1);
}

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/219385.html<

(0)
运维的头像运维
上一篇2025-04-14 02:18
下一篇 2025-04-14 02:20

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注