她到目前為止最喜歡的演算法是「氣泡排序」。這是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 這樣,我們可以最後把整個數列割到最小兩個元素的子列,再使子列有序,從而整個數列都有序。值得注意的是,快排不會使某個...