当前位置:网站首页>扁平数组转树结构实现方式
扁平数组转树结构实现方式
2022-08-01 07:39:00 【nwao7890】
背景
今天遇到一个题,需要将扁平数组转树结构,题目大致如下
将扁平数组转为树结构输出 pid0为根节点,id顺序可能不递增,pid可能不存在于数组内
给定输入
[
{id: 1, name: '111', pid: 0},
{id: 2, name: '222', pid: 1},
{id: 3, name: '333', pid: 1},
{id: 4, name: '444', pid: 3},
{id: 5, name: '555', pid: 4},
]
给定输出:
{
"id": 1,
"name": "111",
"pid": 0,
"children": [
{
"id": 2,
"name": "222",
"pid": 1,
"children": []
},
{
"id": 3,
"name": "333",
"pid": 1,
"children": [
// ...
]
}
]
}
思考
这个题当时用c++没有做出来,一看这个输出就是json格式,应该就是个前端的题,后来一搜果然。
不过用c++肯定也能写就是构造个树,递归去查找比较插入唄。额外支持一下要求的特例。后来还是用c++写了一下最后输出格式没弄。算法可能不是最优,先实现了吧。
写完也没明白用这个前端题来考什么,估计是应变能力吧,还是得加强算法练习,才能遇题不慌不乱。
上代码
由于题目要求,这里可能会存在多棵树(pid不在树内的情况)。
考虑到插入树时,若id不是顺序的,则会产生临时的N棵树,后续还要合并这些树,比较麻烦,就先排一下序,这样除非不在当前树内的,否则都能找到对应节点插入。
这里我们使用了preorder先序遍历的算法,在遍历时,判断pid 和id有无和待插入的元素有关系的,找到了就挂在树上。
有个特殊的情况是待插入元素会成为当前树的根,这里需要处理一下
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
// 节点定义
class onenode
{
public:
int id;
int pid;
std::vector<onenode*> childs;
onenode(int idt, int pidt)
{
id = idt,
pid = pidt;
}
~onenode(){
};
};
// 遍历找位置插入树
onenode* preorder(onenode* node, onenode*tmpnode)
{
if (node == nullptr)
return nullptr;
if (node->id == tmpnode->pid)
{
node->childs.push_back(tmpnode);
return node;
}
if (node->pid == tmpnode->id)
{
tmpnode->childs.push_back(node);
return tmpnode;
}
for (auto it = node->childs.begin(); it != node->childs.end(); it++)
{
onenode* tmpnode1 = preorder(*it, tmpnode);
if (tmpnode1 != nullptr)
return tmpnode1;
}
return nullptr;
}
int tryaddtotree(onenode* tmproot, onenode* cur, std::map<int, onenode*>& nodetree)
{
onenode* tmpptr = preorder(tmproot, cur);
if (tmpptr != nullptr)
{
if (tmpptr == cur)
{
for (auto it = tmpptr->childs.begin(); it != tmpptr->childs.end(); it++)
{
if ((*it)== tmproot)
{
return 1;// 新节点是root了 需要换root
}
}
}
return 2;// 树里的一个子节点
}
else
{
//没加进去需要新增树了
return 3;
}
}
int preprint(onenode* root)
{
if (root == nullptr)
return 0;
printf("id: %d, pid %d\n", root->id, root->pid);
for (auto it = root->childs.begin(); it != root->childs.end(); it++)
{
preprint(*it);
}
return 0;
}
int main()
{
std::map<int, onenode*> nodetree;
//std::vector<onenode> srcdata = {
{1,0},{2,1},{3,1},{4,3},{5,4},{6, 99}};
std::vector<onenode> srcdata = {
{
1,0},{
4,3},{
5,4},{
2,1},{
3,1},{
6, 99}};
for (auto it = srcdata.begin(); it != srcdata.end(); it++)
{
printf("%d %d\n", (*it).id, (*it).pid);
}
//for (auto it : srcdata)
//{ printf("%d %d\n", it.id, it.pid);}
sort(srcdata.begin(), srcdata.end(),[](onenode a, onenode b){
return a.id < b.id;
});
for (auto it = srcdata.begin(); it != srcdata.end(); it++)
{
onenode* willaddnode = &(*it);
if (nodetree.empty())
{
nodetree.emplace(std::make_pair(willaddnode->id, willaddnode));
continue;
}
bool added = false;
for (auto itm = nodetree.begin(); itm != nodetree.end(); itm++)
{
onenode* tmproot = itm->second;
int addret = tryaddtotree(tmproot, willaddnode, nodetree);
if (addret == 1)
{
nodetree.emplace(std::make_pair(willaddnode->id, willaddnode));
nodetree.erase(tmproot->id);
added = true;
}
else if (addret == 2)
{
added = true;
}
if (added)
break;
}
if (!added)
{
nodetree.emplace(std::make_pair(willaddnode->id, willaddnode));
}
}
for (auto itm = nodetree.begin(); itm != nodetree.end(); itm++)
{
printf("*****\n");
preprint(itm->second);
}
return 0;
}
总结
虽然是个前端题不过是涉及到树的遍历,用c++还是可以写的,平时还是需要多练习
还有就是这个总是提示大于10字的不足10行?
边栏推荐
- Upgrade to heavyweight lock, lock reentrancy will lead to lock release?
- 根据指定区域内容生成图片并进行分享总结
- mysql查看cpu使用情况
- 请问用flinksql写入数据到clickhouse需要引入什么依赖吗?
- Golang: go to connect and use mysql
- 云原生FAQ
- special day to remember
- Gethostbyname \ getaddrinfo DNS domain name IP address is not safe
- pytest接口自动化测试框架 | 使用函数返回值的形式传入参数值
- 插入排序—直接插入排序和希尔排序
猜你喜欢
随机推荐
22牛客多校1 C.Grab the Seat (几何 + 暴力)
图片无损压缩软件哪个好用:试试完全免费的JPG-C 图片批量修整压缩减肥工具吧 | 最新jpg批量修整工具下载
Go 支持 OOP: 用 struct 代替 class
13 - JUC CountDownLatch concurrent programming
The socket option
pytest interface automation testing framework | single/multiple parameters
Vim简介
第02章 MySQL的数据目录【1.MySQL架构篇】【MySQL高级】
Chapters 6 and 7 of Huawei Deep Learning Course
Flink SQL - client, how to deal with the source side and to increase the target, the SQL - client including mapping table and the JOB such as
Chapter 9 of Huawei Deep Learning Course - Convolutional Neural Network and Case Practice
2022杭电中超杯(1)个人题解
华为深度学习课程第六、七章
Golang: go get url and form attribute value
What do the values 1, 2, and 3 in nodetype mean?
Electromagnetic compatibility introductory tutorial (6) test project
22牛客多校1 J.Serval and Essay (启发式合并)
巧妙利用unbuffer实时写入
Golang:go静态文件处理
POJ1287联网题解