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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

快速排序 (Quick Sort)(Java实现)

發(fā)布時間:2023/12/4 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 快速排序 (Quick Sort)(Java实现) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

快速排序(Quicksort)是對冒泡排序的一種改進,借用了分治的思想,由C. A. R. Hoare在1962年提出。

1、基本思想

快速排序的基本思想:挖坑填數+分治法。

首先選一個軸值(pivot,也有叫基準的),通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續(xù)進行排序,以達到整個序列有序。

2、算法描述

快速排序使用分治策略來把一個序列(list)分為兩個子序列(sub-lists)。步驟為:

  • 從數列中挑出一個元素,稱為"基準"(pivot)
  • 重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準后面(相同的數可以到任一邊)。在這個分區(qū)結束之后,該基準就處于數列的中間位置。這個稱為分區(qū)(partition)操作
  • 遞歸地(recursively)把小于基準值元素的子數列和大于基準值元素的子數列排序
  • 遞歸到最底部時,數列的大小是零或一,也就是已經排序好了。這個算法一定會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最后的位置去。

    3、代碼實現

    用偽代碼描述如下:

  • i = L; j = R; 將基準數挖出形成第一個坑a[i]
  • j–,由后向前找比它小的數,找到后挖出此數填前一個坑a[i]中
  • i++,由前向后找比它大的數,找到后也挖出此數填到前一個坑a[j]中
  • 再重復執(zhí)行②,③二步,直到i==j,將基準數填入a[i]中
  • 3.1 遞歸實現

    /*** 快速排序(遞歸)** ①. 從數列中挑出一個元素,稱為"基準"(pivot)。* ②. 重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準后面(相同的數可以到任一邊)。在這個分區(qū)結束之后,該基準就處于數列的中間位置。這個稱為分區(qū)(partition)操作。* ③. 遞歸地(recursively)把小于基準值元素的子數列和大于基準值元素的子數列排序。* @param arr 待排序數組* @param low 左邊界* @param high 右邊界*/ public static void quickSort(int[] arr, int low, int high){if(arr.length <= 0) return;if(low >= high) return;int left = low;int right = high;int temp = arr[left]; //挖坑1:保存基準的值while (left < right){while(left < right && arr[right] >= temp){ //坑2:從后向前找到比基準小的元素,插入到基準位置坑1中right--;}arr[left] = arr[right];while(left < right && arr[left] <= temp){ //坑3:從前往后找到比基準大的元素,放到剛才挖的坑2中left++;}arr[right] = arr[left];}arr[left] = temp; //基準值填補到坑3中,準備分治遞歸快排System.out.println("Sorting: " + Arrays.toString(arr));quickSort(arr, low, left-1);quickSort(arr, left+1, high); }

    上面是遞歸版的快速排序:通過把基準temp插入到合適的位置來實現分治,并遞歸地對分治后的兩個劃分繼續(xù)快排。那么非遞歸版的快排如何實現呢?

    因為遞歸的本質是棧,所以我們非遞歸實現的過程中,可以借助棧來保存中間變量就可以實現非遞歸了。在這里中間變量也就是通過Pritation函數劃分區(qū)間之后分成左右兩部分的首尾指針,只需要保存這兩部分的首尾指針即可。

    3.2 非遞歸實現

    /*** 快速排序(非遞歸)** ①. 從數列中挑出一個元素,稱為"基準"(pivot)。* ②. 重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準后面(相同的數可以到任一邊)。在這個分區(qū)結束之后,該基準就處于數列的中間位置。這個稱為分區(qū)(partition)操作。* ③. 把分區(qū)之后兩個區(qū)間的邊界(low和high)壓入棧保存,并循環(huán)①、②步驟* @param arr 待排序數組*/ public static void quickSortByStack(int[] arr){if(arr.length <= 0) return;Stack<Integer> stack = new Stack<Integer>();//初始狀態(tài)的左右指針入棧stack.push(0);stack.push(arr.length - 1);while(!stack.isEmpty()){int high = stack.pop(); //出棧進行劃分int low = stack.pop();int pivotIdx = partition(arr, low, high);//保存中間變量if(pivotIdx > low) {stack.push(low);stack.push(pivotIdx - 1);}if(pivotIdx < high && pivotIdx >= 0){stack.push(pivotIdx + 1);stack.push(high);}} }private static int partition(int[] arr, int low, int high){if(arr.length <= 0) return -1;if(low >= high) return -1;int l = low;int r = high;int pivot = arr[l]; //挖坑1:保存基準的值while(l < r){while(l < r && arr[r] >= pivot){ //坑2:從后向前找到比基準小的元素,插入到基準位置坑1中r--;}arr[l] = arr[r];while(l < r && arr[l] <= pivot){ //坑3:從前往后找到比基準大的元素,放到剛才挖的坑2中l++;}arr[r] = arr[l];}arr[l] = pivot; //基準值填補到坑3中,準備分治遞歸快排return l; }

    快速排序是通常被認為在同數量級(O(nlog2n))的排序方法中平均性能最好的。但若初始序列按關鍵碼有序或基本有序時,快排序反而蛻化為冒泡排序。為改進之,通常以“三者取中法”來選取基準記錄,即將排序區(qū)間的兩個端點與中點三個記錄關鍵碼居中的調整為支點記錄。快速排序是一個不穩(wěn)定的排序方法。

    以下是快速排序算法復雜度:

    平均時間復雜度最好情況最壞情況空間復雜度
    O(nlog?n)O(nlog?n)O(n2)O(1)(原地分區(qū)遞歸版)

    快速排序排序效率非常高。 雖然它運行最糟糕時將達到O(n2)的時間復雜度, 但通常平均來看, 它的時間復雜為O(nlogn), 比同樣為O(nlogn)時間復雜度的歸并排序還要快. 快速排序似乎更偏愛亂序的數列, 越是亂序的數列, 它相比其他排序而言, 相對效率更高.

    Tips: 同選擇排序相似, 快速排序每次交換的元素都有可能不是相鄰的, 因此它有可能打破原來值為相同的元素之間的順序. 因此, 快速排序并不穩(wěn)定.

    4、拓展

    https://github.com/iTimeTraveler/SortAlgorithms#六快速排序quick-sort

    https://blog.csdn.net/shujuelin/article/details/82423852

    創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現金大獎

    總結

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

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