การเข้ารหัสต้นไม้แบบไบนารี


12

สมมติว่าคุณมีต้นไม้ไบนารีที่สมบูรณ์ (เช่นแต่ละโหนดภายในมีสองลูกหลานที่ไม่ว่างเปล่า) แต่ละโหนดมีจำนวนเต็มไม่ใช่ศูนย์ คุณได้รับภารกิจการเข้ารหัสและถอดรหัสทรีลงใน / จากรายการจำนวนเต็ม

ต้นไม้ถูกเก็บไว้ภายในสิ่งที่ชอบ:

struct node {
  int data;
  struct node *left, *right;
};

และคุณต้องใช้สองฟังก์ชั่น:

int *encode(struct node *root);
struct node *decode(int *array);

มันขึ้นอยู่กับคุณว่าคุณเข้ารหัสและถอดรหัสอย่างไร

คะแนนสำหรับ:

  • ความยาวการเข้ารหัสขั้นต่ำ
  • ความซับซ้อน (นึกคิดเชิงเส้นในจำนวนโหนด)
  • ความคิดริเริ่ม

ไม่มีคะแนนสำหรับความยาวซอร์สโค้ดและคุณไม่ได้ถูก จำกัด ไว้ที่ C

ตัวอย่างต้นไม้:

     5
    / \
   3   2
      / \
     2   1
    / \
   9   9

1
ข้อกำหนดอินพุตและเอาต์พุตจะไม่เจ็บ
Yasir Arsanukaev

2
@Yasir: อัลกอริทึมการเข้ารหัสเป็นงานของคุณดังนั้นฉันจึงไม่สามารถให้อินพุตและเอาต์พุตได้ int *เป็นกล่องดำสำหรับผู้ใช้
Alexandru

มีข้อ จำกัด ใด ๆ ในช่วงจำนวนเต็มหรือไม่ โดยเฉพาะอย่างยิ่งถ้าเราใช้ภาษาที่มีจำนวนเต็มขนาดใหญ่โดยพลการเราอนุญาตให้ใช้มันได้หรือไม่? และขนาดของข้อมูลที่เข้ารหัสถูกวัดเป็นจำนวนเต็มหรือจำนวนไบต์?
sepp2k

ฟังก์ชั่นการเข้ารหัสและถอดรหัสต้องปราศจากผลข้างเคียง (นอกเหนือจากการจัดสรรหน่วยความจำ) หรือไม่? หรือพวกเขาอาจยกตัวอย่างเช่นเก็บข้อมูลในตัวแปรทั่วโลก?
sepp2k

1
สมมติว่าข้อมูลจำนวนเต็มนั้นเป็นจำนวนเต็ม 32 บิตจริง ๆ แล้วมีการเข้ารหัสอย่างง่ายที่ใช้บิต 32 * n เท่านั้น
อานนท์

คำตอบ:


2

~ 1.03 N

ดูเหมือนว่าคำตอบทั้งหมดใช้เวลาอย่างน้อย 2 * N * 32- บิตในการจัดเก็บ (ยกเว้นโซลูชันในภาษาที่อนุญาตให้มีค่าจำนวนเต็มยาวกว่า 32 บิตเช่น Haskell และ Ruby solutions - แต่โซลูชั่นเหล่านั้นยังคงต้องใช้ไบต์เพิ่มเติมเพื่อเข้ารหัสเมื่อใดก็ตามที่ข้อมูลมีค่ามากกว่า 16K)

นี่คือวิธีการแก้ปัญหาซึ่งใช้ N + ceiling (N / 32) +1 ของการจัดเก็บข้อมูล วิธีนี้เป็น 1.03125 N สำหรับ N ขนาดใหญ่และต่ำกว่า 1.1 N สำหรับ N ทั้งหมดมากกว่า 20

แนวคิดคือการเก็บบิตเพิ่มเติมสำหรับแต่ละโหนดโดยที่ 1 คือ "hasChildren" บิตเหล่านี้บรรจุในคำศัพท์ N / 32 ล่วงหน้า

int* encodeHelper(Node* n, int* code, int* pos, int* flag)
{
   int hasKids = (n->left!=0);
   code[*flag/32]|=hasKids<<(*flag&31);
   *flag+=1;
   if (hasKids) bencodeHelper(n->left, code, pos, flag);
   code[*pos]=n->data;
   *pos+=1;
   if (hasKids) bencodeHelper(n->right, code, pos, flag);
   return code;
}

int* encode(Node* h, int* sizeOut)
{
   int nnodes=countNodes(h);
   int nflags = (int)ceil(nnodes/32.0);
   int pos=nflags+1;
   int flag=32;
   int* out;
   *sizeOut = 1+nnodes+nflags;
   out = calloc(*sizeOut, sizeof(int));
   if (!h) return out;
   out[0]=nflags+1; //store start of data
   return encodeHelper(h,out,&pos,&flag);
}

Node* decodeHelper(int* code, int* pos, int* flag)
{
   Node*n = calloc(1, sizeof(Node));
   int hasKids = code[*flag/32]>>(*flag&31)&1;
   *flag+=1;
   if (hasKids) n->left = bdecodeHelper(code, pos, flag);
   n->data = code[*pos];
   *pos+=1;
   if (hasKids) n->right = bdecodeHelper(code, pos, flag);
   return n;
}

Node* decode(int* code)
{
   int flag=32;
   int pos=code[0];
   if (!pos) return NULL;
   return decodeHelper(code, &pos, &flag);
}

(บังคับใช้การดำเนินการที่นี่)


5

โปรแกรม Haskell นี้เข้ารหัสต้นไม้ของโหนด n ใน n จำนวนเต็ม เคล็ดลับคือการเข้ารหัสข้อมูลของโหนดเป็นสองเท่าจากนั้นใช้บิตลำดับล่างเพื่อระบุว่านี่เป็นโหนดใบไม้หรือโหนดภายใน

ในทางเทคนิคแล้วParserMonad ที่นี่ฆ่ามากกว่าเนื่องจากมีตัวแยกวิเคราะห์เพียงตัวเดียวที่สร้างขึ้นdecoderและฉันสามารถวางตรรกะการแยกวิเคราะห์ไว้ที่นั่นโดยตรง แต่ด้วยวิธีนี้ตัวถอดรหัสมีความชัดเจนมากและParserแม้จะมีขนาดที่เล็ก แต่ก็เป็นกรอบการแยกวิเคราะห์แบบง่าย ๆ ที่สมเหตุสมผล

import Control.Monad (ap)

data Tree = Leaf Integer | Node Integer Tree Tree
  deriving (Eq, Show)

encode :: Tree -> [Integer]
encode (Leaf n)     = [n*2]
encode (Node n t u) = (n*2+1) : encode t ++ encode u

decode :: [Integer] -> Maybe Tree
decode = fullyParse decoder
  where
    decoder :: Parser Integer Tree
    decoder = do
      i <- next
      let n = i `div` 2
      if even i
        then return (Leaf n)
        else return (Node n) `ap` decoder `ap` decoder

-- A simple Parsing Monad
data Parser a b = P { runParser :: [a] -> Maybe (b, [a]) }

instance Monad (Parser a) where
  return a = P ( \ts -> Just (a, ts) )
  p >>= q  = P ( \ts -> runParser p ts >>= (\(v,ts') -> runParser (q v) ts') )
  fail _   = P ( const Nothing )

next :: Parser a a
next = P n
 where n (t:ts) = Just (t,ts)
       n _      = Nothing

fullyParse :: Parser a b -> [a] -> Maybe b
fullyParse p ts = runParser p ts >>= consumedResult
  where
    consumedResult (v,[]) = Just v
    consumedResult _      = Nothing

-- Example
main :: IO ()
main = do
    putStrLn $ "example:  " ++ show ex
    putStrLn $ "encoding: " ++ show encEx
    putStrLn $ "decoding: " ++ show decEx
    putStrLn $ "worked?   " ++ show worked
  where
    ex = Node 5
          (Leaf 3)
          (Node 2
            (Node 2
              (Leaf 9)
              (Leaf 9)
            )
            (Leaf 1)
          )
    encEx = encode ex
    decEx = decode encEx
    worked = maybe False (ex ==) decEx

การทำเช่นนี้จะทำให้คุณได้รับ:

> runhaskell TreeEncoding.hs 
example:  Node 5 (Leaf 3) (Node 2 (Node 2 (Leaf 9) (Leaf 9)) (Leaf 1))
encoding: [11,6,5,5,18,18,2]
decoding: Just (Node 5 (Leaf 3) (Node 2 (Node 2 (Leaf 9) (Leaf 9)) (Leaf 1)))
worked?   True

4

ในซี

#include <stdlib.h>
#include <stdio.h>

struct Node;
typedef struct Node Node;

struct Node
{
    int   data;
    Node* left;
    Node* right;
};
/* Private Functions */
static int*  encodeNode(Node* tree, int* store);
static Node* decodeNode(int** store);

/* Public Functions */
Node*   newNode(int data,Node* left,Node* right);
void    deleteTree(Node* tree);
int     countNodesTree(Node* tree);
int*    encode(Node *tree);
Node*   decode(int* store);
void    printTree(Node* tree);

Node* newNode(int data,Node* left,Node* right)
{
    Node* result    = (Node*)malloc(sizeof(Node));
    result->data    = data;
    result->left    = left;
    result->right   = right;

    return result;
}

void deleteTree(Node* tree)
{
    if (tree == NULL)
    {   return;
    }

    deleteTree(tree->left);
    deleteTree(tree->right);
    free(tree);
}

int countNodesTree(Node* tree)
{
    if (tree == NULL)
    {   return 0;
    }

    return    countNodesTree(tree->left)
            + countNodesTree(tree->right)
            + 1;
}

void printTree(Node* tree)
{
    if (tree == NULL)
    {
        fprintf(stdout, "- ");
    }
    else
    {
        fprintf(stdout, "%d ", tree->data);
        printTree(tree->left);
        printTree(tree->right);
    }
};

การเข้ารหัส:

int* encode(Node *tree)
{
    int     nodeCount   = countNodesTree(tree);
    int*    result      = (int*)malloc(sizeof(int) * (nodeCount * 2 + 1));

    // Put the node count in the first element.
    // This makes it easy to also serialize this object for transport
    // i.e. you can put it in a file or a stream (socket) and easily recover it.
    result[0]           = nodeCount;
    encodeNode(tree, result + 1);
    return result;
}

int* encodeNode(Node* tree, int* store)
{
    if (tree != NULL)
    {
        store[0]    = tree->data;
        /*
         * Slight overkill. for this question.
         * But works and makes future enhancement easy
         */
        store[1]    = (tree->left  == NULL ? 0 : 1)
                    + (tree->right == NULL ? 0 : 2);
        store += 2;

        store       = encodeNode(tree->left,  store);
        store       = encodeNode(tree->right, store);
    }
    return store;
}

ถอดรหัส:

Node* decode(int* store)
{
    if (store == NULL)
    { fprintf(stderr, "Bad Input terminating: encode() always return non NULL\n");
      exit(1);
    }

    if (store[0] == 0)
    {
        return NULL;
    }

    store++;
    return decodeNode(&store);
}

Node* decodeNode(int** store)
{
    int     value   = (*store)[0];
    int     flag    = (*store)[1];
    (*store) += 2;

    Node*   left    = flag & 1 ? decodeNode(store) : NULL;
    Node*   right   = flag & 2 ? decodeNode(store) : NULL;

    return newNode(value, left, right);
}

หลัก:

int main()
{
    Node*   t = newNode(5,
                        newNode(3, NULL, NULL),
                        newNode(2,
                                newNode(2,
                                        newNode(9, NULL, NULL),
                                        newNode(9, NULL, NULL)
                                       ),
                                newNode(1, NULL, NULL)
                               )
                       );

    printTree(t);
    fprintf(stdout,"\n");

    int*    e   = encode(t);
    Node*   d   = decode(e);
    printTree(d);
    fprintf(stdout,"\n");

    free(e);
    deleteTree(d);
    deleteTree(t);
}

บันทึก. แต่ละโหนดจะถูกเข้ารหัสเป็นจำนวนเต็มสองจำนวน (บวกหนึ่ง int สำหรับจำนวนโหนด)
ดังนั้นทรีที่ให้มาเข้ารหัสเช่นนี้:

 7, 5, 3, 3, 0, 2, 3, 2, 3, 9, 0, 9, 0 1, 0
 ^  ^
 ^  ^ Node 1
 ^
 Count

3

ใน Ruby ด้วยการเข้ารหัสเดียวกันกับ@MtnViewMark :

class Node
        def initialize(data, left = nil, right = nil)
                @data, @left, @right = data, left, right
        end

        def encode
                "%d %s %s" % [@data<<1|1, @left.encode, @right.encode]
        end

        class << self
                def decode(str)
                        _decode(str.split.map &:to_i)
                end

                private

                def _decode(a)
                        n = a.shift
                        if n & 1 == 1
                                Node.new(n>>1, _decode(a), _decode(a))
                        else
                                Leaf.new(n>>1)
                        end
                end
        end
end

class Leaf < Node
        def encode
                (@data<<1).to_s
        end
end

tree=Node.decode("11 6 5 5 18 18 2")
print tree.encode

ค่าใช้จ่ายเป็นจำนวนเต็มหนึ่งต่อโหนด ( data << 1 | has_childs):

11 6 5 5 18 18 2

ว้าว - นั่นดูผอมและสง่างาม อย่างไรก็ตามมันไม่ใช้อาเรย์ของ int ใช่ไหม?
ผู้ใช้ที่ไม่รู้จัก

2

รับต้นไม้ไบนารีด้วยnโหนดนี้เข้ารหัสในรายการ2n + 1จำนวนเต็ม ทั้งอัลกอริธึมการเข้ารหัสและถอดรหัสมีO(n)ความซับซ้อน

ฉันใช้จำนวนเต็ม 0 เป็นเครื่องหมายแสดงเวลาเมื่อเข้ารหัสแสดงเมื่อฉันเปิดการสอบถามซ้ำ จากนั้นเมื่อฉันถอดรหัสฉันใส่โหนดของต้นไม้ที่ฉันสร้างบนสแต็ก (แปลก ๆ ) และใช้ 0s ในรายการเพื่อติดตามตำแหน่งที่จะเพิ่มโหนดถัดไป ฉันไม่ได้ลอง แต่ฉันค่อนข้างมั่นใจว่าการถอดรหัสจะแตกถ้าต้นไม้ไม่สมบูรณ์

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

// Prototypes
struct BTnode;
struct BTnode * bt_add_left(struct BTnode * node, int data);
struct BTnode * bt_add_right(struct BTnode * node, int data);
int             bt_depth(struct BTnode * tree);
int             bt_encode_preorder(int * list, struct BTnode * tree, int index);
struct BTnode * bt_node_create(int data);
int             bt_node_delete(struct BTnode * node);
void            bt_print_preorder(struct BTnode * tree);
int *           encode(struct BTnode * tree);
struct BTnode * decode(int * list);

// Binary tree node
struct BTnode
{
  int data;
  struct BTnode *left, *right;
};

// Add node to this node's left
struct BTnode * bt_add_left(struct BTnode * node, int data)
{
  struct BTnode * newnode = bt_node_create(data);
  node->left = newnode;
  return newnode;
}

// Add node to this node's right
struct BTnode * bt_add_right(struct BTnode * node, int data)
{
  struct BTnode * newnode = bt_node_create(data);
  node->right = newnode;
  return newnode;
}

// Determine depth of the tree
int bt_depth(struct BTnode * tree)
{
  int depth;
  int leftdepth = 0;
  int  rightdepth = 0;
  if( tree == NULL ) return 0;

  if( tree->left != NULL )
    leftdepth = bt_depth(tree->left);
  if( tree->right != NULL )
    rightdepth = bt_depth(tree->right);

  depth = leftdepth;
  if(rightdepth > leftdepth)
    depth = rightdepth;

  return depth + 1;
}

// Recursively add node values to integer list, using 0 as an unfolding sentinel
int bt_encode_preorder(int * list, struct BTnode * tree, int index)
{
  list[ index++ ] = tree->data;

  // This assumes the tree is complete (i.e., if the current node does not have
  // a left child, then it does not have a right child either)
  if( tree->left != NULL )
  {
    index = bt_encode_preorder(list, tree->left, index);
    index = bt_encode_preorder(list, tree->right, index);
  }

  // Add sentinel
  list[ index++ ] = 0;
  return index;
}

// Allocate memory for a node
struct BTnode * bt_node_create(int data)
{
  struct BTnode * newnode = (struct BTnode *) malloc(sizeof(struct BTnode));
  newnode->left = NULL;
  newnode->right = NULL;
  newnode->data = data;
  return newnode;
}

// Free node memory
int bt_node_delete(struct BTnode * node)
{
  int data;
  if(node == NULL)
    return 0;
  data = node->data;

  if(node->left != NULL)
    bt_node_delete(node->left);
  if(node->right != NULL)
    bt_node_delete(node->right);

  free(node);
  return data;
}

// Print all values from the tree in pre-order
void bt_print_preorder(struct BTnode * tree)
{
  printf("%d ", tree->data);
  if(tree->left != NULL)
    bt_print_preorder(tree->left);
  if(tree->right != NULL)
    bt_print_preorder(tree->right);
}

// Decode binary tree structure from a list of integers
struct BTnode * decode(int * list)
{
  struct BTnode * tree;
  struct BTnode * nodestack[ list[0] ];
  int i,j;

  // Handle trivial case
  if( list == NULL ) return NULL;

  tree = bt_node_create( list[1] );
  nodestack[ 1 ] = tree;

  j = 1;
  for(i = 2; i < list[0]; i++)
  {
    if( list[i] == 0 )
    {
      //printf("popping\n");
      j--;
    }
    else
    {
      if( nodestack[j]->left == NULL )
      {
        //printf("Adding %d to left of %d\n", list[i], nodestack[j]->data);
        nodestack[ j+1 ] = bt_add_left(nodestack[j], list[i]);
        j++;
      }
      else
      {
        //printf("Adding %d to right of %d\n", list[i], nodestack[j]->data);
        nodestack[ j+1 ] = bt_add_right(nodestack[j], list[i]);
        j++;
      }
    }
  }

  return tree;
}

// Encode binary tree structure as a list of integers
int * encode(struct BTnode * tree)
{
  int maxnodes, depth, length;
  int * list;
  int j;

  // Handle trivial case
  if(tree == NULL) return NULL;

  // Calculate maximum number of nodes in the tree from the tree depth
  maxnodes = 1;
  depth = bt_depth(tree);
  for(j = 0; j < depth; j++)
  {
    maxnodes += pow(2, j);
  }

  // Allocate memory for the list; we need two ints for each value plus the
  // first value in the list to indicate length
  list = (int *) malloc( ((maxnodes * 2)+1) * sizeof(int));
  length = bt_encode_preorder(list, tree, 1);
  list[ 0 ] = length;
  return list;
}

int main()
{
  struct BTnode * tree;
  struct BTnode * newtree;
  int * list;
  int i;

  /* Provided example

        5
       / \
      3   2
         / \
        2   1
       / \
      9   9
  */
  tree = bt_node_create(5);
  bt_add_left(tree, 3);
  struct BTnode * temp = bt_add_right(tree, 2);
  bt_add_right(temp, 1);
  temp = bt_add_left(temp, 2);
  bt_add_left(temp, 9);
  bt_add_right(temp, 9);
  printf("T (traversed in pre-order):  ");
  bt_print_preorder(tree);
  printf("\n");

  list = encode(tree);
  printf("T (encoded as integer list): ");
  for(i = 1; i < list[0]; i++)
    printf("%d ", list[i]);
  printf("\n");

  newtree = decode(list);
  printf("T' (decoded from int list):  ");
  bt_print_preorder(newtree);
  printf("\n\n");


  // Free memory
  bt_node_delete(tree);
  bt_node_delete(newtree);
  free(list);
  return 0;
}

บันทึกสิ่งนี้เมื่อencode.cรวบรวมและดำเนินการแล้ว โปรแกรมนี้ใช้ต้นไม้ตัวอย่างที่คุณให้ไว้และฉันได้ทำการทดสอบกับผู้อื่นแล้ว

$ gcc -Wall -lm -o encode encode.c
$ ./encode 
T (traversed in pre-order):  5 3 2 2 9 9 1 
T (encoded as integer list): 5 3 0 2 2 9 0 9 0 0 1 0 0 0 
T' (decoded from int list):  5 3 2 2 9 9 1

มันเป็นสิ่งที่ฉันมีอยู่ในใจ :)
Alexandru

จะไม่ล้มเหลวในการถอดรหัสหากข้อมูลมี 0
AShelly

@ ASHelly เขากล่าวอย่างชัดเจนว่า 0 จะไม่รวมอยู่ในต้นไม้ ถ้าเป็นเช่นนั้นแล้วใช่สิ่งนี้จะล้มเหลว
Daniel Standage

2

รหัสของฉันเข้ารหัสต้นไม้ในเส้นทางการสั่งซื้อล่วงหน้าแต่ละใบในสอง ints (ข้อมูลตามด้วย 0) และแต่ละโหนดภายในในหนึ่ง int (ข้อมูลตามด้วยลูกซ้ายของมันแล้วขวา) สำหรับต้นไม้ไบนารีที่สมบูรณ์ (ตามที่คุณกำหนด) ด้วยโหนด n, n ต้องเป็นเลขคี่และมี (n + 1) / 2 ใบและ (n-1) / 2 โหนดภายในดังนั้นนั่นคือ 3n / 2 + 1 / 2 จำนวนเต็มสำหรับการเข้ารหัส

คำเตือน: ยังไม่ได้ทดสอบเพิ่งพิมพ์ลงไป

struct node {
  int data;
  struct node *left, *right;
};

void encodeInternal(struct node *root, vector<int> *buf) {
  buf->push_back(root->data);
  if (root->left) {
    encodeInternal(root->left, buf);
    encodeInternal(root->right, buf);
  } else {
    buf->push_back(0);
  }
}
int *encode(struct node *root) {
  vector<int> buf;
  encodeInternal(root, &buf);
  return &buf[0];
}

struct decodeResult {
  int encoded_size;
  struct node *n;
}
struct decodeResult decodeInternal(int *array) {
  struct node *n = (struct node*)malloc(sizeof(struct node));
  n->data = array[0];
  if (array[1] == 0) {
    n->left = n->right = NULL;
    return (decodeResult){2, n};
  } else {
    decodeResult L = decodeInternal(array + 1);
    decodeResult R = decodeInternal(array + 1 + L.encoded_size);
    n->left = L.n;
    n->right = R.n;
    return (decodeResult){1 + L.encoded_size + R.encoded_size, n};
  }
}
struct node *decode(int *array) {
  return decodeInternal(array).n;
}

1

นี่คือความพยายามของฉัน มันเก็บต้นไม้ในอาร์เรย์ขนาด 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 สำหรับการแก้ไขการจัดรูปแบบ)


1

Scala:

trait Node {
  def encode (): Array[Int]
}

case object Node {
  def decode (a: Array[Int]): InnerNode = {
    if (a.length == 1) InnerNode (a(0)) else {
      val r = InnerNode (a(1)) 
      val l = decode (a.tail.tail) 
      InnerNode (a(0), l, r) 
    }
  }
}

case object Leaf extends Node {
  def encode (): Array[Int] = Array.empty
}

case class InnerNode (val data: Int, var l: Node=Leaf, var r: Node=Leaf) extends Node {
  def encode (): Array[Int] = Array (data) ++ r.encode () ++ l.encode () 
}

object BinTreeTest extends App {
  println (Node.decode (Array (1, 2, 3, 4, 5)).encode.mkString (", "))
}

นี่เป็นวิธีการที่ใช้ไวยากรณ์ที่เลิกใช้แล้ว แต่คอมไพล์โดยไม่มีข้อผิดพลาดใน Scala 2.9.1 มันสร้างทรีและถอดรหัสทรีที่เข้ารหัสแล้วไปยังอาร์เรย์เดียวกันกับที่ใช้สำหรับการเข้ารหัส บางทีฉันอาจกำจัดคำเตือนที่เลิกใช้แล้วในวันนี้

ว้าว - นั่นเป็นเรื่องง่าย ความคิดแรกทำงานได้ทันที

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.