快速排序的深入詳解以及java實(shí)現(xiàn)
更新時(shí)間:2013年07月03日 08:59:30 作者:
本篇文章是對(duì)java中的快速排序進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
快速排序作為一種高效的排序算法被廣泛應(yīng)用,SUN的JDK中的Arrays.sort 方法用的就是快排。
快排采用了經(jīng)典的分治思想(divide and conquer):
Divide:選取一個(gè)基元X(一般選取數(shù)組第一個(gè)元素),通過某種分區(qū)操作(partitioning)將數(shù)組劃分為兩個(gè)部分:左半部分小于等于X,右半部分大于等于X。
Conquer: 左右兩個(gè)子數(shù)組遞歸地調(diào)用Divide過程。
Combine:快排作為就地排序算法(in place sort),不需要任何合并操作
可以看出快排的核心部分就是劃分過程(partitioning),下面以一個(gè)實(shí)例來詳細(xì)解釋如何劃分?jǐn)?shù)組(圖取自于《算法導(dǎo)論》)
初始化:選取基元P=2,就是數(shù)組首元素。i=1,j=i+1=2 (數(shù)組下標(biāo)以1開頭)
循環(huán)不變量:2~i之間的元素都小于或等于P,i+1~j之間的元素都大于或等于P
循環(huán)過程:j從2到n,考察j位置的元素,如果大于等于P,就繼續(xù)循環(huán)。如果小于P,就將j位置的元素(不應(yīng)該出現(xiàn)在i+1~j這個(gè)區(qū)間)和i+1位置(交換之后仍在i+1~j區(qū)間)的元素交換位置,同時(shí)將i+1.這樣就維持了循環(huán)不變量(見上述循環(huán)不變量說明)。直到j(luò)=n,完成最后一次循環(huán)操作。
要注意的是在完成循環(huán)后,還需要將i位置的元素和數(shù)組首元素交換以滿足我們最先設(shè)定的要求(對(duì)應(yīng)圖中的第i步)。
細(xì)心的讀者可能會(huì)想到另一種更直白的分區(qū)方法,即將基元取出存在另一相同大小數(shù)組中,遇到比基元小的元素就存儲(chǔ)在數(shù)組左半部分,遇到比基元大的元素就存儲(chǔ)在數(shù)組右半部分。這樣的操作復(fù)雜度也是線性的,即Theta(n)。但是空間復(fù)雜度提高了一倍。這也是快排就地排序的優(yōu)勢(shì)所在。

public class QuickSort {
private static void QuickSort(int[] array,int start,int end)
{
if(start<end)
{
int key=array[start];//初始化保存基元
int i=start,j;//初始化i,j
for(j=start+1;j<=end;j++)
if(array[j]<key)//如果此處元素小于基元,則把此元素和i+1處元素交換,并將i加1,如大于或等于基元?jiǎng)t繼續(xù)循環(huán)
{
int temp=array[j];
array[j]=array[i+1];
array[i+1]=temp;
i++;
}
}
array[start]=array[i];//交換i處元素和基元
array[i]=key;
QuickSort(array, start, i-1);//遞歸調(diào)用
QuickSort(array, i+1, end);
}
}
public static void main(String[] args)
{
int[] array=new int[]{11,213,134,44,77,78,23,43};
QuickSort(array, 0, array.length-1);
for(int i=0;i<array.length;i++)
{
System.out.println((i+1)+"th:"+array[i]);
}
}
}
快排采用了經(jīng)典的分治思想(divide and conquer):
Divide:選取一個(gè)基元X(一般選取數(shù)組第一個(gè)元素),通過某種分區(qū)操作(partitioning)將數(shù)組劃分為兩個(gè)部分:左半部分小于等于X,右半部分大于等于X。
Conquer: 左右兩個(gè)子數(shù)組遞歸地調(diào)用Divide過程。
Combine:快排作為就地排序算法(in place sort),不需要任何合并操作
可以看出快排的核心部分就是劃分過程(partitioning),下面以一個(gè)實(shí)例來詳細(xì)解釋如何劃分?jǐn)?shù)組(圖取自于《算法導(dǎo)論》)
初始化:選取基元P=2,就是數(shù)組首元素。i=1,j=i+1=2 (數(shù)組下標(biāo)以1開頭)
循環(huán)不變量:2~i之間的元素都小于或等于P,i+1~j之間的元素都大于或等于P
循環(huán)過程:j從2到n,考察j位置的元素,如果大于等于P,就繼續(xù)循環(huán)。如果小于P,就將j位置的元素(不應(yīng)該出現(xiàn)在i+1~j這個(gè)區(qū)間)和i+1位置(交換之后仍在i+1~j區(qū)間)的元素交換位置,同時(shí)將i+1.這樣就維持了循環(huán)不變量(見上述循環(huán)不變量說明)。直到j(luò)=n,完成最后一次循環(huán)操作。
要注意的是在完成循環(huán)后,還需要將i位置的元素和數(shù)組首元素交換以滿足我們最先設(shè)定的要求(對(duì)應(yīng)圖中的第i步)。
細(xì)心的讀者可能會(huì)想到另一種更直白的分區(qū)方法,即將基元取出存在另一相同大小數(shù)組中,遇到比基元小的元素就存儲(chǔ)在數(shù)組左半部分,遇到比基元大的元素就存儲(chǔ)在數(shù)組右半部分。這樣的操作復(fù)雜度也是線性的,即Theta(n)。但是空間復(fù)雜度提高了一倍。這也是快排就地排序的優(yōu)勢(shì)所在。

復(fù)制代碼 代碼如下:
public class QuickSort {
private static void QuickSort(int[] array,int start,int end)
{
if(start<end)
{
int key=array[start];//初始化保存基元
int i=start,j;//初始化i,j
for(j=start+1;j<=end;j++)
if(array[j]<key)//如果此處元素小于基元,則把此元素和i+1處元素交換,并將i加1,如大于或等于基元?jiǎng)t繼續(xù)循環(huán)
{
int temp=array[j];
array[j]=array[i+1];
array[i+1]=temp;
i++;
}
}
array[start]=array[i];//交換i處元素和基元
array[i]=key;
QuickSort(array, start, i-1);//遞歸調(diào)用
QuickSort(array, i+1, end);
}
}
public static void main(String[] args)
{
int[] array=new int[]{11,213,134,44,77,78,23,43};
QuickSort(array, 0, array.length-1);
for(int i=0;i<array.length;i++)
{
System.out.println((i+1)+"th:"+array[i]);
}
}
}
相關(guān)文章
Java自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏
在實(shí)際開發(fā)中經(jīng)常會(huì)遇到有一些信息不能全部展示用戶,需要隱藏(可以叫脫敏),所以本文為大家分享了利用自定義注解實(shí)現(xiàn)數(shù)據(jù)脫敏的示例代碼,需要的可以參考下2023-07-07
idea遠(yuǎn)程Debug部署在服務(wù)器上的服務(wù)
在開發(fā)的時(shí)候我們通常在本地代碼上debug程序,但是服務(wù)部署到了開發(fā)環(huán)境服務(wù)器上,如何遠(yuǎn)程調(diào)試,本文主要介紹了idea遠(yuǎn)程Debug部署在服務(wù)器上的服務(wù),具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12
SpringBoot配置Profile實(shí)現(xiàn)多環(huán)境支持
這篇文章主要介紹了SpringBoot配置Profile實(shí)現(xiàn)多環(huán)境支持操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
@Valid和@Validated注解校驗(yàn)以及異常處理方式
在Javaweb開發(fā)中,防止數(shù)據(jù)庫惡意攻擊是至關(guān)重要的,盡管前端校驗(yàn)可以起到一定的篩選作用,但通過工具如postman直接對(duì)后端發(fā)起請(qǐng)求的情況仍然需要后端進(jìn)行嚴(yán)格的數(shù)據(jù)校驗(yàn),Java生態(tài)下,@Valid注解配合SpringBoot提供了一個(gè)便捷高效的后端數(shù)據(jù)校驗(yàn)方案2024-11-11
java使用DelayQueue實(shí)現(xiàn)延時(shí)任務(wù)
項(xiàng)目中經(jīng)常會(huì)用到類似一些需要延遲執(zhí)行的功能,比如緩存,java提供了DelayQueue來很輕松的實(shí)現(xiàn)這種功能,下面小編就來和大家介紹一下如何使用DelayQueue實(shí)現(xiàn)延時(shí)任務(wù)吧2023-10-10

