樹形分割槽設計採用C 實現排序

2021-06-23 09:24:10 字數 2397 閱讀 5123

當n比較大時,需要更新大量元素,且元素的值變化比較快的情況下使用:

我們可以把[0, 1,000,000)作為一級區間;再把一級區間分為兩個2級區間[0, 500,000), [500,000, 1,000,000),然後把二級區間二分為4個3級區間[0, 250,000), [250,000, 500,000), [500,000, 750,000), [750,000, 1,000,000),依此類推,最終我們會得到1,000,000個21級區間[0,1), [1,2) … [999,999, 1,000,000)。這實際上是把區間組織成了一種平衡二叉樹結構,根結點代表一級區間,每個非葉子結點有兩個子結點,左子結點代表低分區間,右子結點代表高分區間。樹形分割槽結構需要在更新時保持一種不變數(invariant):非葉子結點的count值總是等於其左右子結點的count值之和。

以後,每次使用者積分有變化所需要更新的區間數量和積分變化量有關係,積分變化越小更新的區間層次越低。總體上,每次所需要更新的區間數量是使用者積分變數的log(n)級別的,也就是說如果使用者積分一次變化在百萬級,更新區間的數量在二十這個級別。在這種樹形分割槽積分表的輔助下查詢積分為s的使用者排名,實際上是乙個在區間樹上由上至下、由粗到細一步步明確s所在位置的過程。比如,對於積分499,000,我們用乙個初值為0的排名變數來做累加;首先,它屬於1級區間的左子樹[0, 500,000),那麼該使用者排名應該在右子樹[500,000, 1,000,000)的使用者數count之後,我們把該count值累加到該使用者排名變數,進入下一級區間;其次,它屬於3級區間的[250,000, 500,000),這是2級區間的右子樹,所以不用累加count到排名變數,直接進入下一級區間;再次,它屬於4級區間的…;直到最後我們把使用者積分精確定位在21級區間[499,000, 499,001),整個累加過程完成,得出排名!

雖然,本演算法的更新和查詢都涉及到若干個操作,但如果我們為區間的from_score和to_score建立索引,這些操作都是基於鍵的查詢和更新,不會產生表掃瞄,因此效率更高。另外,本演算法並不依賴於關係資料模型和sql運算,可以輕易地改造為nosql等其他儲存方式,而基於鍵的操作也很容易引入快取機制進一步優化效能。進一步,我們可以估算一下樹形區間的數目大約為2,000,000,考慮每個結點的大小,整個結構只占用幾十m空間。所以,我們完全可以在記憶體建立區間樹結構,並通過user_score表在o(n)的時間內初始化區間樹,然後排名的查詢和更新操作都可以在記憶體進行。一般來講,同樣的演算法,從資料庫到記憶體演算法的效能提公升常常可以達到10^5以上;因此,本演算法可以達到非常高的效能。

#include class binarytreeclass

};int binarytreeclass::indexout = 0;

binarytreeclass* createtreeclass(binarytreeclass* root, int from, int to)

root = new binarytreeclass(from, to);

if(from == to)

return root;

int mid = from + ((to-from)>>1);

root->left = createtreeclass(root->left, from, mid);

root->right = createtreeclass(root->right, mid+1, to);

return root;

}void insertnewnode(binarytreeclass* root, int score)

if(score>= root->from_score && score<=root->to_score)

int mid = root->from_score + ((root->to_score - root->from_score)>>1);

if(score <= mid)

else }

void getrank1(binarytreeclass* root, int score, int& rank)

getrank1(root->left, score, rank);

} else

}int getrank1(binarytreeclass* root, int score)

void findnodebyindex(binarytreeclass* root, int index, int& from, int& to)//find node by index from root

findnodebyindex(root->right, index, from, to); }}

void printclass(binarytreeclass* root) }

int main()

快速排序,採用遞迴實現

一趟快速排序主要步驟如下 1 設定兩個變數,l r,初始變數分別為left和right,表示待排序列的其實下標和終止下標。2 將第l個記錄暫時存在變數pivot中,這個記錄可以隨意選取,相當於基準值,pivot arr l 3 從下標為r的位置向前搜尋,當找到比基準值小的數時,將其移動到下標為l的位...

常見排序演算法 採用Objective c實現

1 2algorithm4 5 created by 張 漢國 on 11 9 30.6 7 89 import 1011 inte ce sort nsobject 1415 選擇排序 16 void selectsortwitharray nsarray adata 17 插入排序 18 voi...

設計模式四(裝飾模式,採用python 實現)

裝飾模式原理請隨便找書看一下,這裡直接給例子 生產一把刀需要兩個工序,工序一和工序二 process 生產 component 原料 生產刀具的原材料是棒料 bar procedure 生產刀具工序 firstprocedure 工序一 secondprocedure 工序二 from future...