前面學習了歸併和快速排序演算法,現在來了解歸併和快速排序演算法背後的演算法思想:分治思想,並對歸併和快速排序進行擴充套件,解決經典演算法問題:逆序對和第k大的演算法問題
顧名思義,分而治之,就是將原問題,分割成同等結構的子問題,之後將子問題逐一解決後,原問題也就得到了解決。
對於乙個長度為n的整數序列a,滿足i < j 且 ai > aj.的數對(i,j)稱為整數序列a的乙個逆序。 通常逆序對可以表示乙個數列的順序程度,從小到大的數列逆序對為0,從大到小的逆序對為:(n*(n-1))/2;採用分而治之的思想,要求整個數列的逆序對,可以先求出前一半數列的逆序對,和後一半數列的逆序對,然後加上前乙個數列和後乙個數列所形成的逆序對,因為前後兩個數列都是有序,直接在歸併排序merge的時候求是非常簡單的。
function
merge
(&$arr, $l, $mid, $r)
elseif ($j > $r) elseif($tmp[$i] <= $tmp[$j])else
} return $res;
}/**
* [__mergesort 對區間為[l,r]的元素進行歸併排序]
* @param [type] $arr [description]
* @param [type] $l [description]
* @param [type] $r [description]
* @return [type] [description]
*/function
__inversioncount
(&$arr, $l, $r)
$mid = (int)(($l + $r) / 2);
// 求出 arr[l...mid] 範圍的逆序數
$res1 = __inversioncount($arr, $l, $mid);
// 求出 arr[mid+1...r] 範圍的逆序數
$res2 = __inversioncount($arr, $mid+1, $r);
return $res1 + $res2 + merge($arr, $l, $mid, $r);
}function
inversioncount
(&$arr, $n)
複製**
結果
array
( [0] => 3
[1] => 0
[2] => 5
[3] => 5
[4] => 8
[5] => 0
[6] => 8
[7] => 5
)逆序對的個數: 7
複製**
這裡我們採用第三種解法,時間複雜度為:o(n)+o(1/2)+o(1/4)+...+o(1/n), 當n為無窮大時候,時間複雜度約為o(n)
//對arr[l...r]部分進行partition操作
// 返回p,使得arr[l...p-1] < arr[p] ; arr[p+1...r] > arr[p]
function
partition
(&$arr, $l, $r)
} swap($arr, $l, $j);
return $j;
}/**
* [__quicksort 對陣列arr[l...r]進行快速排序]
* @param [type] &$arr [description]
* @param [type] $l [description]
* @param [type] $r [description]
* @return [type] [description]
*/function
__selectk
(&$arr, $l, $r, $k)
// 如果 k == p, 直接返回arr[p]
$p = partition($arr, $l, $r, $k);
if ($p == $k) elseif($p > $k)else
}// 尋找arr陣列中第k小的元素
function
selectk
(&$arr, $n, $k)
複製**
結果
array
( [0] => 9
[1] => 4
[2] => 10
[3] => 4
[4] => 7
[5] => 6
[6] => 3
[7] => 10
[8] => 7
[9] => 9
)第3小的數為: 6
複製**
-------------------------華麗的分割線--------------------
看完的朋友可以點個喜歡/關注,您的支援是對我最大的鼓勵。
個人部落格番茄技術小棧和掘金主頁
快速 歸併和基數排序
快速排序 public class quicksort while arr r pivot if l r temp arr l arr l arr r arr r temp if arr l pivot if arr r pivot if l r if leftif right l public c...
歸併排序 快速排序 分治思想
蒟蒻來水一篇博文方便複習參考 快速排序的基本原理 隨機選擇乙個基點,將比基點大的元素放在基點左側,將比基點小的元素放在基點右側。然後再分別只看基點左側和右側,重複上述過程。由於其利用了分治思想,在平均狀態下其時間複雜度為o nlogn 基本 如下 includeusing namespace std...
歸併和sort排序簡單運用
今天學習了歸併排序和sort函式的簡單運用,感覺sort函式真的是無比的神奇,能加各種神奇的東西,然後進行一些排序練習 歸併排序基本 include using namespace std void merge int data,int start,int end,int result while ...