數據結構 快速排序

  快速排序是對冒泡排序的一種改進,是所有內部排序算法中平均性能最優的排序算法。其基本思想是基于分治法的:在待排序數組L[1...n]中任取一個元素pivot作為基準,從數組的兩端開始掃描。設兩個指示標志(low指向起始位置,high指向末尾),先從后向前掃描(high遞減),如果high位置的元素小于pivot,就交換low和high位置的元素,然后從前向后掃描(low遞增),如果low位置的元素大于pivot,就交換low和high位置的元素。重復上述過程,直到low>=high,然后把基準放到low位置上,一趟排序就完成了,將一個元素(基準)放到了最終位置上,不產生有序子序列。將待排序數組劃分為兩部分即L[1...k-1]和L[k+1...n],使得前半部分L[1...k-1]所有元素小于pivot,后半部分L[k+1...n]所有元素大于或等于pivot。接著采用遞歸的方式分別對前半部分和后半部分排序,直到每部分只有一個元素或空為止,即所有元素放在了最終位置上。

  之所以快速排序比較快,是因為相比于冒泡排序,每次交換是跳躍式的。每次排序時選取一個基準,將小于基準的數全部放到基準點的左邊,將大于或等于基準的數全部放到基準的右邊,在每次交換時不會像冒泡排序一樣只能在相鄰的數之間進行交換,增大了交換距離,減少了總的比較和交換次數,加快了速度。在最壞情況下,仍可能交換相鄰的兩個數。

  假設對“6 1 2 7 9 3 4 5 10 8”這10個數進行排序:

  從后向前掃描

  

  交換7和5

  

  交換之后:6 1 2 5 9 3 4 7 10 8

  交換9和4

  

  交換之后:6 1 2 5 4 3 9 7 10 8

  i>=j,交換6和3

  

  交換之后:3 1 2 5 4 6 9 7 10 8

  一趟排序結束。

 1 public class QuickSort {
 2 
 3     public static void quickSort(int[] arr, int low, int high) {
 4         // 至少有兩個元素需要排序
 5         if (low < high) {
 6             int curLow = low;
 7             int curHigh = high;
 8             int temp = arr[low];
 9 
10             while(curLow < curHigh) {
11                 // 從右向左掃描,尋找第一個比基準小的數
12                 while(curLow < curHigh && arr[curHigh] >= temp) {
13                     curHigh--;
14                 }
15                 arr[curLow] = arr[curHigh];
16 
17                 // 從左向右掃描,尋找第一個比基準大的數
18                 while(curLow < curHigh && arr[curLow] <= temp) {
19                     curLow++;
20                 }
21                 arr[curHigh] = arr[curLow];
22             }
23 
24             // 基準歸位
25             arr[curLow] = temp;
26 
27             // 基準位置左邊子序列遞歸排序
28             quickSort(arr, low, curLow - 1);
29             // 基準位置左邊子序列遞歸排序
30             quickSort(arr, curLow + 1, high);
31         }
32     }
33 
34     public static void main(String[] args) {
35         int[] arr = {15, 1, 17, 3, 6, 8};
36         QuickSort.quickSort(arr, 0, arr.length - 1);
37 
38         for (int i = 0, length = arr.length; i < length; i++) {
39             System.out.printf(" %d", arr[i]);
40         }
41     }
42 
43 }

  結果如下:

 1 3 6 8 15 17

  上述代碼每次以當前數組中第一個元素作為基準對數組進行劃分。

  快速排序性能分析:

  空間復雜度:因為快速排序是遞歸的,所以需要借助一個遞歸工作棧來保存每一層遞歸調用的必要信息,容量應與遞歸調用的最大深度一致。最壞情況下n-1次遞歸調用,棧的深度為O(n);最好和平均情況下棧的深度為O(log2n)。所以,空間復雜度在最壞情況下為O(n),平均情況下為O(log2n)。

  時間復雜度:快速排序的性能主要取決于劃分操作的好壞。最壞情況下待排序數組基本有序或基本逆序時,每一次遞歸劃分的兩個區域分別包含n-1個元素和0個元素,快速排序退化成冒泡排序,時間復雜度為O(n2)。最好情況下最平衡劃分,兩個子數組長度不超過n/2,時間復雜度為O(nlog2n)。而快速排序平均情況下運行時間接近于最好情況下的運行時間,即時間復雜度在最壞情況下為O(n2),平均情況下為O(nlog2n)。

  穩定性:如果右端區間有兩個相同的關鍵字,且均小于基準,那么交換到左端區間后,它們的相對次序會變化,即快速排序不穩定。例如,表L={3, 2, 2},經過一趟排序后L={2, 2, 3},最終結果是L={2,?2, 3},2與2的相對次序發生了變化。

  改進方案

  1 使用直接插入排序

  當遞歸過程中劃分得到的子數組長度較小時,可以使用直接插入排序完成排序工作。

1 public static void quick(int []array ,int lo,int hi){
2         if(hi-lo+1<10){
3             insertSort(array);
4         }else{
5             quickSort(array,lo,hi);
6         }
7     }

  2 選取好的基準

  盡量選取可以把元素平衡劃分的基準,有三種方法:固定切分,隨機切分和三取樣切分。固定切分的效率低。隨機切分是常用的一種切分,效率高,最壞情況下時間復雜度有可能為O(n2)。三取樣切分最理想,具體操作:選取數組的頭尾和中間這3個元素,取這3個元素的中間值作為基準。

 1 public static int partition(int []array,int lo,int hi){
 2         //三數取中
 3         int mid=lo+(hi-lo)/2;
 4         if(array[mid]>array[hi]){
 5             swap(array[mid],array[hi]);
 6         }
 7         if(array[lo]>array[hi]){
 8             swap(array[lo],array[hi]);
 9         }
10         if(array[mid]>array[lo]){
11             swap(array[mid],array[lo]);
12         }
13         int key=array[lo];
14         
15         while(lo<hi){
16             while(array[hi]>=key&&hi>lo){
17                 hi--;
18             }
19             array[lo]=array[hi];
20             while(array[lo]<=key&&hi>lo){
21                 lo++;
22             }
23             array[hi]=array[lo];
24         }
25         array[hi]=key;
26         return hi;
27     }
28     
29     public static void swap(int a,int b){
30         int temp=a;
31         a=b;
32         b=temp;
33     }
34     public static void sort(int[] array,int lo ,int hi){
35         if(lo>=hi){
36             return ;
37         }
38         int index=partition(array,lo,hi);
39         sort(array,lo,index-1);
40         sort(array,index+1,hi);
41     }

  

  參考資料

  《2017年數據結構聯考復習指導》 P287-288

  快速排序(java實現)

  坐在馬桶上看算法:快速排序

轉載于:https://www.cnblogs.com/WJQ2017/p/8340156.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281302.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281302.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281302.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Finally語句塊的運行

一、finally語句塊是否一定運行&#xff1f; Java中異常捕獲機制try...catch...finally塊中的finally語句是不是一定會被運行&#xff1f;非常多人都說不是。當然他們的回答是正確的&#xff0c;經過試驗。至少下面有兩種情況下finally語句是不會被運行的&#xff1a; &#xf…

vue-cli 3.0 跨域請求代理

官方文檔中指明&#xff0c;跨域請求可以通過配置vue.config.js中的devServer.proxy選項來進行配置。 這個選項配置的本質實際上就是http-proxy-middleware中間件的用法&#xff0c;和Webpack-dev-server的proxy一樣。 vue-cli 3.0中介紹了兩種常見的用法&#xff1a; modul…

小米人員架構調整:組建中國區,王川任總裁

12月13日上午&#xff0c;小米內部發布人員調整公開信&#xff0c;信中傳達了兩個重要內容&#xff1a;將銷售與服務部改組為中國區&#xff0c;任命集團高級副總裁王川兼任中國區總裁。 在今年9月份&#xff0c;也就是小米上市前夕&#xff0c;雷軍在一封內部信中宣布對公司組…

在 .NET 7上使用 WASM 和 WASI

WebAssembly&#xff08;WASM&#xff09;和WebAssembly System Interface&#xff08;WASI&#xff09;為開發人員開辟了新的世界。.NET 開發人員在 Blazor WebAssembly 發布時熟悉了 WASM。Blazor WebAssembly 在瀏覽器中基于 WebAssembly 的 .NET 運行時上運行客戶端。WASI通…

Java基礎 五 方法

方法 1.1 方法概述 在我們的日常生活中&#xff0c;方法可以理解為要做某件事情&#xff0c;而采取的解決辦法。 如&#xff1a;小明同學在路邊準備坐車來學校學習。這就面臨著一件事情&#xff08;坐車到學校這件事情&#xff09;需要解決&#xff0c;解決辦法呢&#xf…

django rest framework 過濾 lim分頁

一.過濾 1.首先引用diango 自帶的過濾配置 2.導入模塊 from django_filters.rest_framework import DjangoFilterBackend from django_filters import rest_framework as filters 3.一種簡單的過濾: class BookView(ModelViewSet):queryset Book.objects.all()serializer_clas…

MySQL用戶及權限管理

MySQL用戶及權限管理查看用戶及權限查看用戶及作用域&#xff08;使用范圍&#xff09;查看用戶權限創建用戶及授權字段參數用戶管理使用命令提示符登錄MySQL mysql -h localhost -u root -p查看用戶及權限 mysql中的用戶信息和權限等都存儲在一個名為mysql的數據庫中。其中主…

附近有什么?8款可以查周邊的App

如今科技發達的時代&#xff0c;手機的功能不僅僅只是能通訊聊天&#xff0c;而是逐漸的走進了人們的生活中。因為有了APP&#xff0c;我們的生活才更豐富&#xff0c;并且有很多是我們生活中不可缺少的軟件&#xff0c;而這些軟件便是根據手機中的GPS定位系統而來的。簡單來說…

MyEclipse小問題與漢字處理

今天在使用MyEclipse時&#xff0c;遇到工作目錄報錯(如上圖)&#xff0c;解決方法如下&#xff1a;找到對應工作區(查看工作區的方法為&#xff1a;單擊File → Switch Workspace 即可)依次打開 .metadata文件夾 → .plugins文件夾 → org.eclipse.core.runtime文件夾 → .set…

關系數據庫設計及優化原則

一直以來就想總結一下自己這么多年來在關系數據庫上積累的經驗。奈何自己是一個比較懶的人一直不想動手去寫。扎克伯格曾說過&#xff1a;“想做一件事的話&#xff0c;最好的辦法就是先開始”。索性就先寫一點東西&#xff0c;這些東西不會太長&#xff0c;自然也不會包括太多…

java B2B2C springmvc mybatis電子商務平臺源碼-消息隊列之RocketMQ

RocketMQ出自阿里公司的開源產品&#xff0c;用 Java 語言實現&#xff0c;在設計時參考了 Kafka&#xff0c;并做出了自己的一些改進&#xff0c;消息可靠性上比 Kafka 更好。RocketMQ在阿里集團被廣泛應用在訂單&#xff0c;交易&#xff0c;充值&#xff0c;流計算&#xff…

VSCode同步設置

2022/4/1 更新 剛剛發現還有人在看這篇文章&#xff0c;這里更新一下&#xff0c;VSCode 從1.48版本開始已經內置了同步功能&#xff0c;可以不用再使用Settings Sync插件了。 點擊左下角的用戶或者設置的 Sign in to Sync Setting&#xff0c;使用GitHub或者Microsoft賬戶登…

配置三臺服務器組成的ELK集群(二)

上一篇里主要是介紹了ES和ES-Head的安裝過程&#xff0c;這一篇繼續介紹ELK集群的其他核心組件安裝過程。 五、安裝Logstash&#xff1a; 本案的Logstash安裝在10.113.130.117上&#xff1b;燃鵝&#xff0c;Logstash也可以利用多臺組成集群&#xff0c;如果未來單臺處理不過來…

Discuz X3.2源碼解析 discuz_application類(轉自百度)

discuz_application在/source/class/discuz/discuz_application.php中。 discuz_application繼承自抽象類discuz_base discuz_application主要實現對運行環境、配置、輸入、輸出、數據庫、設置、用戶、session、移動模塊、計劃任務、手機預覽等方面的初始化。 instance()函數來…

.NET性能優化-是時候換個序列化協議了

計算機單機性能一直受到摩爾定律的約束&#xff0c;隨著移動互聯網的興趣&#xff0c;單機性能不足的瓶頸越來越明顯&#xff0c;制約著整個行業的發展。不過我們雖然不能無止境的縱向擴容系統&#xff0c;但是我們可以分布式、橫向的擴容系統&#xff0c;這聽起來非常的美好&a…

Kubernetes-基于Helm安裝部署高可用的Redis

1、Redis簡介 Redis是一個開放源代碼&#xff08;BSD許可證&#xff09;的代理&#xff0c;其在內存中存儲數據&#xff0c;可以代理數據庫、緩存和消息。它支持字符串、散列、列表、集合和位圖等數據結構。Redis 是一個高性能的key-value數據庫&#xff0c; 它在很大程度改進了…

Vue 深度監聽和初始綁定

vue的監聽屬性普通方式無法監聽對象內部屬性的改變&#xff0c;并且初始化時不會監聽數據對象。 vue為監聽屬性提供了一種對象方法 watch: {option.size: {// handler為默認執行的方法handler (newValue, oldValue) {this.size newValue}&#xff0c;// 立即執行handler方法…

markdown流程圖畫法小結

markdown流程圖畫法小結markdown畫圖流程圖 最簡單的流程圖為例mermaid! graph TD A --> B //在沒有(),[].{}等括號的情況之下&#xff0c;圖標默認名字就是字母 A --> C C --> D B --> D 給圖標添加名字&#xff0c;改變只有矩陣圖形&#xff0c;在箭頭上添加文字…

hihocoder 1689 - 推斷大小關系(圖論+二分)

題目鏈接 https://vjudge.net/problem/HihoCoder-1689有N個整數A1, A2, ... AN&#xff0c;現在我們知道M條關于這N個整數的信息。每條信息是&#xff1a;Ai < Aj 或者 Ai Aj 小Hi希望你能從第一條信息開始依次逐條處理這些信息。一旦能推斷出A1和AN的大小關系就立即停止。…

32歲京東畢業程序員,走投無路當了外企外包,閑得心里發慌,到點下班渾身不自在!...

??當一位京東程序員進入外企當外包會怎么樣&#xff1f;順利躺平&#xff0c;實現wlb&#xff08;工作生活平衡&#xff09;嗎&#xff1f;未必&#xff0c;因為人是一種很奇怪的動物。這位網友說&#xff1a;32歲京東畢業程序員&#xff0c;找了幾個月工作一直沒有合適的&am…