更好訂貨
我建議使用colexicographical order,在這種情況下,你不會有供應對象的總數。訂購您對這樣的:
0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: …
0&1, 0&2, 1&2, 0&3, 1&3, 2&3, 0&4, 1&4, 2&4, 3&4, 0&5, 1&5, 2&5, 3&5, …
你已經能夠這個名單擴大到無限長,這樣你就可以知道任一對指數不知道的項目數。這樣做,當你添加新的項目,你的數據結構,你只需要添加到您的陣列,而不是重新定位現有項目的效益。我已經調整的指數,以從零開始,當你標記你的問題C++,所以我假設你將使用從零開始的索引。我所有的答案都假設了這個順序。
您也可以可視化的colex排序是這樣的:
a: 0 1 2 3 4 5 …
b:
1 0
2 1 2 index of
3 3 4 5 a&b
4 6 7 8 9
5 10 11 12 13 14
6 15 16 17 18 19 20
⋮ ⋮ ⋱
對單指數
讓我們首先把一對成一個單一的指標。訣竅是,對於每一對,你看第二個位置,並想象在該位置具有較少數字的所有對。因此,例如,對於2&4
對,您首先計算第二個數小於4的所有對。這是從一組4個(即數字0到3)中選擇兩個項的可能方式的數量,所以您可以將其表示爲二項式係數4C2。如果你評估它,你會得到4(4-1)/ 2 = 6。要添加第一個數字,因爲這是索引較低但第二個數字相同的對的數目。對於2&4
這是2,因此2&4
的總體索引是4(4-1)/ 2 + 2 = 8。
一般來說,對於一對一個 & b索引將是 b( b -1)/ 2 + 一個。
int index_from_pair(int a, int b) {
return b*(b - 1)/2 + a;
}
單指數配對
一種方式把單個索引我回一對數字將增加 b直到 b( b +1)/ 2 >我,即,情況會導致指數比我較大的 b下一個值。然後,你可以找到一個作爲差一個 = 我 - b( b -1)/ 2。通過遞增 b這種方法一次涉及使用循環。
pair<int, int> pair_from_index(int i) {
int a, b;
for (b = 0; b*(b + 1)/2 <= i; ++b)
/* empty loop body */;
a = i - b*(b - 1)/2;
return make_pair(a, b);
}
你也可以解釋 b( b -1)/ 2 = 我作爲二次方程,它可以解決使用平方根。你需要的是真實的 b浮點數 b你會得到這個二次方程的正解。由於此方法中由於舍入誤差可能會遇到問題,因此您可能需要檢查是否存在 b( b +1)/ 2> i。如果不是這種情況,就像在循環方法中那樣增加 b。一旦你有 b, a的計算保持不變。
pair<int, int> pair_from_index(int i) {
int b = (int)floor((sqrt(8*i + 1) + 1)*0.5);
if (b*(b + 1)/2 <= i) ++b; // handle possible rounding error
int a = i - b*(b - 1)/2;
return make_pair(a, b);
}
順序存取
請注意,您只需要打開指數回對隨機訪問到您的列表。在遍歷所有對時,一組嵌套循環更容易。因此,而不是
for (int = 0; i < n*(n - 1)/2; ++i) {
pair<int, int> ab = pair_from_index(i);
int a = ab.first, b = ab.second;
// do stuff
}
你最好是寫
for (int i = 0, b = 1; b != n; ++b) {
for (int a = 0; a != b; ++a) {
// do stuff
++i;
}
}
難道我理解正確的話,你正在尋找「索引」的節點列表的排序NC2((8 2 )是最大的,(2 2)是最小假設總是有子女),所以給定索引'n'你想從該排序組合列表中找到一對?是對的嗎 ? – WhozCraig
@WhozCraig:不,該列表僅僅是與一對兩個對象相對應的任意距離值的數組。爲了減少內存消耗,我只是存儲表示距離的浮點值,而不是存儲器消耗的兩倍或兩倍,而不是距離和兩個指向對象的指針。問題是通過數學計算升序對來確定數組條目所代表的哪兩個對象,第一對項目具有優先級。 –
因此,[d1,d2,d3,d4 ...]應該是[1&2,1&3,1&4,2&3 ....]之間的距離,並且根據給定的距離返回[n&m]與之相距的距離?我靠近了嗎? – WhozCraig