面试20之创建含有某一深度上所有结点的链表。
2017-04-29 00:14
435 查看
题目描述
对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表。给定二叉树的根结点指针TreeNode* root,以及链表上结点的深度,请返回一个链表ListNode,代表该深度上所有结点的值,请按树上从左往右的顺序链接,保证深度不超过树的高度,树上结点的值为非负整数且不超过100000。
<方法1>:层次遍历
这个题目的意思就是输出二叉树的某一层的所有元素,这个首先想到的是层次遍历,层次遍历最简单的方法就是用队列实现,我们传统的层次遍历方法是可以输出所有元素,那么如何区分相邻两层之间的元素呢?
其实我们可以用两个整数变量curlevel,nextlevel来记录相邻两层的元素个数,其中curlevel代表出栈那一层留下的元素个数,nextlevel代表下一层进栈元素的个数,每当curlevel为0的时候,说明上一层已经全部出栈,下一层已经全部入栈,那么层次遍历层数就加一,这个时候将nextlevel的值复制给curlevel,nextlevel=0,当遍历到第dep层的时候,便把那一层的所有元素输出,停止遍历。
<方法2>:递归遍历
其实也可以用递归遍历实现,刚开始为深度为dep,每往下递归一层,则深度减一(dep=dep-1),当dep==1的时候,便输出那个元素,如果先递归左子树,那么则实现从左到右打印,如果先递归右子树,则实现从右往左打印。
树的节点和链表节点定义:
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x):val(x),left(NULL),right(NULL) { }
};
struct ListNode
{
int val;
struct ListNode *next;
ListNode(int x):val(x),next(NULL) { }
};
//第一种方法,非递归。
ListNode *GetTreeLevel(TreeNode *root,int dep) { if(root == NULL || dep <= 0) return NULL; int heigh = 1; queue<TreeNode*> q; q.push(root); int curlevel = 1; //表示当前要遍历层的节点个数。 int nextlevel = 0;//表示下一层节点个数。 while (!q.empty()) { if(heigh == dep) break; TreeNode *temp = q.front(); q.pop(); if(temp->left) { q.push(temp->left); nextlevel++; } if(temp->right) { q.push(temp->right); nextlevel++; } curlevel--; if(curlevel == 0) //表示这一层遍历完了。 { heigh++; //遍历下一层高度++ curlevel = nextlevel; nextlevel = 0; } } ListNode *phead = NULL; ListNode *Tail = NULL; while(!q.empty()) //此时队列中存放的是要求的这一层的节点。 { TreeNode *temp = q.front(); ListNode *Node = new ListNode(temp->val); q.pop(); if(phead == NULL) { phead = Node; Tail = Node; } else { Tail->next = Node; Tail = Node; } } return phead; }
//第二种方式,递归,但是链表要有一个头节点。
void Get(TreeNode *root,ListNode *&head,int dep) //注意这里要用引用。递归会回退,比如在树中找第二层的节点,在左子树找到了,head->next = left,head = left,
{ //但是递归退回到跟节点,找右子树,也找到,但是此时head还是头节点,而不是指向刚刚插入的左子树了。又重新插入节点。
if(root == NULL||dep <= 0)
return ;
if(dep == 1)
{
ListNode *Node = new ListNode(root->val);
head->next = Node;
head = Node;
return ;
}
Get(root->left,head,dep-1);
Get(root->right,head,dep-1);
}
ListNode *GetTreeLevel(TreeNode *root,int dep)
{
if(root == NULL || dep <= 0)
return NULL;
ListNode *pHead = new ListNode(-1); //头节点。
ListNode *list = pHead;
Get(root,pHead,dep);
return list->next;
}
测试代码:
void test()
{
TreeNode *p1 = new TreeNode(1);
TreeNode *p2 = new TreeNode(2);
TreeNode *p3 = new TreeNode(3);
TreeNode *p4 = new TreeNode(4);
TreeNode *p5 = new TreeNode(5);
TreeNode *p6 = new TreeNode(6);
TreeNode *p7 = new TreeNode(7);
TreeNode *p8 = new TreeNode(8);
TreeNode *p9 = new TreeNode(9);
TreeNode *p10 = new TreeNode(10);
p1->left = p2;
p1->right = p3;
p2->left = p4;
p2->right = p5;
p3->right = p6;
p4->left = p7;
p4->right = p8;
p5->right = p9;
p6->right = p10;
ListNode *phead = GetTreeLevel(p1, 4);
while(phead)
{
cout << phead->val << " ";
phead = phead->next;
}
}
int main()
{
test();
cout << "hello..."<<endl;
return 0;
}
相关文章推荐
- 【二叉树】创建含有某一深度上所有结点的链表
- 给定一棵二叉树,创建含有某一深度上所有结点的链表
- 给定一棵二叉树,设计一个算法,创建含有某一深度上所有结点的链表(比如:若一棵树的深度为D,则会创建出D个链表)
- 某一深度上所有结点的链表
- 程序员面试金典: 9.4树与图 4.4 在二叉树上创建包含某一深度上所有节点的链表
- 微软面试100题之一,之四 二叉查找树变双向链表 和为某一值的所有路径
- 二叉树创建、遍历(递归和非递归)、深度及求取二叉树中和为某一值的所有路径
- 头插法,尾插法,创建单链表,然后删除所有结点值为x的结点
- 用结构体实现链表的创建、遍历、结点插入、结点删除、链表删除-----带菜单选项
- C++写的带有头结点单链表创建,插入,删除,显示
- [java 面试100道]13.输入一个单向链表,输出该链表中倒数第k个结点。
- 设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点
- 用结构体实现链表的创建、遍历、结点插入、结点删除
- 微软面试之4 在二元树中找出和为某一值的所有路径(树)
- 学习笔记——C语言实现单链表的基本操作:创建、输出、插入结点、删除结点、逆序链表
- 单链表数据中含有数字字符、字母字符、其他字符三种 。 构造3个循环链 ,使得循环链只有一种字符 。但必须要使用原来单链的结点空间作为三个表的结点空间
- [google面试CTCI] 2-0.链表的创建
- 单链表中通过某一结点指针删除该结点
- Q4.4 每一层的所有结点构建为一个链表
- 微软等数据结构+算法面试100题(31)--在O(1)时间内删除链表结点