Ось моя спроба. Він зберігає дерево в масиві розміром 2 ** глибини + 1. Він використовує a[0]
для утримання розміру та a[size]
утримування індексу першого "порожнього вузла", з яким він стикається, в ході першої глибини. (Порожній вузол - це місце, де зберігалася б дитина, якби у батьків був такий). Кожен порожній вузол містить індекс наступного порожнього вузла, який буде зустрічатися.
Ця схема дозволяє уникнути резервування бітів для позначення дітей презентації, тому кожен вузол може використовувати весь цілий діапазон. Це також дозволяє незбалансовані дерева - батько може мати лише одну дитину.
вихід:
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];
Кодер:
//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;
}
}
Декодер:
//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;
}
(дякую @daniel sobral за виправлення форматування)