程序员面试金典: 9.4树与图 4.4 在二叉树上创建包含某一深度上所有节点的链表
2016-12-29 10:04
591 查看
#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; }
相关文章推荐
- 给定一棵二叉树,设计一个算法,创建含有某一深度上所有结点的链表(比如:若一棵树的深度为D,则会创建出D个链表)
- 给定一棵二叉树,创建含有某一深度上所有结点的链表
- 【二叉树】创建含有某一深度上所有结点的链表
- 面试20之创建含有某一深度上所有结点的链表。
- 二叉树创建、遍历(递归和非递归)、深度及求取二叉树中和为某一值的所有路径
- 某一深度上所有结点的链表
- --创建表函数查找某节点的所有子节点(包含自己)
- 删除两个双向链表中相同元素的所有节点
- 二叉树的创建、遍历、深度、叶子节点数
- hdu 3887 Counting Offspring 树上求所有节点的子树上比当前节点小的个数 树状数组
- PHP 将二叉查找树转换为双向链表,要求不能创建新节点,只能调节节点指针
- 2012年7月4日 题:创建一个 10节点 内容随机但不重复的 链表
- 给定一个单向链表,目前已经有一个指针,指向某一个节点(记作A),现在要删除这个节点A,如何操作。
- 创建一个包含15个随机整数(0~9)的列表,然后去掉其中的所有重复数字。
- 找出图中的所有连通子图(创建图的邻接表,深度优先遍历查找子图)
- 程序员面试100题(算法)之二叉树中找出和为某一值的所有路径(含二叉树前序创建、遍历)
- 一个经过改良的XMLHelper(包含了序列化,反序列化,创建xml文件,读取节点,C#对象与xml文件的相互转换等等。)
- 采用选择排序法对链表进行排序,注意交换操作中不是对链表里某一节点里的某一元素进行交换,而是对两节点指针的交换
- 小窍门:创建超长链表时加一个特殊头节点优化创建速度
- php获取某一目录包含的所有目录和文件