氣泡排序深入理解

2022-05-11 14:20:30 字數 3979 閱讀 7874

她到目前為止最喜歡的演算法是「氣泡排序」。這是bessie的對長度為n的陣列a進行排序的奶牛碼實現。

sorted = false

while (not sorted):

sorted = true

moofor i = 0 to n-2:

if a[i+1] < a[i]:

swap a[i], a[i+1]

sorted = false

顯然,奶牛碼中的「moo」指令的作用只是輸出「moo」。奇怪的是,bessie看上去執著於在她的**中的不同位置使用這個語句。

給定乙個輸入陣列,請**bessie的**會輸出多少次「moo」。

題意即進行多少次氣泡排序

比如:6 1 2 3 4 5 進行一次為 1 2 3 4 5 6

那麼對於位置i, 氣泡排序進行到i-1時, \(a_\)為前i1個數中最大的乙個, 如果它大於\(a_i\)那麼它就會到\(a_i\)的後面

由此可推知, 每一次位置i前都會將乙個比\(a_i\)大的數推至其後, 直至沒有比它大的

那麼我們對每位置求一下它前面有幾個比它大就好啦(注意要將答案加一)

具體來說先進行離散化, 再樹狀陣列求解即可

**:

#include#include#include#includeusing namespace std;

const int n = 100500;

int d[n], n;

int read(void)

return x;

}struct node

}p[n];

inline int low(int x)

int get(int x)

void add(int x)

bool cmp(node i,node j)

int main() ;

sort(p + 1,p + n + 1);

for (int i = 1;i <= n; i++) p[i].val = i;

sort(p + 1,p + n + 1, cmp);

int ans = 0;

for (int i = 1;i <= n; i++)

printf ("%d\n", ans+1);

return 0;

}

sorted = false

while (not sorted):

sorted = true

moofor i = 0 to n-2:

if a[i+1] < a[i]:

swap a[i], a[i+1]

for i = n-2 downto 0:

if a[i+1] < a[i]:

swap a[i], a[i+1]

for i = 0 to n-2:

if a[i+1] < a[i]:

sorted = false

給定乙個輸入陣列,請**bessie的**會輸出多少次「moo」。

題意:求雙向氣泡排序的排序次數

我們暫且稱它為平衡條件吧

首先將序列離散化

相比較於out of sorts s, 本題思路在於不動的位置, 結論為對於位置x, ans = max

為什麼呢

在x不滿足平衡條件的時候

因為它不滿足平衡條件

因為回來的時候一定會冒泡出乙個位置在x後的最小值, 因為x不滿足平衡條件, 所以最小值小於等於x, 就又插了回來

有人可能會問為什麼out of sorts s不能用這個式子嘞, 因為每次換出的一定大於x, 但x+1位置上的數可能換過來, 而它有可能大於x

由此可知, 求每個位置前大於其的數就行啦

**:

#include#include#include#includeusing namespace std;

const int n = 100500;

int d[n], n;

int read(void)

return x;

}struct node

}p[n];

inline int low(int x)

int get(int x)

void add(int x)

bool cmp(node i,node j)

int main() ;

sort(p + 1,p + n + 1);

for (int i = 1;i <= n; i++) p[i].val = i;

sort(p + 1,p + n + 1, cmp);

int ans = 1;

for (int i = 1;i <= n; i++)

printf ("%d\n", ans);

return 0;}/*

62 5 6 3 1 4

*/

以下是bessie最初的對陣列aa進行排序的實現的概要。她首先寫了乙個簡單的函式,執行氣泡排序的一輪:

bubble_sort_pass (a)
她的快速排序(相當快)函式的遞迴**是按下面的樣子構成的:

quickish_sort (a)  while (no partition points exist in a) 

divide a at all partition points; recursively quickish_sort each piece

}

bessie好奇於她的**能夠執行得多快。簡單起見,她計算出她得主迴圈的每一輪都消耗線性時間,所以她相應增加乙個全域性變數work_counter的值,以此來跟蹤整個演算法總共完成的工作量。

給定乙個輸入陣列,請**quickish_sort函式接收這個陣列之後,變數work_counter的最終值。

求每一次氣泡排序的長度, 不如求每乙個點被氣泡排序了幾次

定義分割點為i與i+1的分割線,不妨假設它就在i上吧

再次定義序列排好序的標準

那麼接下來我們要求分割點的出現時間t陣列

對於每個點它不用在進行氣泡排序了當且僅當兩邊都已成為分割點, 也就是兩邊出現時間的最大值

依據t陣列,我們可以求出每個點被排了幾次

首先離散化

對於乙個點x來說, 所有小於它的數卻在它後面的, 每一次都會向前走一次

那麼它出現的時間就是離它最遠的小於它的點冒泡到它前面的時間

即那個點到它的距離, 具體見**

所以單調佇列或指標都可以維護

**:

#include#include#include#include#includeusing namespace std;

const int n = 100500;

int d[n], n;

int read(void)

return x;

}struct node

}p[n];

bool cmp(node i,node j)

int t[n], k;

int main() ;

sort(p + 1,p + n + 1);

for (int i = 1;i <= n; i++) p[i].val = i;

sort(p + 1,p + n + 1, cmp);

long long ans = 0;

k = n;

for (int i = n;i >= 1; i--)

for (int i = 0;i < n; i++) ans += max(t[i], t[i+1]);

printf ("%lld\n", ans);

return 0;}/*

62 5 6 3 1 4

*/

深入理解氣泡排序

氣泡排序可能非你所想。氣泡排序的思路 給定乙個陣列,每次迴圈出最大的數依次向後排,並將較小的數向前冒。平均時間複雜度 o n 2 最好情況 o n 已經排好序 最壞情況 o n 2 倒敘的時候 空間複雜度 o 1 沒有占用額外的空間 穩定性 穩定 排序前相等的兩個數,排序後位置不變 氣泡排序值得注意...

深入理解希爾排序

希爾排序是按照不同步長對元素進行分組插入排序的,當剛開始元素很無序的時候,步長最大,所以插入排序的元素個數很少,速度很快 當元素基本有序了,步長很小,插入排序對於有序的序列效率很高。所以,希爾排序的時間複雜度會優於o n 2 具體實現 如下,先看一種複雜一點的,但是便於理解的實現 for int i...

深入理解快速排序

快速排序分為兩部分 2,快排函式本身,通過遞迴呼叫自身,每次呼叫可以使乙個元素回歸正確的位置,並使該元素之前的元素都小於該元素,之後的元素都大於該元素 遞迴的退出條件是base top 這樣,我們可以最後把整個數列割到最小兩個元素的子列,再使子列有序,從而整個數列都有序。值得注意的是,快排不會使某個...