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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

荷兰国旗问题以及快速排序

發(fā)布時間:2024/8/1 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 荷兰国旗问题以及快速排序 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 一、荷蘭國旗問題
    • 1、啥是荷蘭國旗問題
    • 2、荷蘭國旗問題的抽象
    • 3、解決的思路
    • 4、詳細的參考代碼
  • 二、快速排序
    • 1、啥是快排(排序流程)
    • 2、抽象后的快排流程
    • 3、詳細的參考代碼

大家好,我是周一。

最近幾篇算法,我們都是聊的歸并排序,歸并排序也說的差不多了,今天講講快速排序。

一、荷蘭國旗問題

1、啥是荷蘭國旗問題

荷蘭國旗是由紅白藍3種顏色的條紋拼接而成,如下圖所示:


假設這樣的條紋有多條,且各種顏色的數(shù)量不一,并且隨機組成了一個新的圖形,新的圖形可能如下圖所示,但不僅僅只有這一種情況:

需求是:把這些條紋按照顏色排好,紅色的在上半部分,白色的在中間部分,藍色的在下半部分,我們把這類問題稱作荷蘭國旗問題。

2、荷蘭國旗問題的抽象

我們把荷蘭國旗問題抽象成數(shù)組的形式是下面這樣的:

給定一個整數(shù)數(shù)組和一個值M(存在于原數(shù)組中),要求把數(shù)組中小于M的元素放到數(shù)組的左邊,等于M的元素放到數(shù)組的中間,大于M的元素放到數(shù)組的右邊,最終返回一個整數(shù)數(shù)組,只有兩個值,0位置是等于M的數(shù)組部分的左下標值、1位置是等于M的數(shù)組部分的右下標值。

進一步抽象為更加通用的形式是下面這樣的:

給定數(shù)組arr,將[l, r]范圍內(nèi)的數(shù)(當然默認是 [ 0 - arr.length - 1 ]),小于arr[r](這里直接取數(shù)組最右邊的值進行比較)放到數(shù)組左邊,等于arr[r]放到數(shù)組中間,大于arr[r]放到數(shù)組右邊。最后返回等于arr[r]的左, 右下標值。

3、解決的思路

定義一個小于區(qū),一個大于區(qū);遍歷數(shù)組,挨個和arr[r]比較,

(1)小于arr[r],與小于區(qū)的后一個位置交換,當前位置后移;

(2)等于arr[r],當前位置直接后移;

(3)大于arr[r],與大于區(qū)的前一個位置交換,當前位置不動(交換到此位置的數(shù)還沒比較過,所以不動)。

遍歷完后,arr[r]和大于區(qū)的最左側位置交換。

最后返回,此時小于區(qū)的后一個位置,大于區(qū)的位置,即是最后的等于arr[r]的左, 右下標值。

4、詳細的參考代碼

/*** 荷蘭國旗問題* <p>* 把數(shù)組arr中,[l, r]范圍內(nèi)的數(shù),小于arr[r]放到數(shù)組最左邊,等于arr[r]放到數(shù)組中間,大于arr[r]放到數(shù)組最右邊** @return 返回等于arr[r]的左, 右下標值*/public static int[] netherlandsFlag(int[] arr, int l, int r) {if (l > r) {return new int[]{-1, -1};}if (l == r) {return new int[]{l, r};}// 小于arr[r]的右邊界,從L的左邊一位開始int less = l - 1;// 大于arr[r]的左邊界,從r開始,即當前右邊界里已經(jīng)有arr[r]int more = r;// 當前正在比較的下標int index = l;// 不能與 大于arr[r]的左邊界 撞上while (index < more) {if (arr[index] < arr[r]) {// 小于時,將當前位置的數(shù)和小于arr[r]的右邊界的下一個位置交換// 當前位置后移一位swap(arr, index++, ++less);} else if (arr[index] == arr[r]) {// 等于時,當前位置后移一位即可index++;} else {// 大于時,當前位置的數(shù)和大于arr[r]的左邊界的前一個位置交換// 當前位置不動swap(arr, index, --more);}}// 將arr[r]位置的數(shù)和大于arr[r]的左邊界的數(shù)交換// 此時整個數(shù)組就按照 小于、等于、大于arr[r] 分成了左中右三塊swap(arr, more, r);// 最后整個數(shù)組中,等于arr[r]的左右邊界分別是less + 1, morereturn new int[]{less + 1, more};}

二、快速排序

1、啥是快排(排序流程)

首先設定一個分界值,通過該分界值將數(shù)組分成左中右三部分。

(1)將小于分界值的數(shù)據(jù)集中到數(shù)組的左邊,等于分界值的數(shù)據(jù)集中到數(shù)組的中間,大于分界值的數(shù)據(jù)集中到數(shù)組右邊。

(2)然后,左邊和右邊的數(shù)據(jù)可以獨立排序。對于左側的數(shù)據(jù),又可以取一個分界值,將該部分數(shù)據(jù)分成左中右三部分,同樣在左邊放較小值,中間放等于值,右邊放較大值。右邊數(shù)據(jù)也做同樣的處理。

(3)重復上述過程,可以看出,這是一個遞歸過程。通過遞歸將左側部分排好序后,再遞歸排好右側部分的順序。當左、右兩個部分各數(shù)據(jù)排序完成后,整個數(shù)組的排序也就完成了。

當看完了快排的流程,是不是發(fā)現(xiàn)快排的核心方法就是荷蘭國旗問題,所以知道為啥本文一開始就介紹荷蘭國旗問題了吧

2、抽象后的快排流程

(1)隨機將數(shù)組中的某個數(shù)放到比較位置上(即最右側位置)

(2)調(diào)用荷蘭國旗方法,(此時等于區(qū)的數(shù)即在最后排好序的位置上),拿到等于區(qū)的左右下標

(3)小于區(qū)和大于區(qū)再各自遞歸調(diào)用(1)(2)步即可將小于區(qū)和大于區(qū)排好序。

3、詳細的參考代碼

/*** 隨機快排*/public static void quickSortRandom(int[] arr) {if (arr == null || arr.length < 2) {return;}processRandom(arr, 0, arr.length - 1);}private static void processRandom(int[] arr, int l, int r) {if (l >= r) {return;}// 隨機將數(shù)組中的某個數(shù)放到比較位置上(即數(shù)組最右邊位置)// 這一步是保證快排時間復雜度是O(N*logN)的關鍵,不然,快排的時間復雜度是O(N^2)swap(arr, l + (int) ((r - l + 1) * Math.random()), r);// 將數(shù)組劃分為 小于、等于、大于arr[r] 的左中右三塊int[] equalArea = netherlandsFlag(arr, l, r);// 此時等于區(qū)域的值已經(jīng)處于最后排序結果的位置了// 遞歸將左半部分的排好序processRandom(arr, l, equalArea[0] - 1);// 遞歸將右半部分的排好序processRandom(arr, equalArea[1] + 1, r);}public static void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}

總結

以上是生活随笔為你收集整理的荷兰国旗问题以及快速排序的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。