快速排序是一種高效的排序演算法,基於分治策略。是面試中頻繁考察的重點之一。
原理:它選擇一個基準元素,透過一趟排序將待排序序列分割成兩部分。其中一部分的所有元素都比基準元素小,另一部分則比基準元素大。然後,對這兩部分分別進行快速排序,整個序列就逐步變得有序。
實現思路:
- 首先,在序列中選擇一個基準元素,常見的是選擇第一個或最後一個元素。
- 接著,從序列的兩端開始設定兩個指標,一個從左向右,一個從右向左。左指標尋找大於基準的元素,右指標尋找小於基準的元素,當找到後交換這兩個元素。
- 持續這個過程,直到兩個指標相遇,此時將基準元素與相遇位置的元素交換,這樣就完成了一次劃分。
- 遞迴地對劃分後的兩個子序列重複上述操作,直到子序列的長度為 1 或 0,此時整個序列排序完成。它的平均時間複雜度為O(n log n) ,但在最壞情況下可能退化為 O(n2)。
本文使用 C、C++ 、Python、Java、Kotlin、Swift、JavaScript、Rust 和 Go 9 種主流程式語言實現快速排序演算法。
1. C語言
#include <stdio.h>
// 交換兩個元素的值
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 核心程式碼,理解了這個函式就理解了整個演算法。
// 劃分函式1,以最後一個元素為基準,將小於基準的元素放在左邊,大於基準的元素放在右邊
int partition(int arr[], int low, int high) {
int pivot = arr[low];
int start = low;
while (low < high) {
while (low < high && arr[high] >= pivot) {
high--;
}
while (low < high && arr[low] <= pivot) {
low++;
}
swap(&arr[low], &arr[high]);
}
swap(&arr[start], &arr[low]);
return low;
}
// 劃分函式2,其它語言參考該方法即可
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // 選擇最後一個元素作為基準
int i = low - 1; // i 是小於基準的元素的索引
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]); // 關鍵,將基準元素放到正確位置
return i + 1;
}
// 快速排序函式
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1); // 遞迴排序左半部分
quickSort(arr, pi + 1, high); // 遞迴排序右半部分
}
}
// 列印陣列
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
}
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原始陣列:\n");
printArray(arr, n);
quickSort(arr, 0, n - 1);
printf("排序後的陣列:\n");
printArray(arr, n);
return 0;
}
2. C++
#include <iostream>
using namespace std;
// 劃分函式1
int partition(vector<int>& nums, int low, int high) {
int pivot = nums[low];
int start = low;
while (low < high) {
while (low < high && nums[high] >= pivot) high--;
while (low < high && nums[low] <= pivot) low++;
if (low >= high) {
break;
}
swap(nums[low], nums[high]);
}
swap(nums[start], nums[low]);
return low;
}
// 劃分函式2
int partition(vector<int>& arr, int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}
swap(arr[i + 1], arr[high]);
return i + 1;
}
// 快速排序函式
void quickSort(vector<int>& arr, int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
vector<int> arr = {10, 7, 8, 9, 1, 5};
cout << "原始陣列:";
for (int num : arr) cout << num << " ";
cout << endl;
quickSort(arr, 0, arr.size() - 1);
cout << "排序後的陣列:";
for (int num : arr) cout << num << " ";
cout << endl;
return 0;
}
3. Python
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
# 劃分函式1
def partition(arr, low, high):
pivot = arr[low]
start = low
while low < high:
while low < high and arr[high] >= pivot:
high -= 1
while low < high and arr[low] <= pivot:
low += 1
if low >= high:
break
swap(arr, low, high)
swap(arr, start, low)
return low
# 劃分函式2
def partition(arr, low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] < pivot:
i += 1
swap(arr, i, j)
swap(arr, i + 1, high)
return i + 1
def quick_sort(arr):
low, high = 0, len(arr) - 1
while low < high:
pivot = partition(arr, low, high)
quick_sort(arr[low:pivot])
quick_sort(arr[pivot + 1:high + 1])
arr = [10, 7, 8, 9, 1, 5]
print("原始陣列:", arr)
quick_sort(arr)
print("排序後的陣列:", arr)
4. Java
遞迴
public class QuickSortJava {
static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 劃分函式1
static int partition(int[] nums, int low, int high) {
int pivot = nums[low]; // 選定陣列第一個元素作為基準值
int start = low; // 記錄基準值的初始位置
while (low < high) {
// 從右向左找第一個小於基準值的元素
while (low < high && nums[high] >= pivot) {
high--;
}
// 從左向右找第一個大於基準值的元素
while (low < high && nums[low] <= pivot) {
low++;
}
// 如果low和high沒有交錯,交換它們找到的元素
if (low >= high) {
break;
}
swap(nums, low, high);
}
// 基準值歸位:將基準值放到low(或high,此時它們相等)的位置上
swap(nums, start, low);
// 返回基準值的最終位置
return low;
}
// 劃分函式2
static int partition(int[] arr, int low, int high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(arr, i, j);
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
static void quickSort(int[] arr, int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
static void main(String[] args) {
int[] arr = {10, 7, 8, 9, 1, 5};
quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
非遞迴
import java.util.Stack;
class Solution {
public int[] quickSort(int[] nums) {
Stack<Integer> stack = new Stack<>();
stack.push(nums.length - 1);
stack.push(0);
while (!stack.isEmpty()) {
int low = stack.pop();
int high = stack.pop();
if (low < high) {
int index = partition(nums, low, high);
// Push right, middle, and left indices in correct order
stack.push(index - 1);
stack.push(low);
stack.push(high);
stack.push(index + 1);
}
}
return nums;
}
private int partition(int[] nums, int low, int high) {
int pivot = nums[low];
int start = low;
while (low < high) {
while (low < high && nums[high] >= pivot) {
high--;
}
while (low < high && nums[low] <= pivot) {
low++;
}
if (low >= high) {
break;
}
swap(nums, low, high);
}
swap(nums, start, low); // 關鍵,將基準元素放到正確位置
return low;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
5. Kotlin
fun swap(arr: IntArray, i: Int, j: Int) {
val temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
// 劃分函式1
fun partition(nums: IntArray, low: Int, high: Int): Int {
val pivot = nums[low]
var start = low
while (low < high) {
while (low < high && nums[high] >= pivot) {
high--
}
while (low < high && nums[low] <= pivot) {
low++
}
if (low >= high) {
break
}
swap(nums, low, high)
}
swap(nums, start, low)
return low
}
// 劃分函式2
fun partition(arr: IntArray, low: Int, high: Int): Int {
val pivot = arr[high]
var i = low - 1
for (j in low until high) {
if (arr[j] < pivot) {
i++
swap(arr, i, j)
}
}
swap(arr, i + 1, high)
return i + 1
}
fun quickSort(arr: IntArray) {
var low = 0
var high = arr.size - 1
while (low < high) {
val pivot = partition(arr, low, high)
quickSort(arr.copyOfRange(low, pivot))
quickSort(arr.copyOfRange(pivot + 1, high + 1))
}
}
fun main() {
val arr = intArrayOf(10, 7, 8, 9, 1, 5)
println("原始陣列: ${arr.joinToString()}")
quickSort(arr)
println("排序後的陣列: ${arr.joinToString()}")
}
6. Swift
func partition(_ nums: inout [Int], low: Int, high: Int) -> Int {
let pivot = nums[low]
var start = low
while low < high {
while low < high && nums[high] >= pivot {
high -= 1
}
while low < high && nums[low] <= pivot {
low += 1
}
if low >= high {
break
}
swap(&nums, low, high)
}
swap(&nums, start, low)
return low
}
func partition(_ arr: inout [Int], low: Int, high: Int) -> Int {
let pivot = arr[high]
var i = low - 1
for j in low..<high {
if arr[j] < pivot {
i += 1
swap(&arr, i, j)
}
}
swap(&arr, i + 1, high)
return i + 1
}
func quickSort(_ arr: inout [Int]) {
var low = 0
var high = arr.count - 1
while low < high {
let pivot = partition(&arr, low: low, high: high)
if pivot - low < high - pivot {
quickSort(&arr[low..<pivot])
low = pivot + 1
} else {
quickSort(&arr[(pivot + 1)...high])
high = pivot - 1
}
}
}
var arr = [10, 7, 8, 9, 1, 5]
print("原始陣列: \(arr)")
quickSort(&arr)
print("排序後的陣列: \(arr)")
7. JavaScript
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
function partition(nums, low, high) {
let pivot = nums[low];
let start = low;
while (low < high) {
while (low < high && nums[high] >= pivot) {
high--;
}
while (low < high && nums[low] <= pivot) {
low++;
}
if (low >= high) {
break;
}
swap(nums, low, high);
}
swap(nums, start, low);
return low;
}
function partition(arr, low, high) {
const pivot = arr[high];
let i = low - 1;
for (let j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, high);
return i + 1;
}
function quickSort(arr) {
let low = 0;
let high = arr.length - 1;
while (low < high) {
const pivot = partition(arr, low, high);
if (pivot - low < high - pivot) {
quickSort(arr.slice(low, pivot));
low = pivot + 1;
} else {
quickSort(arr.slice(pivot + 1, high + 1));
high = pivot - 1;
}
}
}
const arr = [10, 7, 8, 9, 1, 5];
console.log("原始陣列:", arr);
quickSort(arr);
console.log("排序後的陣列:", arr);
8. Rust
fn swap(arr: &mut Vec<i32>, i: usize, j: usize) {
arr.swap(i, j);
}
fn partition(nums: &mut [i32], low: usize, high: usize) -> usize {
let pivot = nums[low];
let mut start = low;
let mut low = low;
let mut high = high;
while low < high {
while low < high && nums[high] >= pivot {
high -= 1;
}
while low < high && nums[low] <= pivot {
low += 1;
}
if low >= high {
break;
}
nums.swap(low, high);
}
nums.swap(start, low);
low
}
fn partition(arr: &mut Vec<i32>, low: usize, high: usize) -> usize {
let pivot = arr[high];
let mut i = low as isize - 1;
for j in low..high {
if arr[j] < pivot {
i += 1;
swap(arr, i as usize, j);
}
}
swap(arr, (i + 1) as usize, high);
(i + 1) as usize
}
fn quick_sort(arr: &mut Vec<i32>) {
let mut low = 0;
let mut high = arr.len() - 1;
while low < high {
let pivot = partition(arr, low, high);
quick_sort(&mut arr[low..pivot].to_vec());
quick_sort(&mut arr[(pivot + 1)..=high].to_vec());
}
}
fn main() {
let mut arr = vec![10, 7, 8, 9, 1, 5];
println!("原始陣列: {:?}", arr);
quick_sort(&mut arr);
println!("排序後的陣列: {:?}", arr);
}
9. Go
package main
import (
"fmt"
)
func swap(arr []int, i, j int) {
arr[i], arr[j] = arr[j], arr[i]
}
func partition(nums []int, low, high int) int {
pivot := nums[low]
start := low
for low < high {
for low < high && nums[high] >= pivot {
high--
}
for low < high && nums[low] <= pivot {
low++
}
if low >= high {
break
}
swap(nums, low, high)
}
swap(nums, start, low)
return low
}
func partition(arr []int, low, high int) int {
pivot := arr[high]
i := low - 1
for j := low; j < high; j++ {
if arr[j] < pivot {
i++
swap(arr, i, j)
}
}
swap(arr, i+1, high)
return i + 1
}
func quickSort(arr []int) {
low := 0
high := len(arr) - 1
for low < high {
pivot := partition(arr, low, high)
quickSort(arr[low:pivot])
quickSort(arr[pivot+1 : high+1])
}
}
func main() {
arr := []int{10, 7, 8, 9, 1, 5}
fmt.Println("原始陣列:", arr)
quickSort(arr)
fmt.Println("排序後的陣列:", arr)
}
以上程式碼分別展示了不同程式語言實現非遞迴的快速排序演算法。希望這篇文章能對你有所幫助,記得收藏起來哦,方便隨時查閱和複習。