[CareerCup] 17.13 BiNode 双向节点

 

17.13 Consider a simple node-like data structure called BiNode, which has pointers to two other nodes. The data structure BiNode could be used to represent both a binary tree (where nodel is the left node and node2 is the right node) or a doubly linked list (where nodel is the previous node and node2 is the next node). Implement a
method to convert a binary search tree (implemented with BiNode) into a doubly linked list. The values should be kept in order and the operation should be performed in place (that is, on the original data structure).

 

这道题定义了一个双向节点BiNode的类,其既可以表示二叉树的结构,也可以表示为双向链表的结构,让我们把一个二叉树的结构转化为双向链表的结构。我们有很多种方法可以实现,首先来看一种建立一种新数据结构NodePair类,保存了链表的首节点和尾节点,用递归的方法来实现压平二叉树,参见代码如下:

 

解法一:

class BiNode {
public:
    BiNode *node1;
    BiNode *node2;
    int data;
    BiNode(int d): data(d), node1(NULL), node2(NULL) {}
};

class NodePair {
public:
    BiNode *head;
    BiNode *tail;
    NodePair(BiNode *h, BiNode *t): head(h), tail(t) {}
};

void concat(BiNode *x, BiNode *y) {
    x->node2 = y;
    y->node1 = x;
}

NodePair* convert(BiNode *root) {
    if (!root) return NULL;
    NodePair *part1 = convert(root->node1);
    NodePair *part2 = convert(root->node2);
    if (part1) concat(part1->tail, root);
    if (part2) concat(root, part2->head);
    return new NodePair(part1 ? part1->head : root, part2 ? part2->tail : root);
}

 

我们也可以不使用别的数据结构,那么我们如何返回链表的首结点和尾结点呢,我们可以返回首结点,然后通过遍历链表来找到尾结点,参见代码如下:

 

解法二:

int cnt = 0;
class BiNode {
public:
    BiNode *node1;
    BiNode *node2;
    int data;
    BiNode(int d): data(d), node1(NULL), node2(NULL) {}
};


void concat(BiNode *x, BiNode *y) {
    x->node2 = y;
    y->node1 = x;
}

BiNode* get_tail(BiNode *node) {
    if (!node) return NULL;
    while (node->node2) {
        ++cnt;
        node = node->node2;
    }
    return node;
}

BiNode* convert(BiNode *root) {
    if (!root) return NULL;
    BiNode *part1 = convert(root->node1);
    BiNode *part2 = convert(root->node2);
    if (part1) concat(get_tail(part1), root);
    if (part2) concat(root, part2);
    return part1 ? part1 : root;
}

 

还有一种方法是创建一个循环链表,当我们建立了循环链表,那么我们返回首结点时,尾结点可以通过head->node1直接找到,参见代码如下:

 

解法三:

class BiNode {
public:
    BiNode *node1;
    BiNode *node2;
    int data;
    BiNode(int d): data(d), node1(NULL), node2(NULL) {}
};

void concat(BiNode *x, BiNode *y) {
    x->node2 = y;
    y->node1 = x;
}

BiNode* convert_to_circular(BiNode *root) {
    if (!root) return NULL;
    BiNode *part1 = convert_to_circular(root->node1);
    BiNode *part3 = convert_to_circular(root->node2);
    if (!part1 && !part3) {
        root->node1 = root;
        root->node2 = root;
        return root;
    }
    BiNode *tail3 = part3 ? part3->node1 : NULL;
    // Join left to root
    if (!part1) concat(part3->node1, root);
    else concat(part1->node1, root);
    // Join right to root
    if (!part3) concat(root, part1);
    else concat(root, part3);
    // Join right to left
    if (part1 && part3) concat(tail3, part1);
    return part1 ? part1 : root;
}

BiNode* convert(BiNode *root) {
    BiNode *head = convert_to_circular(root);
    head->node1->node2 = NULL;
    head->node1 = NULL;
    return head;
}

 

CareerCup All in One 题目汇总

posted @ 2016-04-29 10:50  Grandyang  阅读(952)  评论(0编辑  收藏  举报
Fork me on GitHub