[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 题目汇总

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值