排序演算法小結

2021-09-20 05:17:00 字數 2602 閱讀 9713

略····

乙個陣列,從0~n-1選擇最小的和0位置值交換;1~n-1選擇最小的和1位置值交換;以此類推。每次都是選擇最小的放在前面。

0~i-1位置是排好的,對於新來的第i個數,相當於把這個數按大小插到原來排好的牌裡,對於計算機來說,插進去的過程就是一路交換。這個i-1位置,是從0開始一直往後擴的,一直擴到陣列最後乙個,這樣這個陣列就排好了。

整體為o(n^2)演算法,但是和資料狀況有關係。

遞迴行為和遞迴時間複雜度的估算

遞迴函式就是系統在幫你壓棧

估計遞迴行為複雜度的通式:t(n) = at(n/b)+o(n^d)

遞迴 先左邊有序,再右邊有序,再外排。外排就是準備兩個指標,分別指著左右兩邊的第乙個數,再準備乙個空陣列,左右比較,小的那個放空陣列裡,指標++;如果乙個指標到頭了,另乙個整體拷貝進陣列。

時間複雜度o(n*logn),空間複雜度o(n)

mid = l +(r-l) >> 1(安全,不會產生溢位)

歸併演算法的應用:

小和問題:在乙個陣列中,每乙個數左邊比當前數小的數累加起來,叫做這個陣列的小和,求乙個陣列的小和。

在找兩個待merge的陣列中,右邊有多少個比前面指向的大,就產生多少個小和。

逆序對問題:如果左邊的數比右邊的數大,則兩個數構成乙個逆序對。請列印所有的逆序對。

在兩個待merge的陣列中,右邊有多少個數比左邊的小.

歸併演算法應用,題目裡如果出現了左,右根據大小做一些什麼事情的時候,這個時候就很有可能利用的是歸併的思想。

partition問題:按照給定的num,小於等於放在陣列左邊,大於等於放在陣列右邊(額外空間複雜度o(1),時間複雜度o(n)):

小於等於區域的指標x,從-1位置一直往下擴。cur從前向後遍歷,

當前數如果大於num,跳過;

如果小於等於num,把這個數和x+1位置數交換,x++。

荷蘭國旗問題:小於放一邊,中間放一邊,大於放右邊。(o(1),o(n)):

準備兩個表示區域的指標,小於區域less(-1)和大於區域more(n)。cur從前向後遍歷,

如果當前數等於num,跳過,cur++;

如果小於num,當前數和less+1位置的數交換,less++,cur++;

如果大於num,當前數和more-1位置的數交換,more–,cur停在原地,考察換過來的值和num的大小。

停止條件為cur和more撞上。

經典快排

陣列最後乙個為x,小於等於x的放左邊,大於的放右邊。左右再分別這麼做。

一次劃分,只搞定乙個數

改進的快排

用最後乙個數做劃分,小於的放左邊,等於的放中間,大於的放右邊。左右再劃分,中間不用管。參考荷蘭國旗問題。

一次劃分,搞定了等於這乙個區域的數。

隨機快排

經典快排的問題:用最後乙個數去劃分,很有可能造成左右兩邊的資料規模差距大,使演算法變成o(n^2)

隨機選擇乙個數做劃分,用平均期望去估計複雜度。(o(nlogn),額外空間複雜度o(logn))

堆:完全二叉樹

子節點和父節點的關係:假設父結點在陣列中的位置為i,左孩子在陣列中的位置為:2*i+1;右孩子為2*i+2(不越界條件下,越界相當於不存在);假設知道孩子結點的位置為i(無論左右),則父節點的位置為:(i-1)/2

大根堆:在這棵完全二叉樹中,任何子樹的最大值均為其根節點。

給定乙個陣列,構建大根堆(heapinsert):(經歷乙個新來的數插入到已經有的大根堆的過程)

認為從0位置到i位置都是乙個完全二叉樹,i=0~n-1.在每乙個完全二叉樹中構建大根堆,也就是來乙個數,跟他的父節點比,大就交換。然後大根堆的範圍不斷往下擴。

時間複雜度:o(n)

heapify(陣列中(大根堆)中有個數變小了,如何調整(下沉)使再次成為大根堆)

找到它的左右兩個孩子,其中最大的交換上去。也就是說變小之後的數下沉的過程。

應用:隨時找到乙個流中吐出數的中位數。

準備兩個陣列,乙個構建大根堆,乙個構建小根堆

流吐出來的第乙個數放到大根堆裡

新來的數如果比大根堆的堆頂大,放小根堆去,否則放大根堆,每放進去一次,都得進行一次heapinsert的操作

比較大根堆和小根堆的heapsize,如果大根堆比小根堆size大超過一,則把大根堆的堆頂彈出,放到小根堆;否則,小根堆的堆頂彈出,放大根堆。

這裡有乙個彈出堆頂的操作,實現:將堆頂和最後乙個數交換,heapsize減1,然後剩下的堆來一次heapify操作。

重複上述過程,始終保持兩個堆的size差不超過1

堆排序

來了乙個陣列,先進行heapinsert操作,構建大根堆(這一步並不能保證陣列一定有序,中間可能有亂的,但是堆頂一定是陣列中的最大數)

把堆頂和陣列最後乙個數交換,heapsize–

heapify(每次搞定乙個數,並且給放到陣列末尾)

重複上述操作

先判斷資料是五種基礎型別還是使用者定義的型別

基礎型別:快排

自己定義的:歸併排序

陣列長度很短(<60):插排:常數項極低

歸併排序的額外空間複雜度可以達到o(1),但是非常難,「內部快取法」

快排可以做到穩定性問題,但是非常難。「01 stable sort」

排序演算法小結

1 快速排序 quicksort 快速排序是乙個就地排序,分而治之,大規模遞迴的演算法。從本質上來說,它是歸併排序的就地版本。快速排序可以由下面四步組成。1 如果不多於1個資料,直接返回。2 一般選擇序列最左邊的值作為支點資料。3 將序列分成2部分,一部分都大於支點資料,另外一部分都小於支點資料。4...

排序演算法小結

1 歸併排序 3.區別與聯絡 遞迴是從未知推到已知,相當於把未知的東西壓入棧,等到可以算出結果了,就一步一步出棧。迭代是從已知到未知,從已知的東西一步一步推至目標。遞迴與迭代就好像一對逆元。遞迴的 更加清晰,但開銷更大,也更容易出錯,除錯較困難 而迭代的 編寫更困難,但速度和開銷較小。4.空間占用 ...

排序演算法小結

演算法過程 假設乙個無序的序列,該演算法將其分成兩部分,前一部分已經完成排序 有序,一開始時只有乙個元素 後一部分任然無序,將後面序列選擇第乙個插入到前面的有序序列,如此直到所有完全有序。複雜度 最簡單的即為,整個序列原來即有序,按照一種最 省事 的方式,我們僅需比較n 1次即可。最複雜的情況,應該...