面试20之创建含有某一深度上所有结点的链表。

题目描述

对于一棵二叉树,请设计一个算法,创建含有某一深度上所有结点的链表。

给定二叉树的根结点指针TreeNode* root,以及链表上结点的深度,请返回一个链表ListNode,代表该深度上所有结点的值,请按树上从左往右的顺序链接,保证深度不超过树的高度,树上结点的值为非负整数且不超过100000。



<方法1>:层次遍历

     这个题目的意思就是输出二叉树的某一层的所有元素,这个首先想到的是层次遍历,层次遍历最简单的方法就是用队列实现,我们传统的层次遍历方法是可以输出所有元素,那么如何区分相邻两层之间的元素呢?

     其实我们可以用两个整数变量curlevel,nextlevel来记录相邻两层的元素个数,其中curlevel代表出栈那一层留下的元素个数,nextlevel代表下一层进栈元素的个数,每当curlevel为0的时候,说明上一层已经全部出栈,下一层已经全部入栈,那么层次遍历层数就加一,这个时候将nextlevel的值复制给curlevelnextlevel=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;
}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值