二叉树基本操作汇总练习
来源:互联网 发布:c语言读入txt文本文件 编辑:程序博客网 时间:2024/06/05 18:16
#include<iostream>#include<queue>#include<assert.h>using namespace std;//二叉树的构建、销毁、赋值,拷贝构造。、遍历、修改、查找、template<typename T>struct BinaryTreeNode{ BinaryTreeNode<T>(const T&data=T()) : _data(data) , _pLeft(NULL) , _pRight(NULL) {} T _data; BinaryTreeNode<T>* _pLeft; BinaryTreeNode<T>*_pRight;};template<typename T>class BinaryTree{ typedef BinaryTreeNode<T> Node;public: BinaryTree() :_pRoot(NULL) , _invalid(T()) { } BinaryTree(const T arr[], const size_t length,const T& invalid) { size_t index = 0; _pRoot = _CreateTree(_pRoot, arr, length, index,invalid); } //前序遍历 void PreOrder() { _PreOrder(_pRoot); } void InOrder() { _InOrder(_pRoot); } void MidOrder() { _MidOrder(_pRoot); } //查找两节点的最近公共祖先 void ComParent(Node* node1, Node* node2) { //算法思路:1.判断两个节点的在根节点的左、右位置。 //2,递归下去进行查找 if (_pRoot == NULL || node1 == NULL || node2 == NULL) { return NULL; } bool left1 = Find(node1->_data); bool left2 = Find(node2->_data); if () { } } //Node* GetLastCommonAncestor(Node* root, Node* node1, Node* node2) //{ // if (root == NULL || node1 == NULL || node2 == NULL) // { // return NULL; // } // if (node1 == root || node2 == root)//前序遍历框架 // { // return root; // } // Node* left_lca = GetLastCommonAncestor(root->_pLeft,node1,node2); // Node* right_lca = GetLastCommonAncestor(root->_pRight, node1, node2); // if (left_lca&&right_lca) // { // return root; // } // else if (left_lca==NULL) // { // return right_lca; // } // else // { // return left_lca; // } //} //递归进行查找 Node* GetLastCommonAncestor(Node* root, Node* node1, Node* node2) { if (root == NULL || node1 == NULL || node2 == NULL) { return NULL; } if (root == node1 || root == node2) { return root; } Node* left_lca = GetLastCommonAncestor(root->_pLeft,node1,node2); Node* cur = NULL; if (left_lca) { //判断是否为父子关系 cur = GetLastCommonAncestor(left_lca->_pLeft, node1, node2); if (cur == NULL) { cur = GetLastCommonAncestor(left_lca->_pRight,node1,node2); } if ((cur == node1) && (left_lca == node2) || (cur == node2) && (left_lca == node1)) return root; } Node* right_lca = GetLastCommonAncestor(root->_pRight,node1,node2); if (right_lca) { //判断受否具有祖孙关系 cur = GetLastCommonAncestor(right_lca->_pLeft, node1, node2); if (cur == NULL) { cur = GetLastCommonAncestor(right_lca->_pRight, node1, node2); } if ((cur == node1) && (right_lca == node2) || (cur == node2) && (right_lca == node1)) return root; } if (left_lca&&right_lca)//一个在root的左结点,一个在root的右节点,则返回root { return root; } else if (left_lca) { return left_lca; } else { return right_lca; } } //根据前序和中序构建一颗二叉树 BinaryTree( T pre[], size_t n1, T mid[], size_t n2) { if (n1 != n2) { _pRoot= NULL; } else { _pRoot = CreatTreeFromPriAndMid(pre, mid, n2); } } Node* CreatTreeFromPriAndMid(T pre[], T mid[], size_t n) { //根据前序遍历特点,在中序中进行划分区间,来创建二叉树 if (n < 1) { return NULL; } Node* root = new Node(pre[0]); size_t i = 0; for (; i < n&&mid[i] != pre[0]; ++i)//左闭右开 { } size_t left = i;//开区间 size_t right = n- i - 1;//闭区间 if (left>0) { root->_pLeft = CreatTreeFromPriAndMid(&pre[1], mid, left);//其根节点已经创建好了 } if (right > 0) { root->_pRight = CreatTreeFromPriAndMid(&pre[left+1], &mid[left+1], right); } return root; } void LevelOrder() { //层序遍历 //利用队列实现因为需要先入的先访问,如果按照栈的特点来做,访问左孩子后,为了方便访问下一层,需要保存它的左右孩子,无法访问按层序访问右孩子,因为已经插上来了 //所以我们使用队列,就可以满足这一点 //只需要一个循环就能实现 if (_pRoot != NULL) { queue<Node*>q; q.push(_pRoot); while (!q.empty()) { Node*cur = q.front(); q.pop(); cout << cur->_data<<" "; if (cur->_pLeft) { q.push(cur->_pLeft); } if (cur->_pRight) { q.push(cur->_pRight); } } } } //拷贝构造函数 BinaryTree(const BinaryTree<T>& Bt) { //根据指针拷贝对象 _pRoot = _Copy(Bt._pRoot); } //赋值函数 BinaryTree<T>* operator =(BinaryTree<T>Bt) { //基本框架一样 或者采用新赋值方法,交换两者的空间。然后函数结束,销毁临时对象 if (_pRoot != &Bt._pRoot) { //拷贝 BinaryTree<T> temp(Bt); Destory(_pRoot); //释放新空间 _pRoot = temp._pRoot; } return *this; } //查找 Node* Find(const T& t) { return _Find(_pRoot, t); } //找出该节点的父亲结点 //思路: //求叶子节点的个数 Node* Parent(Node* cTest) { return _Parent(_pRoot,cTest); } Node* _Parent(Node* root ,Node * cTest) { if (root == NULL) { return NULL; } if (root->_pLeft == NULL&&root->_pRight == NULL) { return NULL; } if (root->_pLeft == cTest||root->_pRight==cTest) { return root; } Node* parent= _Parent(root->_pLeft, cTest); if (parent) { return parent; } return _Parent(root->_pRight,cTest); } //求一个节点的父亲结点—方法二 //利用层序遍历(这一次我们自己实现一个队列)的思路如果结点等于其左子树或者右子树,将其返回 Node* ParentNode(Node * node) { if (node == NULL || _pRoot == node) { return NULL; } int max = 50; int front, rear; Node* current, *child; int count = 0; if (node != NULL) { Node queue[max]; front = rear = 0; queue[rear++] = node; count++; while (count != 0) { current = queue[front]; if (current->_pLeft) { child = current->_pLeft; if (node == child) { return current; } else { //入队 queue[rear] = child; rear = (rear + 1)%max;//循环队列实现方式 count++; } } if (current->_pRight) { child = current->_pRight; if (child == node) { return current; } else { queue[rear] = child; rear = (rear + 1) % max; count++; } } front = (front + 1) % max; count--; } } return NULL; } //求数的高度 size_t Height() { return _Height(_pRoot); } //节点个数 size_t size() { size_t count = 0; _size(_pRoot,count); return count; } //叶子节点个数 size_t leaf() { size_t count = 0; _leaf(_pRoot,count); return count; } ~BinaryTree() { //销毁函数 DestoryTree(_pRoot); _pRoot = NULL; } /******************************************************/ // 二叉树的非递归操作 /******************************************************/ void InOrderNoR() { _InOrderNoR(_pRoot); } //获取父亲结点 Node* GetParent(Node* pRoot,Node* pNode) { if (_pRoot == NULL || pNode == NULL)return NULL; if (_pRoot == pNode)return NULL; if (pRoot->_pLeft == pNode || pRoot->_pRight == NULL) { return pRoot; } GetParent(pRoot->_pLeft,pNode); GetParent(pRoot->_pRight,pNode); return NULL; } //获取树的高度 size_t Height(Node* pRoot) { if (pRoot == NULL) return 0; size_t left = Height(pRoot->_pLeft); size_t right = Height(pRoot->_pRight); return left > right ? left + 1 : right + 1; } size_t leafSize() { if (pRoot == NULL) { return 0; } if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL) { return 1; } return Height(pRoot->_pLeft) + Height(pRoot->_pRight); } //获取第k层结点的个数 size_t GetKthLevelCount(Node* pRoot ,size_t k) { if (pRoot == NULL||k<1) { return 0; } if (k == 1) { return 1; } return GetKthLevelCount(pRoot->_pLeft,k-1) + GetKthLevelCount(pRoot->_pRight,k-1); } //获取一颗二叉树的镜像 //利用层序遍历进行左右节点进行交换 Node* mirror(Node* pRoot) { if (pRoot == NULL || (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL)) { return pRoot; } //队列来实现 queue<Node* >q; q.push(pRoot); while (!q.empty()) { Node* pCur = q.front(); q.pop(); if (pCur->_pLeft) { q.push(pCur->_pLeft); } if (pCur->_pRight) { q.push(pCur->_pRight); } swap(pCur->_pLeft, pCur->_pRight); } }protected: //递归创建是一个二叉树 //Node*_CreateTree(Node* pRoot, const T arr[], const size_t length, size_t & index,const T &invalid) //{ // if (pRoot == NULL) // { // if (index < length&&arr[index] != invalid) // { // pRoot = new Node(arr[index]); // } // } // if (pRoot) // { // _CreateTree(pRoot->_pLeft, arr, length, ++index, invalid); // _CreateTree(pRoot->_pRight, arr, length, ++index, invalid); // } // return pRoot; //} Node* _CreateTree(Node* &pRoot,const T arr[],const size_t length,size_t&index,const T&invalid) { Node* temp = NULL; if (index<length&&arr[index]!=invalid)//pRoot为空不能作为遍历结束条件 { //先对根进行操作 temp = new Node(arr[index]); pRoot = temp; _CreateTree(pRoot->_pLeft, arr, length, ++index, invalid);//在遍历左子树 _CreateTree(pRoot->_pRight, arr, length, ++index, invalid);//在遍历右子树 } return temp; } //四种遍历:前中后。层 void _PreOrder(Node* pRoot) { if (pRoot) { cout << pRoot->_data << " "; _PreOrder(pRoot->_pLeft); _PreOrder(pRoot->_pRight); } } void _InOrder(Node* pRoot) { if (pRoot) { _InOrder(pRoot->_pLeft); _InOrder(pRoot->_pRight); cout << pRoot->_data << " "; } } void _MidOrder(Node* pRoot) { if (pRoot) { _PreOrder(pRoot->_pLeft); cout << pRoot->_data << " " << endl; _PreOrder(pRoot->_pRight); } } //拷贝构造函数 //Node* _Copy(Node* node) //{ // Node* cur = node; // Node* root = NULL; // if (cur) // { // root = new Node(cur->_data); // root->_pLeft = _Copy(cur->_pLeft); // root->_pRight = _Copy(cur->_pRight); // } // return root; // //} Node* _Copy(Node* node) { Node* root = NULL; if (node) { root = new Node(node->_data); root->_pLeft = _Copy(node->_pLeft); root->_pRight = _Copy(node->_pRight); } return root; } Node* _Find(Node* root, const T & t) { if (root) { if (root->_data == t) { return root; } Node* ret = _Find(root->_pLeft, t); //此处不应该如此,因为一直递归到最深处,假如没有找到,肯定函数返回为NULL,整个函数结束 if (ret) { return ret; } return _Find(root->_pRight, t); } return root; } size_t _Height(Node* root) { //左右子树最深的个数加1就是当前树的深度 if (root == NULL) { return 0; } size_t left = _Height(root->_pLeft); size_t right = _Height(root->_pRight); return left > right ? left + 1 : right + 1; } void _size(Node* root,size_t & count) { if (root) { if (root->_pLeft == NULL&&root->_pRight == NULL) { return; } _size(root->_pLeft, ++count); _size(root->_pRight, ++count); } } size_t _leaf(Node* root,size_t &count) { if (root == NULL) { return 0; } if (root->_pLeft == NULL&&root->_pRight == NULL) { count++; } _leaf(root->_pLeft, count); _leaf(root->_pRight, count); return count; } //销毁函数 void DestoryTree(Node*pRoot) { if (pRoot) { DestoryTree(pRoot->_pLeft); DestoryTree(pRoot->_pRight); delete pRoot; pRoot = NULL; } } //非递归前序遍历:两种实现 //思路:利用栈模拟递归,保存当前函数的参数,方便后面进行取操作 void _PreOrderNoR(Node* _pRoot) { if (NULL == _pRoot)return; stack<Node*>st; st.push(_pRoot); while (!st.empty()) { Node* pCur = st.top(); st.pop(); cout << pCur->_data << " "; //不为空,入栈 if (pCur->_pRight) { st.push(pCur->_pRight); } if (pCur->_pLeft) { st.push(pCur->_pLeft); } } } void _InOrderNoR(Node* _pRoot) { //中序遍历 万能模板 if (!_pRoot) { return; } stack<Node* >st; st.push(_pRoot); Node* pCur = st.top(); st.pop(); while (pCur||(!st.empty())) { //走到最左子树,保存其路径的结点 while (pCur) { st.push(pCur); pCur = pCur->_pLeft; } //打印节点信息 pCur = st.pop(); cout << pCur->_data << " "; //左子树访问完,访问其右子树 pCur = pCur->_pRight; } } //中序遍历 //后序遍历非递归实现 //思路:左、右、根 进行遍历public: Node* _pRoot; T _invalid;};void Test(){ int arr[] = { 1,2, 4, '#', '#', '#', 3, 5, '#', '#', 6 }; BinaryTree<int> Bt(arr,sizeof(arr)/sizeof(arr[0]),'#'); //Bt.MidOrder(); //Bt.InOrder(); //Bt.PreOrder(); //Bt.LevelOrder(); /*BinaryTree<int> Bt1(Bt); Bt1.PreOrder(); cout << endl; BinaryTreeNode<int>* cur = Bt1.Find(6); cout << cur->_data << " ";*/ BinaryTreeNode<int>* cur = Bt.Find(6); BinaryTreeNode<int>*parent = Bt.Parent(cur); cout << parent->_data << endl; cout << "size::" << Bt.size() << " " << "Height::" << Bt.Height() << " Leaf::" << Bt.leaf() << endl;}void Test2(){ int arr[] = { 1, 2, 4, '#', '#', '#', 3, 5, '#', '#', 6 }; BinaryTree<int> Bt(arr, sizeof(arr) / sizeof(arr[0]), '#'); BinaryTreeNode<int>* node1 = Bt.Find(5); BinaryTreeNode<int>* node2 = Bt.Find(6); BinaryTreeNode<int>* ret = Bt.GetLastCommonAncestor(Bt._pRoot,node1,node2); cout << node1->_data << "和" << node2->_data << "的公共祖先是:" << ret->_data;}void Test3(){ int pre[] = {1,2,4,3,5,6}; int mid[] = {4,2,1,5,3,6}; BinaryTree<int> bt(pre,6,mid,6); bt.PreOrder();}int main(){ Test3(); return 0;}
0 0
- 二叉树基本操作汇总练习
- 二叉树操作练习
- 二叉树基本操作
- 二叉树 基本操作
- 二叉树基本操作
- 基本二叉树操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树基本操作
- 二叉树--基本操作
- 汇编语言——寻址方式的综合应用及转移指令的原理
- 复盘二进制的习题(2)
- Python网络通信之黏包问题(五)基于SocketServer模块和socket模块
- SUSE Linux Enterprise Server 12 (x86_64) rpm方式 安装gcc
- 基于qt和opencv的远程视频监控与播放
- 二叉树基本操作汇总练习
- 求两个数的最大公约数和最小公倍数
- 初学Nginx windos下安装
- Java 8新特性汇总
- 文件IO编程八
- LeetCode: 561. Array Partition I
- iOS开发给UITableViewCell绘制分割线
- 欢迎使用CSDN-markdown编辑器
- 第二天: 多态运行期间动态绑定的一个案例