每個數據結構都有它自己的時間複雜性。跳出你最大的是哈希表。插入,刪除和搜索的平均時間都是O(1)。但它確實是不變的時間,因爲可以通過多個代表來找到正確的位置。真正的問題是,如果空間不是問題,我們是否可以在一個操作中完成每個操作?在尋找完美的數據結構
最近我正在研究基數排序,並想出如何儘可能地加快它的速度。我決定做的一件事是做一個2字節的計數排序,因此你只需要循環一次。然後,我開始思考我以前使用的線索,整數在每次修改數字10次後遍歷。這似乎比我嘗試過的任何其他數據結構都要快,但希望使其更快。我今天所嘗試的是將樹狀結構視爲有保證的二級樹。每個節點有2^16(65536)個孩子。這樣我可以像這樣引用每個數字:root-> link [twoByte1] - > link [twoByte2]。其中twoByte1是前16位,2是他第二位。問題是,這是很多記憶。相反,我決定創建一個結構數組,並使用2^16 bool(uint8_t)值,並運行相同的問題。爲了解決這個問題,我做了以下結構。
struct trie {
unsigned int link[2048];
};
我決定使用2048個無符號整數(或簽名,不知道是否會有區別)。這樣我可以在查找過程中將每一位看作真/假值。爲了引用每個位置,我將採用前16個字節,並以前面的方式引用元素,但第二個元素將被32除以找出要使用的整數數組的哪個元素,並再次對該數字進行mod編碼通過32找出哪個位要看。以下是我用來引用它的代碼:
uint8_t getData (int data, uint16_t& dir, uint16_t& pos, uint8_t& x) {
dir = (data >> 0) & 0xffff;
pos = (data >> 16) & 0xffff;
x = pos/32;
return pos % 32;
}
插入功能只是找到點並打開位。要做到這一點,我會從上面的函數中獲取數據,然後或者將特定位與1進行比較。與刪除類似,只有我會反轉位串,然後將其與其關閉。然後爲了搜索那個元素,我只返回特定的位。在這裏找到了如何清除該位的幫助:How do you set, clear, and toggle a single bit?下面是這三個函數的代碼。
void insert(trie *root, int data) {
uint16_t dir, pos;
uint8_t x, y = getData(data, dir, pos, x);
root[dir].link[x] |= 1 << y;
}
bool find(trie *root, int data) {
uint16_t dir, pos;
uint8_t x, y = getData(data, dir, pos, x);
return root[dir].link[x] & (1 << y);
}
void remove(trie *root, int data) {
uint16_t dir, pos;
uint8_t x, y = getData(data, dir, pos, x);
root[dir].link[x] &= ~(1 << y);
}
從這裏就像初始化結構數組一樣簡單。重要的是,隨着元素數量的增加,數據結構將永遠不會進一步擴大。此外,在線程的情況下,因爲我只是在插入過程中打開位,所以我不認爲我需要同步任何線程。因此,它可以加快線程。你對此有什麼想法,我在這裏做了一個測試用例:http://ideone.com/McwWTV。我在運行在i7上的Linux機器上運行測試,並且每2.5秒就能處理2.5億個整數。
對於散列表,如果提前知道可能的輸入數據集(鍵),則可以生成完美散列函數。這樣就不會有任何碰撞。 – 2013-07-13 19:35:23
你的問題是什麼? – delnan
這聽起來更像是你正在尋找http://codereview.stackexchange.com/而不是stackoverflow ... –