二叉树的完整操作
2017-05-07 13:45
411 查看
#include <iostream> using namespace std; #include <queue> #include <stack> #include <list> template<class T> struct BinaryTreeNode { BinaryTreeNode(const T& data) : _data(data) , _pLeft(NULL) , _pRight(NULL) {} T _data; BinaryTreeNode<T>* _pLeft; // 左孩子 BinaryTreeNode<T>* _pRight; // 右孩子 }; template<class T> class BinaryTree { typedef BinaryTreeNode<T> Node; public: BinaryTree() : _pRoot(NULL) {} //构造二叉树 BinaryTree(const T array[], size_t size, const T& invalid) { // 创建树 size_t index = 0; _CreateTree(_pRoot, array, size, index, invalid); } //拷贝二叉树 BinaryTree(const BinaryTree<T>& t) { _pRoot = _CopyBinaryTree(t._pRoot); } //二叉树的赋值函数 BinaryTree<T>& operator=(const BinaryTree<T>& t) { if(this != NULL) { _DestroyTree(_pRoot); _pRoot = _CopyBinaryTree(t._pRoot); return *this; } } // 递归前序遍历:访问根结点-->左子树-->右子树 void PreOrder() { cout<<"递归前序遍历:"; _PreOrder(_pRoot); cout<<endl<<endl; } // 非递归前序遍历:访问根结点-->左子树-->右子树 void PreOrder_Nor() { cout<<"非递归前序遍历:"; if(_pRoot == NULL)//空树 return; stack<Node*> s; s.push(_pRoot); //根节点入栈 while(!s.empty()) { Node* pCur = s.top(); //取当前节点 cout<<pCur->_data<<" "; //访问当前节点 s.pop(); //出栈 if(pCur->_pRight) s.push(pCur->_pRight); //右子树先入栈 if(pCur->_pLeft) s.push(pCur->_pLeft); //左子树再入栈 } cout<<endl<<endl; } // 递归中序遍历:访问左子树-->根结点-->右子树 void InOrder() { cout<<"中序遍历:"; _InOrder(_pRoot); cout<<endl<<endl; } // 非递归中序遍历:访问左子树-->根结点-->右子树 void InOrder_Nor() { cout<<"非递归中序遍历:"; if(_pRoot == NULL) return; //空树 Node* pCur = _pRoot; stack<Node*> s; while(!s.empty() || pCur) { //找最左边节点,并保存该路径上的所有节点 while(pCur) { s.push(pCur); pCur = pCur->_pLeft; } pCur = s.top(); //取栈顶 cout<<pCur->_data<<" "; //访问 s.pop(); //出栈 pCur = pCur->_pRight; } cout<<endl<<endl; } // 后序遍历:访问左子树-->右子树-->根节点 void PostOrder() { cout<<"后序遍历:"; _PostOrder(_pRoot); cout<<endl<<endl; } // 后续遍历的非递归版本:访问左子树-->右子树-->根节点 void PostOrder_Nor() { cout<<"非递归中序遍历:"; if(_pRoot == NULL) return; Node* pCur = _pRoot; Node* prev = NULL; stack<Node*> s; while(!s.empty() || pCur) { //找最左边节点并保存路径上所有节点 while(pCur) { s.push(pCur); pCur = pCur->_pLeft; } pCur = s.top(); //取栈顶 if(pCur->_pRight == NULL || prev == pCur->_pRight) { cout<<pCur->_data<<" "; //访问 prev = pCur; //标记 s.pop(); pCur = NULL; } else { pCur = pCur->_pRight; } } cout<<endl<<endl; } // 层序遍历 void LevelOrder() { cout<<"层序遍历:"; _LevelOrder(_pRoot); cout<<endl<<endl; } ~BinaryTree() { _DestroyTree(_pRoot); _pRoot = NULL; } //找到节点的双亲节点 Node* GetParent(Node* x) { return _GetParent(_pRoot,x); } //找到结点的左孩子 Node* GetLeftChild(Node* pCur) { return pCur->_pLeft; } //找到结点的右孩子 Node* GetRightChild(Node* pCur) { return pCur->_pRight; } //在二叉树中查找某个节点 Node* Find(const T& value) { return _Find(_pRoot, value); } //二叉树的高度 size_t Height() { return _Height(_pRoot); } //叶子结点的个数 size_t GetLeefNode() { return _GetLeefNode(_pRoot); } //第K层有几个节点 size_t GetKLevelNode(size_t k) { return _GetKLevelNode(_pRoot, k); } // 求二叉树的镜像:非递归 void GetBinaryMirror_Nor() { queue<Node *> q; Node *pointer = _pRoot;//当前处理的节点为根节点 while (pointer) { swap(pointer->_pLeft, pointer->_pRight);//交换当前处理节点的孩子 if (pointer->_pLeft)//左孩子不为空 q.push(pointer->_pLeft); if (pointer->_pRight)//右孩子不为空 q.push(pointer->_pRight); if (!q.empty()) { pointer = q.front(); q.pop(); } else { break; } } } // 求二叉树的镜像:递归版本 void GetBinaryMirror() { return _GetBinaryMirror(_pRoot); } // 利用层序遍历来处理--> 关键:找第一个度不为2的结点-->后续结点 // 如果有孩子则不是完全二叉树 // 否则:是 bool IsCompleteBinaryTree() { if(_pRoot == NULL) return true; Node* pCur = NULL; queue<Node*> q; q.push(_pRoot); int flag = false; while(!q.empty()) { pCur = q.front(); q.pop(); if(flag == true) { if(pCur->_pLeft != NULL || pCur->_pRight != NULL) return false; return true; } else { if(pCur->_pLeft != NULL && pCur->_pRight != NULL) { q.push(pCur->_pLeft); q.push(pCur->_pRight); } else if(pCur->_pRight!= NULL) { return false; } else if(pCur->_pLeft != NULL) { q.push(pCur->_pLeft); flag = true; } else { flag = true; } } } return false; } // 求二叉树中两个节点的最近公共祖先节点 Node* GetLastCommonParent(Node* Node1, Node* Node2) { return _GetLastCommonParent(_pRoot, Node1, Node2); } // 由前序遍历序列和中序遍历序列重建二叉树 Node* RebuildBinaryTree(char* PreOrder, char* InOrder, int length) { //int len1 = sizeof(PreOrder/PreOrder[0]); //int len2 = sizeof(InOrder/InOrder[0]); //if(len1 != len2) //return NULL; if(PreOrder == NULL || InOrder == NULL || length < 0) return NULL; // 前序遍历的第一个数据就是根节点数据 Node* _pRoot = new BinaryTreeNode<char>(PreOrder[0]); // 查找根节点在中序遍历中的位置,中序遍历中,根节点左边为左子树,右边为右子树 int rootPositionInOrder = -1; for(int i = 0; i < length; i++) { if(InOrder[i] == _pRoot->_data) { rootPositionInOrder = i; break; } } // 重建左子树 int nodeNumLeft = rootPositionInOrder; char* pPreOrderLeft = PreOrder + 1; char* pInOrderLeft = InOrder + nodeNumLeft; _pRoot->_pLeft = RebuildBinaryTree(pPreOrderLeft, pInOrderLeft, nodeNumLeft); // 重建右子树 int nodeNumRight = length - nodeNumLeft - 1; char* pPreOrderRight = PreOrder + 1 + nodeNumLeft; char* pInOrderRight = InOrder + nodeNumLeft + 1; _pRoot->_pRight = RebuildBinaryTree(pPreOrderRight, pInOrderRight, nodeNumRight); return _pRoot; } private: void _CreateTree(Node*& pRoot, const T array[], size_t size, size_t& index, const T& invalid) { if(index < size && (array[index] != invalid))//两个顺序不可调换,否则会导致越界访问 { //创建根节点 pRoot = new Node(array[index]); //创建根结点左子树 _CreateTree(pRoot->_pLeft, array, size, ++index, invalid); //创建根结点左子树 _CreateTree(pRoot->_pRight, array, size, ++index, invalid); } } Node* _CopyBinaryTree(Node* pRoot) { if(pRoot) { Node* pNewNode = new Node(pRoot->_data); pNewNode->_pLeft = _CopyBinaryTree(pRoot->_pLeft); pNewNode->_pRight = _CopyBinaryTree(pRoot->_pRight); return pNewNode; } return NULL; } void _DestroyTree(Node* &pRoot) { if(pRoot) { _DestroyTree(pRoot->_pLeft); _DestroyTree(pRoot->_pRight); delete pRoot; pRoot = NULL; } } void _PreOrder(Node* pRoot) { if(pRoot) { cout<<pRoot->_data<<" "; _PreOrder(pRoot->_pLeft); _PreOrder(pRoot->_pRight); } } void _InOrder(Node* pRoot) { if(pRoot) { _InOrder(pRoot->_pLeft); cout<<pRoot->_data<<" "; _InOrder(pRoot->_pRight); } } void _PostOrder(Node* pRoot) { if(pRoot) { _PostOrder(pRoot->_pLeft); _PostOrder(pRoot->_pRight); cout<<pRoot->_data<<" "; } } void _LevelOrder(Node* pRoot) { if(pRoot == NULL) return; queue<Node*> q; q.push(pRoot); Node* pCur = NULL; while(!q.empty()) { pCur = q.front(); cout<<pCur->_data<<" "; if(pCur->_pLeft) q.push(pCur->_pLeft); if(pCur->_pRight) q.push(pCur->_pRight); q.pop(); } } Node* _GetParent(Node* pRoot, Node* x) { if(pRoot == NULL || x == NULL || x == pRoot) return NULL; if(pRoot->_pLeft == x || pRoot->_pRight == x) return pRoot; Node* parent = NULL; if(parent = _GetParent(pRoot->_pLeft, x)) return parent; if(parent = _GetParent(pRoot->_pRight, x)) return parent; return NULL; } Node* _Find(Node* pRoot, const T& value) { if(pRoot == NULL) //空树 return NULL; if(pRoot->_data == value) return pRoot; Node* pCur = NULL;//如果不用返回值接收需要再调用一次函数 if(pCur = _Find(pRoot->_pLeft, value)) return pCur; if(pCur = _Find(pRoot->_pRight, value)) return pCur; } size_t _Height(Node* pRoot) { if(pRoot == NULL) //空树 return 0; if(pRoot->_pLeft == NULL || pRoot->_pRight == NULL) return 1; //只有一个根节点的树 size_t lefthHight = _Height(pRoot->_pLeft); size_t rightHeight = _Height(pRoot->_pRight); return (lefthHight>rightHeight) ? (lefthHight+1) : (rightHeight+1); } size_t _GetLeefNode(Node* pRoot) { if(pRoot == NULL) //空树 return 0; if(pRoot->_pLeft == NULL && pRoot->_pRight == NULL) return 1; //只有一个根节点的树 return _GetLeefNode(pRoot->_pLeft) + _GetLeefNode(pRoot->_pRight); } size_t _GetKLevelNode(Node* pRoot, size_t k) { if(pRoot == NULL || k<1 || k>_Height(pRoot)) return 0; if(k == 1) return 1; size_t left = _GetKLevelNode(pRoot->_pLeft, k-1); size_t right = _GetKLevelNode(pRoot->_pRight, k-1); return left + right; } void _GetBinaryMirror(Node* pRoot) { if(pRoot == NULL) return ; if(pRoot->_pLeft == NULL && pRoot->_pRight == NULL) return ; swap(pRoot->_pLeft, pRoot->_pRight); if(pRoot->_pLeft) _GetBinaryMirror(pRoot->_pLeft); if(pRoot->_pRight) _GetBinaryMirror(pRoot->_pRight); } bool GetNodePath(Node* pRoot, Node* pNode, list<Node*>& path) { if(pRoot == pNode) { path.push_back(pRoot); return true; } if(pRoot == NULL) return false; path.push_back(pRoot); bool found = false; found = GetNodePath(pRoot->_pLeft, pNode, path); //在左子树中寻找 if(!found) //在左子树中没有找到,在右子树中寻找 found = GetNodePath(pRoot->_pRight, pNode, path); if(!found) //没有找到该节点 path.pop_back(); return found; } Node* _GetLastCommonParent(Node* pRoot, Node* Node1, Node* Node2) { if(pRoot == NULL || Node1 == NULL || Node2 == NULL) return NULL; list<Node*> l1; bool Result1 = GetNodePath(pRoot, Node1, l1); list<Node*> l2; bool Result2 = GetNodePath(pRoot, Node2, l2); if(!Result1 || !Result2) return NULL; Node * pLast = NULL; list<Node*>::const_iterator iter1 = l1.begin(); list<Node*>::const_iterator iter2 = l2.begin(); while(iter1 != l1.end() && iter2 != l2.end()) { if(*iter1 == *iter2) pLast = *iter1; else break; iter1++; iter2++; } return pLast; } private: BinaryTreeNode<T>* _pRoot; }; void FunTest() { char array[] = "124##5##36##7##"; BinaryTree<char> tree(array, strlen(array), '#'); BinaryTree<char> t(tree); BinaryTree<char> t1; t1 = t; BinaryTreeNode<char>* pCur = NULL; pCur = t.GetParent(t.Find('1')); //找到节点的双亲节点 if(pCur) cout<<"结点1的双亲结点为:"<<pCur->_data<<endl; pCur = t.GetParent(t.Find('2')); if(pCur) cout<<"结点2的双亲结点为:"<<pCur->_data<<endl; pCur = t.GetParent(t.Find('5')); if(pCur) cout<<"结点5的双亲结点为:"<<pCur->_data<<endl; pCur = t.GetLeftChild(t.Find('1')); //找到结点的左孩子 if(pCur) cout<<"结点1的左孩子为:"<<pCur->_data<<endl; pCur = t.GetLeftChild(t.Find('3')); if(pCur) cout<<"结点2的左孩子为:"<<pCur->_data<<endl; pCur = t.GetLeftChild(t.Find('6')); if(pCur) cout<<"结点6的左孩子为:"<<pCur->_data<<endl; pCur = t.GetRightChild(t.Find('1')); //找到结点的右孩子 if(pCur) cout<<"结点1的右孩子为:"<<pCur->_data<<endl; pCur = t.GetRightChild(t.Find('2')); if(pCur) cout<<"结点2的右孩子为:"<<pCur->_data<<endl; pCur = t.GetRightChild(t.Find('5')); if(pCur) cout<<"结点5的右孩子为:"<<pCur->_data<<endl; cout<<"二叉树的高度:"<<t.Height()<<endl; cout<<"二叉树的叶子节点:"<<t.GetLeefNode()<<endl; cout<<"二叉树第三层的节点数:"<<t.GetKLevelNode(3)<<endl; cout<<"二叉树第二层的节点数:"<<t.GetKLevelNode(2)<<endl; cout<<"二叉树第一层的节点数:"<<t.GetKLevelNode(1)<<endl; cout<<"二叉树第四层的节点数:"<<t.GetKLevelNode(4)<<endl; tree.PreOrder(); t.PreOrder_Nor(); tree.InOrder(); t.InOrder_Nor(); tree.PostOrder(); tree.PostOrder_Nor(); tree.LevelOrder(); tree.GetBinaryMirror_Nor(); tree.GetBinaryMirror(); cout<<"二叉树是不是完全二叉树:"<<t.IsCompleteBinaryTree()<<endl; pCur = tree.GetLastCommonParent(tree.Find('2'), tree.Find('6')); if(pCur) cout<<"结点2和5的公共祖先是"<<pCur->_data<<endl; char str1[] = {'1', '2', '4', '5', '3', '6', '7'}; char str2[] = {'4', '2', '5', '1', '6', '3', '7'}; tree.RebuildBinaryTree(str1, str2, 7); } int main() { FunTest(); system("pause"); return 0; }
相关文章推荐
- 二叉树面试题及操作【完整代码】
- 多普达515的硬重启--完整操作说明
- 二叉树的建立及相关操作
- 多数据之间的连接操作-MSSQL(不完整)
- 链表倒转等操作完整程序
- 链表队列与二叉树基本操作
- 二叉树的基本操作
- 多数据之间的连接操作-集中几个.NET常用的方法(不完整)
- 关于二叉树操作的11个算法
- 数据结构类型定义及基本操作汇总(二)-- 二叉树及其遍历
- ASP操作XML文件的完整实例
- 二叉树的操作
- 多数据之间的连接操作-ODBC(不完整)
- 多数据之间的连接操作-MSSQL(不完整)
- 用string实现的一个完整的类,包含以下操作:重载运算符 > >,< < ,string模板类,fstream对二进制数据读写
- [原创] 多选框动态添加,移动,删除,全选 等操作(完整实例)
- Asp学习者完整攻略之三:操作SQL:SQL基础:
- OLEDB方式操作规则EXCEL的字符串的完整写法(解决标题行和列数据类型不一致的问题)
- 多数据之间的连接操作-集中几个.NET常用的方法(不完整)
- 二叉树基本操作的程序实现