算法導論習題解答系列停了一年了,現在重新拾起,好多算法已經忘了,有的記得大概,但是真正的用代碼實現卻很難下手。
CLRS 14.1-3 寫出OS-SELECT的非遞歸形式
一般遞歸形式改寫為非遞歸形式要用到while,有時還要用到棧結構。
OS-SELECT(x, i) { r = size[left[x]] + 1; while (r != i) { if (i < r) { x = left[x]; r = size[left[x]] + 1; } else { x = right[x]; i = i -r; r = size[left[x]] + 1; } } return x; }
CLRS 14.1-4 寫出一個遞歸過程OS-KEY-RANK(T, k)
int OS-KEY-RANK(T, k) { if (k == key[root[T]]) return size[left[root[T]]] + 1; else if (k < key[root[T]]) return OS-KEY-RANK(left[root[T]], k); else return OS-KEY-RANK(right[root[T]], k) + size[left[root[T]]] + 1; }
CLRS 14.1-5 確定元素x的第i個后繼,時間為lg(n)
GET-SUCCESSOR(T, x, i) { r = OS-RANK(T, x); return OS-SELECT(root[T], r + i); }
CLRS 14.1-6
在這題中,將每個結點的秩存於該結點自身之中,這個秩是相對於以該結點為根的子樹而言的。
因而在插入結點x時,對於從root到x結點的路經上的所有結點y,如果插入路經經過y的左支,則rank[y]的值加1,若經過其右支,則rank[y]的值不變。
在刪除結點x時,對於從root到x結點的路經上的所有結點y,如果刪除路經經過y的左支,則rank[y]的值減1,若經過其右支,則rank[y]的值不變。
如圖,在進行右旋轉時,x的秩是不變的,node的秩變為rank[node]減去原來的rank[x]。左旋同理。

CLRS 14.1-7 利用順序統計樹在O(nlgn)的時間內統計逆序對
在習題2-4中,其要求用歸並排序來計算逆序對,見算法導論2-4習題解答(合並排序算法)
在這里,我們對於數組{2,3,8,6,1}這樣分析,對於每個數,選取其前面的數與其比較,
對於6,與其對比的為2,3,8,逆序對有1對,記作inversion_count,
6在原數組的索引為3,記作j,
然后我們來分析子數組{2,3,8,6},6在其中的排名為3,記作rank_j;
再通過分析其他數,我們歸納如下:
inversion_count = j + 1 - rank_j
當把每個結點插入順序統計樹時,我們可以知道j的值,同時調用OS-RANK來得到rank_j,從而得到inversion_count,在這里,每插入一次,就計算一次。
由於插入和OS-RANK都是lg(n),故n個結點即為n*lg(n)。
CLRS 14.1-8 現有一個圓上的n條弦,每條弦都按其端點來定義,請給出一個能在O(n*lgn)時間內確定圓內相交弦的對數的算法,假設任意兩條弦都不會共享端點。

