程序员面试金典: 9.4树与图 4.4 在二叉树上创建包含某一深度上所有节点的链表

#include <iostream>
#include <stdio.h>
#include <string>
#include <queue>
#include <vector>

using namespace std;

/*
问题:给定一颗二叉树,设计一个算法,创建含有某一深度上所有节点的链表(比如,若一棵树的深度为D,
则会创建出D个链表)。
分析:题目的意思应该是深度为1的所有节点构成一个链表,深度为2的所有节点构成一个链表,....,也就是把
      相同深度的节点放在同一个链表中。
	  那么肯定要遍历,我们知道层次遍历最好的方式应该是用广度优先。可以事先创建D个链表,
	  每当遍历到一个节点,获取该节点深度,将该节点放入到对应深度的链表中,结点插入链表的方式可以采用
	  尾插法。
	  当所有结点遍历结束,此时D个链表也已经建立好。
	  而树的深度D,可以通过一个递归实现。

输入:
6(树中结点个数n)
1 2 3 4 5 6(树中结点的值,接下来有n行,每i行第一个字符:'d'表示第i个结点有两个孩子,随后给出两个孩子节点编号,
'l'表示第i个结点只有左孩子,然后给出左孩子结点编号;'r'表示第i个结点只有右孩子,给出右孩子节点编号,'z'表示第i个结点没有孩子结点)
d 2 3
d 4 5
r 6
z
z
z
输出:
depth 1: 1 ,depth 2: 2 3, depth 3: 4 5 6
*/
const int MAXSIZE = 10000;

typedef struct TreeNode
{
	int _value;
	TreeNode* _pLeft;
	TreeNode* _pRight;
	bool _isVisited;
	int _height;
	//TreeNode* _pParent;
}TreeNode;
int g_index;
TreeNode g_treeNodeArray[MAXSIZE];

typedef struct Node
{
	Node* _pNext;
	int _value;
}Node;

TreeNode* createTreeNode()
{
	++g_index;
	g_treeNodeArray[g_index]._pLeft = g_treeNodeArray[g_index]._pRight = NULL; 
	g_treeNodeArray[g_index]._isVisited = false;
	return &g_treeNodeArray[g_index];
}

vector< Node* > visitTreeBFS(TreeNode* head)
{
	vector<Node*> vecNode;
	if(NULL == head)
	{
		return vecNode;
	}
	queue<TreeNode*> queueTree;
	head->_height = 0;//设置根结点的高度为1
	queueTree.push(head);
	vector<Node*> tailNodeVector; //用于存放对应链表的尾结点
	while(!queueTree.empty())
	{
		TreeNode* treeNode = queueTree.front();
		queueTree.pop();
		int height = treeNode->_height;

		//将当前节点加入到与其深度相统一的链表中,说明深度为height对应的链表还没有建立
		if(vecNode.empty() || height == vecNode.size() )
		{
			//建立链表,尾插法,创建尾结点,创建一个新节点,令尾结点为新结点;后续再插结点时,令尾结点指向新结点,再令尾结点为新结点
			Node* pNode = new Node();
			pNode->_value = treeNode->_value;
			pNode->_pNext = NULL;
			vecNode.push_back(pNode);
			tailNodeVector.push_back(pNode);
		}
		else
		{
			Node* pNode = new Node();
			pNode->_value = treeNode->_value;
			pNode->_pNext = NULL;
			Node* tailNode = tailNodeVector.at(height);
			tailNode->_pNext = pNode;
			tailNode = pNode;
			tailNodeVector.at(height) = tailNode; //更新尾结点
		}

		//左子树非空且未访问过,则压入左子树
		if(treeNode->_pLeft && treeNode->_pLeft->_isVisited == false)
		{
			treeNode->_pLeft->_isVisited = true;
			treeNode->_pLeft->_height = height + 1;
			queueTree.push(treeNode->_pLeft);
		}
		if(treeNode->_pRight && treeNode->_pRight->_isVisited == false)
		{
			treeNode->_pRight->_isVisited = true;
			treeNode->_pRight->_height = height + 1;
			queueTree.push(treeNode->_pRight);
		}
	}

	return vecNode;
}

void printResult(vector<Node*>& vecNode)
{
	if(vecNode.empty())
	{
		cout << "List is null!" << endl;
	}
	int size = vecNode.size();
	for(int i = 0 ; i < size ; i++)
	{
		cout << "depth " << (i+1) << ":";
		Node* node = vecNode.at(i);
		while(node)
		{
			cout << node->_value << " ";
			node = node->_pNext;
		}
		cout << ",";
	}
	cout << endl;
}

void releaseList(vector<Node*>& vecNode)
{
	if(vecNode.empty())
	{
		return;
	}
	int size = vecNode.size();
	for(int i = 0 ; i < size ; i++)
	{
		Node* node = vecNode.at(i);
		//删除节点
		while(node)
		{
			Node* tempNode = node;
			node = node->_pNext;
			delete tempNode;
		}
	}
}

void input()
{
	int nodeNum;
	int nodeValue;
	string childNumFlag;
	int leftChild;
	int rightChild;
	while(cin >> nodeNum)
	{
		g_index = 0;
		for(int i = 0 ; i < nodeNum ; i++)
		{
			TreeNode* treeNode = createTreeNode();
			cin >> treeNode->_value;
		}

		//接下来创建结点指向
		for(int i = 1 ; i <= nodeNum ; i++)
		{
			cin >> childNumFlag;
			if("d" == childNumFlag)
			{
				cin >> leftChild >> rightChild;
				g_treeNodeArray[i]._pLeft = &g_treeNodeArray[leftChild];
				g_treeNodeArray[i]._pRight = &g_treeNodeArray[rightChild];
			}
			else if("r" == childNumFlag)
			{
				cin >> rightChild;
				g_treeNodeArray[i]._pRight = &g_treeNodeArray[rightChild];
			}
			else if("l" == childNumFlag)
			{
				cin >> leftChild;
				g_treeNodeArray[i]._pLeft = &g_treeNodeArray[leftChild];
			}
		}

		//下面就是遍历树,创建链表
		vector< Node* > vecNode = visitTreeBFS(&g_treeNodeArray[1]);

		//遍历后打印结果
		printResult(vecNode);
		releaseList(vecNode);
	}
}

int main(int argc , char* argv[])
{
	input();
	getchar();
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值