1. 程式人生 > >快速排序演算法及時間複雜度分析(原地in-place分割槽版本)

快速排序演算法及時間複雜度分析(原地in-place分割槽版本)

快速排序演算法一般來說是採用遞迴來實現,其最關鍵的函式是partition分割函式,其功能是將陣列劃分為兩部分,一部分小於選定的pivot,另一部分大於選定的pivot。我們將重點放在該函式上面。

partition函式總體思路是自從一邊查詢,找到小於pivot的元素,則將其放到前面去,這樣要達到的目的是使小於pivot的元素全部在前面,則大於pivot的元素就必然都在後面了。要達到此目的,有一點必須注意,就是在講小於pivot的元素放到前面去的時候,一定要是緊挨著存放,否則空隙裡面放的就可能會是大於pivot的元素,所以我們設定了一個storeIndex變數,並初始化為left來依次緊挨著存放小於pivot的元素。

由於剛開始並不知道最後pivot的存放位置,所以,需要先將pivot交換到後面去(如果是將大的元素依次放到後面就不需要這樣的交換),然後遍歷陣列,找到小於的pivot的元素,就將其放到storeIndex處,並將storeIndex加1。在partition函式最後將pivot交換到storeIndex處。

在quicksort函式中,應特別注意!首先應當判斷left時候小於right,以此作為遞迴返回的條件,還需根據條件設定pivot。

至於時間複雜度,考慮平均複雜度,即每次都是均等二分,一共會有logn層,每層都會遍歷到陣列幾乎所有元素,為O(n),所以直觀上我們可以看出平均複雜度為O(nlogn)。而,同理最壞時間複雜度為O(n^2)。正規分析如下:

平均時間複雜度T(n)=O(n)+2T(n/2),最壞複雜度T(n)=O(n)+T(n-1)。通過推導,我們也很容易得到上述結論。

程式碼如下:

#include<iostream>

using namespace std;

int a[] = { 1, 2, 8, 7, 9, 5, 6, 4, 3, 66, 77, 33, 22, 11 }; //用於測試,從小到大排序


/* 輸出陣列前n各元素 */
void prt(int n)
{
    int i;
    for (i = 0; i < n; i++) 
   {
        printf("%d\t", a[i]);
    }
    printf("\n");
}
/*交換兩值*/
void swap(int &p,int &q)
{
	int temp=p;
	p=q;
	q=temp;
}


/*劃分函式*/
int partition(int a[],int left,int right,int pivotIndex) // 將pivotIndex的選取放在函式外面做
{
	int pivotValue=a[pivotIndex];
	swap(a[pivotIndex],a[right]); //將pivot放到結尾
	int storeIndex=left; // 用於指示比pivotValue值小的數值應該存放的位置
	for(int i=left;i<right;i++)
	{
		if(a[i]<pivotValue) // 找到了比pivotValue小的值
		{
			swap(a[i],a[storeIndex]);
			storeIndex++;
		}
	}
	swap(a[storeIndex],a[right]); //將pivot放到其最終的位置上
	return storeIndex;
}


void quicksort(int a[],int left,int right)
{
	if(left<right) //該判斷很重要
	{
		int pivotIndex=left; //選取pivot
		int pivotNewIndex=partition(a,left,right,pivotIndex);
		quicksort(a,left,pivotNewIndex-1);
		quicksort(a,pivotNewIndex+1,right);
	}
}


int main(void) {
    /* 排序與輸出 */
    quicksort(a, 0, 13);
    prt(14);
    return 0;
}

相關推薦

快速排序演算法時間複雜分析原地in-place分割槽版本

快速排序演算法一般來說是採用遞迴來實現,其最關鍵的函式是partition分割函式,其功能是將陣列劃分為兩部分,一部分小於選定的pivot,另一部分大於選定的pivot。我們將重點放在該函式上面。 partition函式總體思路是自從一邊查詢,找到小於pivot的元素,則將

排序演算法時間複雜分析

堆其實通常是通過一維陣列來實現的,在陣列起始下標為0的情況下,父節點i的左右子節點分別為2*i+1和2*i+2,子節點i的父節點為(i-1)/2。對堆的操作主要有建堆、調整堆、堆排序、插入和刪除堆中元素。其中調整堆是核心。下面將重點介紹兩種調整堆的方法。 向下調整堆(shi

快速排序實現以及時間複雜分析

平均時間複雜度分析: T(1) = 1; T(n) = 2*T(n/2) + a*n;(a為常數,每次合併時,複雜度為O(n)) = 2*(2*T(n/4)+a*n/2) + a*n = 4*T(n/4) + 2*a*n = 4*(2*T(n/8)+a*n/4) + 2*a*n = 8*T(n/8) + 3

快速排序時間複雜分析

它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料

常用排序演算法時間複雜和空間複雜特點

一、常用排序演算法的時間複雜度和空間複雜度表格 二、特點 1.歸併排序: (1)n大時好,歸併比較佔用記憶體,記憶體隨n的增大而增大,但卻是效率高且穩定的排序演算法。 (2)歸併排序每次遞迴都要用到一個輔助表,長度與待排序的表長度相同,雖然遞迴次數是O(log2n),但每次

排序的JAVA實現時間複雜分析

堆排序是一個比較常用的排序方式,下面是其JAVA的實現: 1. 建堆 // 對輸入的陣列進行建堆的操作 private static void buildMaxHeap(int[] array, int length) { // 遍歷所有

KMP演算法介紹時間複雜分析

概念:字串中 一個字元前面的字串 的字首與字尾的最長匹配長度(短的那個字串) 注意:字首與字尾不可以是整個子字串 例如:a b c a b c d , d位置的最長匹配長度為3,abc 與 abc 匹配 Next陣列:長度與字串長度一致,每個位置儲存對應字元的最長匹配長

八種排序演算法時間複雜複雜

https://www.cnblogs.com/dll-ft/p/5861210.html 轉載 1、穩定性 歸併排序、氣泡排序、插入排序。基數排序是穩定的 選擇排序、快速排序、希爾排序、堆排序是不穩定的   2、時間複雜度 最基礎的四個演算法:冒泡、選擇

各種排序演算法時間複雜

選擇排序、快速排序、希爾排序、堆排序不是穩定的排序演算法, 氣泡排序、插入排序、歸併排序和基數排序是穩定的排序演算法。 排序演算法不穩定的含義是:在排序之前,有兩個數相等. 但是在排序結束之後,它們兩個有可能改變順序. 比如說:  在一個待排序佇列中,A和B相等,且A排在

遞迴演算法時間複雜分析

在演算法分析中,當一個演算法中包含遞迴呼叫時,其時間複雜度的分析會轉化為一個遞迴方程求解。實際上,這個問題是數學上求解漸近階的問題,而遞迴方程的形式多種多樣,其求解方法也是不一而足,比較常用的有以下四種方法:     (1)代入法(Substitution Method)  

常用排序演算法以及時間複雜

希爾排序 快速排序 二叉樹排序 氣泡排序 選擇排序 堆排序 #include <iostream.h> #include <conio.h> #include <stdlib.h> #include <time.h>

實現排序演算法時間複雜為O(n)

我們常用的排序氣泡排序 O(n^2); 快速排序O(nlogn);堆排序O(nlogn);選擇排序O(n^2); 我們常用的排序都不符合時間複雜度的要求; 經常聽說一個說法  用空間代替時間 現在要排序的陣列為陣列 a;例如a數組裡面有  1,1,2,2,3,3,2,2,5

【整理】常見排序演算法及其時間複雜總結

原文出處: 本篇主要整理了氣泡排序,直接插入排序,直接選擇排序,希爾排序,歸併排序,快速排序,堆排序七種常見演算法,是從上面三篇博文中摘抄整理的,非原創。 一、氣泡排序 主要思路是: 通過交換相鄰的兩個數變成小數在前大數在後,這樣每次遍歷後,最大的數就“沉”到最後面了。重複N次即可以使陣列有序。 氣泡

氣泡排序演算法時間複雜和穩定性

氣泡排序 氣泡排序一般是我們學習排序演算法時第一個接觸的演算法,下面來介紹一下氣泡排序。 演算法原理 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。 對每一對相鄰元素做同樣的工作,從開始第一對到結尾的最後一對。在這一步,最後的元素應該會是最大

各個排序演算法時間複雜、空間複雜、穩定性

排序演算法分類 排序演算法比較表格填空 排序演算法比較表格 1 歸併排序可以通過手搖演算法將空間複雜度降到O(1),但是時間複雜度會提高。注: 2 基數排序時間複雜度為O(N*M),其中N為資料個數,M為資料位數。 輔助記憶 時間複雜度記憶-

關於基於比較的排序演算法時間複雜“最壞”下界o(nlogn)與“最優”下界o(n)說明

前言            之前在查詢基於比較排序演算法的時間複雜度時發現,好多博主對“最壞”下界與“最優”下界沒有分清,而是預設的把時間複雜度o(nlogn)當成了“最優”下界。這樣很是誤導大家,影響很不好。所以特此寫一篇說明文章,能讓大家理解得更透徹。 下界    

排序演算法時間複雜和空間複雜-----總結

演算法的時間複雜度是指:演算法執行過程中所需要的基本運算次數。 常見的演算法時間複雜度由小到大依次為:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n^2)<Ο(n^3)<…<Ο(2^n)<Ο(n!)。其中O(1)表示基本語句的執行次數是一個常數,一般來說,

插入排序演算法時間複雜和穩定性

插入排序 演算法原理 將資料分為有序部分和無序部分。 在無序部分選擇一個元素,按照順序插入到有序部分,使之有序。 直到無序部分都插入到有序部分結束。 演算法分析 排序的思想就是維護一個有序的部分,將無序部分的資料按照順序插入到有序部分。 通

常用的排序演算法時間複雜和空間複雜

排序法 最差時間分析 平均時間複雜度 穩定度 空間複雜度 氣泡排序 O(n2) O(n2) 穩定 O(1) 快速排序 O(n2) O(n*log2n) 不穩定 O(log2n)~O(n) 選擇排序 O(n2) O(n2) 穩定 O(1) 二叉樹排序 O(n2) O(n*log2

八大排序演算法時間複雜

排序演算法的穩定性: 假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,ri=rj,且ri在rj之前,而在排序後的序列中,ri仍