Oto moja próba. Przechowuje drzewo w tablicy o rozmiarze 2 ** głębokość + 1. Służy a[0]
do przechowywania rozmiaru i a[size]
do przechowywania indeksu pierwszego „pustego węzła”, który napotyka podczas pierwszej głębokości. (Pusty węzeł to miejsce, w którym dziecko byłoby przechowywane, gdyby rodzic je miał). Każdy pusty węzeł zawiera indeks następnego pustego węzła, który zostanie napotkany.
Ten schemat pozwala uniknąć rezerwowania bitów w celu oznaczenia elementów potomnych obecności, dzięki czemu każdy węzeł może korzystać z pełnego zakresu liczb całkowitych. Pozwala również na niezrównoważone drzewa - rodzic może mieć tylko jedno dziecko.
wynik:
empty tree: [0]
head node only: [2,5,0]
example tree: [16,5,3,2,5,14,2,1,0,0, 0,0,9,9,15,0,4];
Enkoder:
//utility
int findDepth(Node* n) {
int l = 0 ,r = 0;
if (n) {
l = 1 + findDepth(n->left);
r = 1 + findDepth(n->right);
}
return ( l > r ) ? l : r;
}
//Encode Function
int* encodeTree(Node* head) {
int* out;
int depth = findDepth(head);
int size = depth>0;
while (depth--) size*=2;
out = calloc(size+1,sizeof(int));
out[0]=size;
encodeNode(head, out,1, out+size);
return out;
}
void encodeNode(Node* n, int* a, int idx, int* pEmpty) {
if (n) {
a[idx]=n->data;
encodeNode(n->left,a,idx*2,pEmpty);
encodeNode(n->right,a,idx*2+1,pEmpty);
}
else if (idx<a[0]) {
*pEmpty = idx;
pEmpty = a+idx;
}
}
Dekoder:
//Decode Function
Node* decodeArray(int* a) {
return (a[0]) ? decodeNode(a,1,a+a[0]) : NULL;
}
Node* decodeNode(int* a, int idx, int* pEmpty) {
Node* n = NULL;
if (idx== *pEmpty)
*pEmpty=a[idx];
else {
n = calloc(1,sizeof(Node));
n->data = a[idx];
if (idx*2<a[0]) {
n->left = decodeNode(a, idx*2, pEmpty);
n->right = decodeNode(a, idx*2+1, pEmpty);
}
}
return n;
}
(dzięki @ Daniel Sobral za naprawienie formatowania)