[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;
}

本文转自博客园Grandyang的博客,原文链接:双向节点[CareerCup] 17.13 BiNode ,如需转载请自行联系原博主。

相关文章
|
存储 安全 Unix
【Shell 命令集合 文件管理】Linux chmod命令使用教程
【Shell 命令集合 文件管理】Linux chmod命令使用教程
752 0
|
6月前
|
固态存储 关系型数据库 数据库
从Explain到执行:手把手优化PostgreSQL慢查询的5个关键步骤
本文深入探讨PostgreSQL查询优化的系统性方法,结合15年数据库优化经验,通过真实生产案例剖析慢查询问题。内容涵盖五大关键步骤:解读EXPLAIN计划、识别性能瓶颈、索引优化策略、查询重写与结构调整以及系统级优化配置。文章详细分析了慢查询对资源、硬件成本及业务的影响,并提供从诊断到根治的全流程解决方案。同时,介绍了索引类型选择、分区表设计、物化视图应用等高级技巧,帮助读者构建持续优化机制,显著提升数据库性能。最终总结出优化大师的思维框架,强调数据驱动决策与预防性优化文化,助力优雅设计取代复杂补救,实现数据库性能质的飞跃。
1030 0
|
Kubernetes Docker 容器
Job for docker.service failed because the control process exited with error code.
Job for docker.service failed because the control process exited with error code.
2691 0
|
Java Linux Windows
java:获取本机IP,Linux环境下使用InetAddress.getLocalHost()方法获得127.0.0.1
java:获取本机IP,Linux环境下使用InetAddress.getLocalHost()方法获得127.0.0.1
1903 0
java:获取本机IP,Linux环境下使用InetAddress.getLocalHost()方法获得127.0.0.1
|
存储 前端开发 数据安全/隐私保护
|
存储 Kubernetes Cloud Native
容器、容器集群管理平台与Kubernetes技术漫谈
我们为什么使用容器? 我们为什么使用虚拟机(云主机)? 为什么使用物理机? 这一系列的问题并没有一个统一的标准答案。因为以上几类技术栈都有自身最适用的场景,在最佳实践之下,它们分别都是不可替代的。 原本没有虚拟机,所有类型的业务应用都直接跑在物理主机上面,计算资源和存储资源都难于增减,要么就是一直不够用,要么就一直是把过剩的资源浪费掉,所以后来我们看到大家越来越多得使用虚拟机(或云主机),物理机的使用场景被极大地压缩到了像数据库系统这样的特殊类型应用上面。
3621 0
|
Linux Docker 容器
centos7.3 docker升级
#升级操作系统,centos7直接升级到7.3 yum clean all yum update #升级内核 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.
2121 0
|
Java
《Java线程与并发编程实践》—— 1.3 练习
接下来的练习旨在测试你对第1章内容的掌握程度。
1779 0