日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

快速排序的解析

發布時間:2024/9/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 快速排序的解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

快排原理

每一趟快速排序,都是給基準值找其正確的位置(即尋找基準值最終的位置)

該基準值的位置將一個無序的數組劃分成兩部分,前一部分均小于該基準值,后一部分均大于該基準值

這就是一趟快速排序。

?

接下來我用兩種方法求解快速排序,其實它們的基本思想一樣,只是實現方式不同而已

?

快排1的基本思想

1. 在數組中選一個基準值(通常為數組第一個);

2.分區過程,將比基準值大的數全放到它的右邊,小于或等于它的數全放到它的左邊;

3.對基準值左、右兩邊的數組,不斷重復以上兩個過程,直到每個子集只有一個元素,即為全部有序。

快排的圖解過程1

給出一個無序的數組 23,46,0,8,11,18,將該無序數組排成從小到大的數組

如下圖所示,假設最開始的基準值為數組第一個元素23,則首先用一個臨時變量去存儲基準值即tmp=23;然后分別從數組的兩端掃描數組,設兩個標志指針:low指向起始位置,high指向末尾.

①首先從右半部分開始掃描(切記不能從左半部分開始掃描,否則會出錯,因為它是將左邊第一個值作為基準值的,相反如果是將最右邊的值作為基準值,要從左半部分掃描),如果掃描到的值大于基準值就讓high減1,如果發現有元素比該基準值的值小(如上圖中18<=tmp),就將high位置的值賦值給low位置?,結果如下:

②然后開始從左到右掃描掃描,如果掃描到的值小于基準值就讓low加1,如果發現有元素大于基準值(如上圖46=>tmp),就再將low位置的值賦值給high位置的值,指針移動并且數據交換后的結果如下:

③然后開始右到左開始掃描,發現右邊指針的值大于基準值,hign指針向左移動一位

④然后發現上圖11<=tmp,則將high位置的值賦值給low位置的值,結果如下:

⑤然后再開始從左往右遍歷,發現其余值均小于等于基準值,直到low=high結束循環,此時low或high的下標就是基準值在該數組中的正確位置.如下圖所示.

交換arr[low]與基準值23,結果如下圖

這樣一趟快速排序結束了,基準值23放在了最終(正確)的位置了,返回的位置是序列i是4,此時該基準值將無序數組分成了兩部分,前一部分均小于等于基準值,后一部分均大于基準值

以后重復采用遞歸分治的方式分別對前半部分【0~i-1】和后半部分【i+1~5】進行排序,當前半部分【0~i-1】和后半部分【i+1~5】均有序時整個數組就自然有序了。

源碼實現(python)

def swap(arr,a,b):temp=arr[b]arr[b]=arr[a]arr[a]=temp#合并partion函數,這里rear相當于解析中的high,front相當于low arr=[1,3,4,7,8,6,9,5,2,10] left=0 right=len(arr)-1def main(arr,left,right):if(right>=left):front=leftrear=righttemp=arr[front]while(rear>front):while(rear>front) and(arr[rear]>temp):rear-=1#swap(arr,front,rear) #當前的右指針值小于基準值時,與左指針值進行交換arr[front]=arr[rear] #也可以覆蓋,反正最后需要填值的while(rear>front) and(temp>=arr[front]):front+=1#swap(arr,front,rear)#當前的左指針值大于基準值時,與右指針值進行交換arr[rear]=arr[front] #也可以覆蓋,反正最后需要填值的arr[front]=temp #將基準值置于最終的位置,一趟快排結束t=frontmain(arr,left,t-1) #左分治main(arr,t+1,right) #右分治main(arr,left,right) print(arr)

c語言源碼:

#include<stdio.h> int p; int t; void swap(int a[],int m,int n){int temp;temp=a[m];a[m]=a[n];a[n]=temp; } int partion(int a[],int left,int right){int k=left;int s=a[k]; //將中間的這個數和第一個數交換 while(left<right){while(left<right&&a[right]>s){ // 從右向左找第一個小于x的數 right--;}swap(a,right,left);while(left<right&&a[left]<=s){ // 從左向右找第一個大于等于x的數 left++;}swap(a,left,right);}a[left]=s; //一趟劃分結束,left為軸心return left; }void quicksort(int a[],int left,int right){if(right>=left){p=partion(a,left,right);quicksort(a,left,p-1); //軸心的左遞歸quicksort(a,p+1,right); //軸心的右遞歸} }int main(){int a[]={1,2,5,7,4,3,10,6,9,8};t=9;quicksort(a,0,t);for(int i=0;i<=t;i++){printf("%d " ,a[i]);}return 0; }

?

快排2的基本思想

1. 在數組中選一個基準值(通常為數組最右邊的一個);

2.指針i從左到右掃描過程:

? ? ? ? ①若指針i指向的值比基準值大,則首先將指針i的值與rear指針的前一個位置(rear-1)的值互換,然后rear指針向左移動一位。即rear-1

? ? ? ? ②若指針i指向的值比基準值小,則首先將指針i的值與front指針的值互換,然后front指針向右移動一位,指針i也向右移動一位

? ? ? ? ③若指針i指向的值等于基準值,則只有指針i向右移動一位

3.對基準值左、右兩邊的數組,不斷重復以上兩個過程,直到每個子集只有一個元素,即為全部有序。

快排的圖解過程2

給出一個無序的數組 1,3,2,4,6,5,將該無序數組排成從小到大的數組

如下圖所示,假設最開始的基準值為數組最后一個個元素5,則首先用一個臨時變量去存儲基準值即tmp=5;然后設三個標志指針: front指向起始位置,rear指向末尾.? 當前移動指針i指向移動位置

①當前移動指針i從左到右掃描,判斷當前移動指針的值是大于,小于還是等于基準值,從圖中可以看出,當前移動指針的值是小于基準值,所以互相交換arr[i]與arr[front], i指針和front指針都向右移動一步,如下圖

?

②判斷當前移動指針的值是大于還是小于基準值,從圖中可以看出,當前移動指針的值是小于基準值,所以互相交換arr[i]與arr[front], i指針和front指針都向右移動一步(即i+1,front+1)

③重復上面的步驟,直到當前移動指針指向6時,這時6>temp,所以arr[i]與arr[rear-1]互相交換,如下圖

交換arr[i]與arr[rear-1],? ?這里為什么不與arr[rear]交換呢?因為最右邊這個位置是用來存儲基準值的,最后會把基準值與最后大于基準值的數進行交換,以保證前一部分均小于基準值,后一部分均大于基準值。

此時右指針rear向左移動一位(即rear-1),如下圖

③這時移動指針i==rear,移動指針i停止掃描,將最右邊基準位置的值與當前移動指針i的值進行交換,如下圖

一趟快速排序結束,該基準值temp=5,返回的位置是序列i是4,這樣基準值放在了最終(正確)的位置了,將無序數組分成了兩部分,前一部分均小于5,后一部分均大于5

以后重復采用遞歸分治的方式分別對前半部分【0,i-1】和后半部分【i+1,5】進行排序,當前半部分和后半部分均有序時整個數組就自然有序了。

?

ps: 其實這種快排的實現方式可以計算每個基準值相等的數據有多少個,只需要當每趟快排結束后,分別計算i-front+1的值就可以得出該數組中所有數據的相等個數值

源碼實現(python)

def swap(arr,a,b):temp=arr[b]arr[b]=arr[a]arr[a]=tempdef main(arr,left,right):global jif(right>=left):front=lefti=left #移動指針rear=righttemp=arr[right] #注意移動指針從左便利時,以最右邊作為基值while(rear>i): #當移動指針小于右邊界時if(arr[i]>temp): #當前指針的值大于基值時,swap(arr,i,rear-1) #將當前指針的值與右邊界指針的前一位值進行交換rear-=1 #右邊界指針向右移動一位elif(arr[i]<temp): #當前指針的值小于基值時,swap(arr,i,front) #將當前指針的值與左邊界指針的值進行交換front+=1 #左邊界指針向右移動一位i+=1 #當前移動指針也移動一位else: #當前指針的值等于基值時,i+=1 #當前指針向右移動一位swap(arr,i,right) #當i==rear時,將最后的i值與基準值進行交換,一趟快排結束j+=1print("第",j,"趟:",arr)main(arr,left,i-1) #左分治main(arr,i+1,right) #右分治arr=[1,3,2,4,6,5] left=0 right=len(arr)-1 j=0 main(arr,left,right) print(arr)

c語言源碼:

#include<stdio.h> int p; int t; void swap(int a[],int m,int n){int temp;temp=a[m];a[m]=a[n];a[n]=temp; } int partion(int a[],int left,int right){ int k=right; //k作為標準值的下標,為最后一位int i=left; // i作為移動指針,與標準值進行比較判斷int s=a[k]; //標準值while(i<right){ //當i小于right時if(a[i]<s){ //當前移動指針i指向的值小于標準值時swap(a,i,left); //當前i指向的值與left進行交換,保證小于標準值的在標準值的左邊i++; // i向前移動一位left++; // 同時left向右移動}else if(a[i]>s){ //當前移動指針i指向的值大于標準值時swap(a,i,right-1); //當前i指向的值與right-1位進行交換,保證大于標準值的在標準值的右邊right--; // right向左邊移動一位}else{ //當前移動指針i指向的值等于標準值時i++; //i向前移動一位 }}swap(a,i,k); //跳出while循環后i==right,交換最后的i值與標準值,一趟分治結束return i; //返回標準值的位置 }void quicksort(int a[],int left,int right){ //遞歸if(right>=left){p=partion(a,left,right); // 將數組分為兩部分,以p為軸心quicksort(a,left,p-1); // 左邊遞歸quicksort(a,p+1,right); //右邊遞歸} }int main(){int a[]={1,2,2,7,4,3,10,6,6,9};t=9;quicksort(a,0,t);for(int i=0;i<=t;i++){printf("%d " ,a[i]);}return 0; }

?

總結

以上是生活随笔為你收集整理的快速排序的解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。