文章編號:10740時間:2024-09-29人氣:
快速排序是一種高效的排序算法,其核心思想是通過一趟排序將數組分割成兩部分,一部分所有數據小于另一部分,然后遞歸地對這兩部分進行排序。 理解這個過程的關鍵在于遞歸調用自身。
首先,我們從一個待排序的數組 A[1]...A[N] 出發。 選擇一個基準元素,通常選擇第一個元素作為起點,將其稱為 X。 接著,設立兩個指針 I 和 J,分別指向數組的起始和結束。
一趟快速排序 如此進行:從 J 開始向前搜索,遇到小于 X 的元素就將其與 I 位置的元素交換;同時,從 I 向后搜索,找到大于 X 的元素進行交換。 這個過程會一直持續,直到 I 和 J 指針相遇。
值得注意的是,快速排序的 遞歸特性:當劃分完成后,對左右兩部分再次執行相同的排序步驟,直到每個子數組只剩下一個元素或為空,遞歸結束。 這是一種典型的分治策略,每一次遞歸都將問題規模縮小,直至達到基本情況。
然而,快速排序并非 穩定排序,相同元素的相對位置可能會在排序過程中改變。 這源于交換操作,可能會打亂相同值的順序。
在代碼實現中,遞歸調用的偽代碼如下:
總的來說,快速排序的遞歸過程如同一場精密的舞者編排,每個元素都在有序與無序之間優雅地切換,直至整個序列井然有序。 希望這篇文章能幫助你深入了解快速排序的遞歸之美。
常見排序算法(冒泡,選擇,快速)的C語言實現要實現這幾種算法的關鍵是要熟悉算法的思想。
簡單的說,冒泡排序,就如名字說的,每經過一輪排序,將最大的數沉到最底部。
選擇排序的思想是將整個數列,分為有序區和無序區。
每輪排序,將無序區里的最小數移入到有序區。
快速排序的思想是以一個數為中心,通常這個數是該數列第一個數,將整個數列分為兩個部分,一個部分是大于這個數的區域,一個部分是小于這個數的區域。
然后再對這兩個部分的數列分別排序。
如果將數列分為兩個部分是通過,一方面從后向前的搜索,另一方面從前向后的搜索來實現的。
具體的參考后面的來自網絡百科的文檔。
從這幾個簡單的排序算法上看,有幾個特點:冒泡排序是最簡單的,也是最穩定的算法。
選擇排序不太穩定,但是效率上較冒泡還是有較大的提升。
其實在分析的過程中就能發現,選擇排序和冒泡排序相比,中間少了很多的交換過程,和比較的次數,這個應該是時間較少的原因。
選擇排序能夠滿足一般的使用。
當比較的數超過以萬為單位時,選擇排序也還是要一點時間的。
快速排序據說是最快的。
這個可以從思想上看的出來。
,當記錄較多的時候,快速排序的比較循環次數比上面2個都要少。
但是在具體的實現過程中,并不見得如此。
這是因為遞歸效率的低下導致的。
當然,估計在實際使用過的過程,快速排序估計都會使用非遞歸操作棧的方式來實現。
那樣應該會效率高傷不少。
估計我會在后期出一個快速排序的非遞歸實現來真正比較它們3個性能。
在下面的程序中,可以通過調高N的數字就能看的出來冒泡排序和選擇排序性能的差異。
在N較小,大概幾百的時候,是看不出來的。
N較大的的時候,比如N=1000或者N=的時候,快速排序的遞歸實現就會卡死在那里了,出不了結果。
以下是具體的代碼:/*** 常見排序算法比較 */#include
快速排序思想:通過對數據元素集合Rn 進行一趟排序劃分出獨立的兩個部分。 其中一個部分的關鍵字比另一部分的關鍵字小。 然后再分別對兩個部分的關鍵字進行一趟排序,直到獨立的元素只有一個,此時整個元素集合有序。 快速排序的過程,對一個元素集合R[ low ... high ] ,首先取一個數(一般是R[low] )做參照 , 以R[low]為基準重新排列所有的元素。 所有比R[low]小的放前面,所有比R[low] 大的放后面,然后以R[low]為分界,對R[low ... high] 劃分為兩個子集和,再做劃分。 直到low >=high 。 比如:對R={37, 40, 38, 42, 461, 5, 7, 9, 12}進行一趟快速排序的過程如下(注:下面描述的內容中元素下表從 0 開始):開始選取基準 base = 37,初始位置下表 low = 0 , high = 8, 從high=8,開始如果R[8] < base ,將high位置中的內容寫入到R[low]中, 將high位置空出來, low = low +1 ;從low開始探測,由于low=1 , R[low] > base ,所以將R[low]寫入到R[high] , high = high -1 ;檢測到low < high ,所以第一趟快速排序仍需繼續:此時low=1,high=7,因為 R[high] < base ,所以將 R[high] 寫入到到R[low]中,low = low + 1;從low開始探測,low = 2 , R[low] >base ,所以講R[low]寫入到R[high],high=high-1;繼續檢測到 low 小于high此時low=2,high=6,同理R[high] < base ,將R[high] 寫入到R[low]中,low=low+1;從low繼續探測,low = 3 , high=6 , R[low] > base , 將R[low]寫入到R[high]中,high = high-1;繼續探測到low小于high此時low=3,high=5,同理R[high] < base,將R[high]寫入到R[low]中,low = low +1;從low繼續探測,low = 4,high=5,由于R[low] > base , 將R[low]寫入到R[high]中,high = high -1 ;此時探測到low == high == 4 ;該位置即是base所在的位置,將base寫入到該位置中.然后再對子序列Rs1 = {12,9,7,5} 和 Rs2={461,42,38,40}做一趟快速排序,直到Rsi中只有一個元素,或沒有元素。 快速排序的Java實現:private static boolean isEmpty(int[] n) {return n == null || == 0;}// ////////////////////////////////////////////////////** * 快速排序算法思想——挖坑填數方法: * * @param n 待排序的數組 */public static void quickSort(int[] n) {if (isEmpty(n))return;quickSort(n, 0, - 1);}public static void quickSort(int[] n, int l, int h) {if (isEmpty(n))return;if (l < h) {int pivot = partion(n, l, h);quickSort(n, l, pivot - 1);quickSort(n, pivot + 1, h);}}private static int partion(int[] n, int start, int end) {int tmp = n[start];while (start < end) {while (n[end] >= tmp && start < end)end--;if (start < end) {n[start++] = n[end];}while (n[start] < tmp && start < end)start++;if (start < end) {n[end--] = n[start];}}n[start] = tmp;return start;}在代碼中有這樣一個函數:public static void quickSortSwap(int[] n, int l, int h)該函數可以實現,元素集合中特定的l到h 位置間的數據元素進行排序。
首先這個程序不是快速排序。 它是一個遞歸全排列生成的程序。 它是根據輸入的順序生成的。 只要你輸入 CBA ,輸出就是倒序的了。 你這里沒說清輸入的格式,所以沒法作出改動。 var str:string;l:longint;f:array[1..8]of boolean;//用來記錄每個字母是否用過procedure dfs(dep:longint;ans:string);vari:longint;beginif dep>l then//若l個字母都排好了就打印beginwriteln(ans);exit;end;for i:=1 to l do//檢測每一個字母if f[i]=false then//若第i個字母未用過beginf[i]:=true;//標記此字母已使用dfs(dep+1,ans+str[i]);{將str第i字母選為第dep個字母,再選下一個}f[i]:=false;//返回時將已用過的字母“還掉”不用了end;end;beginreadln(str);l:=length(str);fillchar(f,sizeof(f),0);//標記每個字母都未用過dfs(1,);end.
快速排序的基本思想就是從一個數組中任意挑選一個元素(通常來說會選擇最左邊的元素)作為中軸元素,將剩下的元素以中軸元素作為比較的標準,將小于等于中軸元素的放到中軸元素的左邊,將大于中軸元素的放到中軸元素的右邊。
然后以當前中軸元素的位置為界,將左半部分子數組和右半部分子數組看成兩個新的數組,重復上述操作,直到子數組的元素個數小于等于1(因為一個元素的數組必定是有序的)。
以下的代碼中會常常使用交換數組中兩個元素值的Swap方法,其代碼如下
publicstaticvoidSwap(int[] A, inti, intj){
A[i] = A[j];
擴展資料:
快速排序算法 的基本思想是:將所要進行排序的數分為左右兩個部分,其中一部分的所有數據都比另外一 部分的數據小,然后將所分得的兩部分數據進行同樣的劃分,重復執行以上的劃分操作,直 到所有要進行排序的數據變為有序為止。
定義兩個變量low和high,將low、high分別設置為要進行排序的序列的起始元素和最后一個元素的下標。 第一次,low和high的取值分別為0和n-1,接下來的每次取值由劃分得到的序列起始元素和最后一個元素的下標來決定。
定義一個變量key,接下來以key的取值為基準將數組A劃分為左右兩個部分,通 常,key值為要進行排序序列的第一個元素值。 第一次的取值為A[0],以后毎次取值由要劃 分序列的起始元素決定。
從high所指向的數組元素開始向左掃描,掃描的同時將下標為high的數組元素依次與劃分基準值key進行比較操作,直到high不大于low或找到第一個小于基準值key的數組元素,然后將該值賦值給low所指向的數組元素,同時將low右移一個位置。
如果low依然小于high,那么由low所指向的數組元素開始向右掃描,掃描的同時將下標為low的數組元素值依次與劃分的基準值key進行比較操作,直到low不小于high或找到第一個大于基準值key的數組元素,然后將該值賦給high所指向的數組元素,同時將high左移一個位置。
重復步驟(3) (4),直到low的植不小于high為止,這時成功劃分后得到的左右兩部分分別為A[low……pos-1]和A[pos+1……high],其中,pos下標所對應的數組元素的值就是進行劃分的基準值key,所以在劃分結束時還要將下標為pos的數組元素賦值 為 key。
參考資料:快速排序算法_網絡百科
內容聲明:
1、本站收錄的內容來源于大數據收集,版權歸原網站所有!
2、本站收錄的內容若侵害到您的利益,請聯系我們進行刪除處理!
3、本站不接受違法信息,如您發現違法內容,請聯系我們進行舉報處理!
4、本文地址:http://www.hudongshop.com/article/e1202a101487057780eb.html,復制請保留版權鏈接!
body,font,family,Arial,sans,serif,font,size,16px,line,height,1.5,h1,h2,h3,font,weight,bold,h1,font,size,24px,h2,font,size,20px,h3,font,size,18px,code,background,co...。
最新資訊 2024-09-26 23:30:44
引言NullPointerException,NPE,是Java程序中最常見的運行時異常之一,它可能導致不可預測的行為,從輕微的中斷到嚴重的系統故障,NPE的本質在于訪問一個未初始化或被顯式設置為null的對象引用,理解NPE及其潛在影響對于編寫穩定可靠的Java代碼至關重要,NPE的成因和診斷NPE發生在以下情況下,試圖調用或訪問未...。
最新資訊 2024-09-26 15:11:29
簡介JSONDecode是一個Python內置函數,用于從JSON字符串解析并創建Python對象,它提供了一個便捷的方法,允許我們輕松地處理JSON數據,該數據在數據交換和存儲中無處不在,函數語法```pythonjson.JSONDecodeError,msg,doc,pos,```msg,錯誤消息的文本描述,doc,要解析的JS...。
技術教程 2024-09-24 07:09:12
Node.js簡介Node.js是一個基于ChromeV8引擎構建的跨平臺JavaScript運行時環境,它使開發人員能夠使用JavaScript編寫服務器端應用程序,從而消除了前端和后端之間的語言障礙,全棧開發的好處全棧開發是一種軟件開發方法,其中開發人員負責應用程序的完整堆棧,從前端到后端,使用Node.js進行全棧開發具有以下好...。
最新資訊 2024-09-16 11:14:06
p>,以下代碼示例演示如何還原MySQL數據庫,mysql,uroot,pCREATEDATABASEIFNOTEXISTSmy,restored,db,USEmy,restored,db,SOURCE,path,to,my,backup.sql,PostgreSQL數據庫還原以下代碼示例演示如何還原PostgreSQL數據庫,p...。
最新資訊 2024-09-13 06:43:54
簡介ROW函數可用于從數據表中提取特定行的數據,它還可以自動更新序號,即使在刪除行之后亦是如此,此功能對于保持數據表中數據的完整性和準確性非常有用,語法```ROW,```其中,``是要提取數據的行的序號,示例假設我們有一個名為Students的數據表,其中包含以下數據,ID,姓名,年齡,1,JohnS...。
本站公告 2024-09-13 04:31:37
簡介rate函數是JavaScript中一個非常有用的函數,它允許我們以每秒的幀率,FPS,執行動畫,這使得創建平滑、流暢的動畫變得非常容易,語法rate函數的語法如下,```rate,framesPerSecond,```其中framesPerSecond是要執行動畫的幀率,FPS,基本用法要使用rate函數,我們只需要傳入所需的...。
互聯網資訊 2024-09-13 03:28:13
Linux定時任務Linux定時任務是一種強大的機制,允許用戶安排在特定時間或定期執行任務,它通常用于自動化任務,例如備份、系統維護或其他需要在特定時間或間隔執行的任務,創建定時任務要創建定時任務,可以使用crontab命令,crontab是一個文本文件,包含要安排執行的任務列表,它可以由用戶編輯,每個用戶都有自己的crontab文件...。
最新資訊 2024-09-12 11:34:46
對于現代企業而言,數據庫是至關重要的資產,它們存儲關鍵數據,為組織的決策和運營提供動力,隨著數據量的不斷增長和復雜性的提高,企業需要創新數據庫設計來保持競爭力,尖端的工具正在不斷涌現,為數據庫設計師提供新的方法來設計和管理數據庫,這些工具可以幫助提高生產力、優化性能并確保數據的完整性,尖端數據庫設計工具以下是一些最尖端的數據庫設計工具...。
本站公告 2024-09-11 11:21:56
隨著技術不斷發展,編程語言也不斷更新,為了在不斷變化的就業市場中保持領先地位,掌握最熱門的編程語言至關重要,在2013年,以下編程語言處于領先地位,1.PythonPython以其易學、用途廣泛而聞名,在數據科學、機器學習和Web開發等領域得到了廣泛應用,它的簡單語法和豐富的庫使開發人員能夠快速有效地構建項目,Python的使用在近年...。
最新資訊 2024-09-10 15:38:18
Unix操作系統及其廣泛的工具和庫是一套強大的資源,可以幫助程序員編寫復雜且高效的程序,通過利用Unix的功能,程序員可以創建可移植、可定制和可擴展的解決方案,本文將探討如何充分利用Unix工具和庫進行高級編程,幫助您提升編程技能并開發更出色的應用程序,引言Unix是一個多用戶、多任務操作系統,它因其穩定性、可靠性和可移植性而聞名,U...。
最新資訊 2024-09-08 07:27:30
在輪回轉世和靈魂不滅的觀念中,借尸還魂一直是一個頗具爭議的話題,近年來,隨著科學技術的進步,關于靈魂輪回轉世的研究也取得了一些進展,由于缺乏確鑿的證據,這一領域仍然存在著諸多爭論,朱秀華案件2007年,中國湖南省發生了一起震驚全國的借尸還魂案件,引發了關于靈魂輪回轉世的激烈討論,該案件的主人公名叫朱秀華,是一位來自農村的年輕女子,據家...。
互聯網資訊 2024-09-05 04:31:16