Загальна кількість невпорядкованих пар чисел у наборі дорівнює N ( N + 1 ) / 2 . Загальна кількість не упорядкованих пар різних чисел становить N ( N - 1 ) / 2 . Це займає 2 журналу 2 ( N ) = увійти 2 ( N 2 ) біта для представлення впорядкованої пари чисел, і якщо ви маєте один менше біт, ви можете представляти елементи простору до N 2 / 2NN(N+1)/2N(N−1)/22log2(N)=log2(N2)N2/2. Кількість не упорядкованих не обов'язково розрізнених пар трохи більше половини кількості впорядкованих пар, тому ви не можете трохи заощадити в поданні; кількість не упорядкованих окремих пар трохи менше половини, тому ви можете трохи заощадити.
Для практичної схеми, яку легко обчислити, має потужність 2, ви можете працювати над бітовим поданням. Візьміть a = x ⊕ y, де ⊕ - оператор XOR (бітовий ексклюзив або). Пару { x , y } можна відновити з ( a , x ) або ( a , y ) . Тепер ми шукатимемо хитрість, щоб зберегти один біт у другій частині, і надамо симетричну роль x і yNa=x⊕y⊕{x,y}(a,x)(a,y)xyщоб замовлення не вдалося відновити. Зважаючи на обчислення кардинальності вище, ми знаємо, що ця схема не працюватиме у випадку, коли .x=y
Якщо то там є якесь бітове положення, де вони відрізняються. Я напишу x i для i- го біта x (тобто x = ∑ i x i 2 i ), а також y . Нехай k займає найменше бітове положення, де х і у різняться: k - найменше i таке, що x i ≠ y i . k - найменший i такий, що a i 1x≠yxiixx=∑ixi2iykxykixi≠yikiai=1kabxykb=∑i<kxi2i+∑i>kxi2i−1b=∑i<kyi2i+∑i>kyi2i−1) — to make the construction symmetric, pick x if xk=0 and yk=1, and pick y if xk=1 and yk=0. Use (a,b) as the compact representation of the pair. The original pair can be recovered by computing the lowest-order bit that is set in a, inserting a 0 bit at this position in b (yielding one of x or y), and taking the xor of that number with a (yielding the other element of the pair).
In this representation, a can be any nonzero number, and b can be any number with half the range. This is a sanity check: we get exactly the expected number of representations of unordered pairs.
In pseudocode, with ^
, &
, |
, <<
, >>
, ~
being C-like bitwise operators (xor, and, or, left-shift, right-shift, complement):
encode(x, y) =
let a = x ^ y
let k = lowest_set_bit_position(a)
let low_mask = (1 << k) - 1
let z = if x & (1 << k) = 0 then x else y
return (a, (z & low_mask) | (z & ~low_mask) >> 1)
decode(a, b) =
let k = lowest_set_bit_position(a)
let low_mask = (1 << k) - 1
let x = (b & low_mask) | ((b & ~low_mask) << 1)
return (x, a ^ x)