递归类型的二叉树
来源:互联网 发布:mac删除下载的软件 编辑:程序博客网 时间:2024/05/22 16:58
1.创建节点结构体
template <class T>struct BinaryTreeNode//定义二叉树的节点{ BinaryTreeNode(const T& value) :_value(value) ,_pLeft(NULL) ,_pRight(NULL) {} T _value; BinaryTreeNode<T>* _pLeft; BinaryTreeNode<T>* _pRight;};
2.创建一个类来表示二叉树
template<class T>class BinaryTree{ typedef BinaryTreeNode<T> Node;public: BinaryTree() :_pRoot(NULL)//根节点为空 {} //构造函数 BinaryTree(const T arr[], size_t size, const T& invalid) { size_t index=0; //创建树 _CreateBinaryTree(_pRoot, arr, size, index, invalid); }};
3.创建树
private: void _CreateBinaryTree(Node* &pRoot, const T arr[], size_t size, size_t& index, const T& invalid) { if(index<size && arr[index] != invalid) { //创建根节点 pRoot = new Node(arr[index]); //创建左子树 _CreateBinaryTree(pRoot->_pLeft, arr, size, ++index, invalid); //创建右子树 _CreateBinaryTree(pRoot->_pRight, arr, size, ++index, invalid); } }
用先序遍历的方式依次创建根节点—->创建左子树—–>创建右子树,
再分别将根节点的左子树和右子树作为根节点来创建新的树,最后就将整个树创建好了。
4.拷贝构造
public: BinaryTree(const BinaryTree<T>& bt) { _pRoot = _CopyBinaryTree(bt._pRoot); }private: Node* _CopyBinaryTree(Node* pRoot) { Node* pNode = NULL; if(pRoot) { pNode = new Node(pRoot->_value); pNode->_pLeft = _CopyBinaryTree(pRoot->_pLeft); pNode->_pRight = _CopyBinaryTree(pRoot->_pRight); } return pNode; }
将_CopyBinaryTree()函数的权限设为private,是为了不被其他人看到。
5.赋值运算符重载
public: BinaryTree<T>& operator=(const BinaryTree<T>& bt) { if(this != &bt) { _DestroyBinaryTree(_pRoot); _pRoot = _CopyBinaryTree(bt._pRoot); } return *this; }private: Node* _CopyBinaryTree(Node* pRoot) { Node* pNode = NULL; if(pRoot) { pNode = new Node(pRoot->_value); pNode->_pLeft = _CopyBinaryTree(pRoot->_pLeft); pNode->_pRight = _CopyBinaryTree(pRoot->_pRight); } return pNode; } void _DestroyBinaryTree(Node*& pRoot) { if(pRoot) { _DestroyBinaryTree(pRoot->_pLeft); _DestroyBinaryTree(pRoot->_pRight); delete pRoot; pRoot = NULL; } }
删除原来的节点,要用后序遍历的方法,先删除左子树,再删除右子树,最后删除根节点。先序遍历和中序遍历在删除根节点后,就不能找到其左子树或者是右子树。
6.析构函数
public: ~BinaryTree() { _DestroyBinaryTree(_pRoot); }
7.三种遍历方式的打印
(1).先序遍历
根节点—->左子树—–>右子树
public: void PreOrder() { cout<<"PreOrder"<<endl; _PreOrder(_pRoot); cout<<endl; }private: void _PreOrder(Node* pRoot) { if(pRoot) { cout<<pRoot->_value<<" "; _PreOrder(pRoot->_pLeft); _PreOrder(pRoot->_pRight); } }
(2).中序遍历
左子树—–>根节点—–>右子树
public: void InOrder() { cout<<"InOrder"<<endl; _InOrder(_pRoot); cout<<endl; }private: void _InOrder(Node* pRoot) { if(pRoot) { _InOrder(pRoot->_pLeft); cout<<pRoot->_value<<" "; _InOrder(pRoot->_pRight); } }
(3).后序遍历
左子树—–>右子树—–>根节点
public: void PostOrder() { cout<<"PostOrder"<<endl; _PostOrder(_pRoot); cout<<endl; }private: void _PostOrder(Node* pRoot) { if(pRoot) { _PostOrder(pRoot->_pLeft); _PostOrder(pRoot->_pRight); cout<<pRoot->_value<<" "; } }
8.层序遍历
层序遍历是按照树的结构,一层一层的访问,那么可以借助队列来完成。
先将根节点压入队列—->再读取队列的头结点—–>
再分别将读出的节点的左、右子树压入队列—–>读取当前节点的值—–>
再将头指针后移(将读过的结点pop出队列)。
具体的代码:
public: void LevelOrder() { cout<<"LevelOrder"<<endl; _LevelOrder(_pRoot); cout<<endl; }private: void _LevelOrder(Node* pRoot) { if(pRoot == NULL) return ; queue<Node*> q; q.push(pRoot); while(!q.empty()) { Node* temp = q.front(); if(temp->_pLeft) q.push(temp->_pLeft); if(temp->_pRight) q.push(temp->_pRight); cout<<temp->_value<<" "; q.pop(); } }
9.查找值为value的结点
public: Node* Find(const T& value) { return _Find(_pRoot, value); }private: Node* _Find(Node* pRoot, const T& value) { if(pRoot == NULL) return NULL; if(pRoot->_value == value) return pRoot; Node* pNode = NULL; if(pNode = _Find(pRoot->_pLeft, value)) return pNode; return _Find(pRoot->_pRight, value); }
先判断根节点是不是为空,再判断根节点是不是要查找的值,再遍历左子树、遍历右子树,直到找出。
10.查找左孩子、右孩子以及双亲节点
public: Node* LeftChild() { return _pRoot->_pLeft; } Node* RightChild() { return _pRoot->_pRight; } Node* Parent(Node* pCur) { return _Parent(_pRoot, pCur); }private: Node* _Parent(Node* pRoot, Node* pCur) { assert(pCur != NULL || pRoot != NULL); if(pCur == pRoot) return NULL; if(pCur == pRoot->_pLeft) return pRoot; if(pCur == pRoot->_pRight) return pRoot; Node* temp = NULL; if(temp = _Parent(pRoot->_pLeft, pCur)) return temp; return _Parent(pRoot->_pRight, pCur); }
查找左孩子、右孩子时,可以直接找到,但是对于双亲节点,需要将树遍历一遍。
先判断要查找的节点是否存在—->
再判断根节点是否存在—–>
判断要查找的节点是不是根节点(如果是:就返回NULL,因为根节点没有双亲节点)—–>
再分别判断根节点的左子树、右子树是不是要查找的结点(如果是:就返回根节点,否则继续遍历)—–>
再分别遍历根节点的左、右子树。
11.计算二叉树的深度
public: int BinaryTreeDepth() { return _BinaryTreeDepth(_pRoot); }private: int _BinaryTreeDepth(Node* pRoot) { int i = 0, j = 0; if(pRoot == NULL) return 0; if(pRoot->_pLeft) i = _BinaryTreeDepth(pRoot->_pLeft); else i = 0; if(_BinaryTreeDepth(pRoot->_pRight)) j = _BinaryTreeDepth(pRoot->_pRight); else j = 0; return i>j?i+1:j+1; }
如果树的左、右子树存在,i+1=5。
不存在, i=0。
完整代码
#include <iostream>#include <windows.h>#include <string.h>#include <queue>#include <assert.h>using namespace std;template <class T>struct BinaryTreeNode//定义二叉树的节点{ BinaryTreeNode(const T& value) :_value(value) ,_pLeft(NULL) ,_pRight(NULL) {} T _value; BinaryTreeNode<T>* _pLeft; BinaryTreeNode<T>* _pRight;};template<class T>class BinaryTree{ typedef BinaryTreeNode<T> Node;public: BinaryTree() :_pRoot(NULL) {} BinaryTree(const T arr[], size_t size, const T& invalid) { size_t index=0; _CreateBinaryTree(_pRoot, arr, size, index, invalid); } BinaryTree(const BinaryTree<T>& bt) { _pRoot = _CopyBinaryTree(bt._pRoot); } BinaryTree<T>& operator=(const BinaryTree<T>& bt) { if(this != &bt) { _DestroyBinaryTree(_pRoot); _pRoot = _CopyBinaryTree(bt._pRoot); } return *this; } ~BinaryTree() { _DestroyBinaryTree(_pRoot); } void PreOrder() { cout<<"PreOrder"<<endl; _PreOrder(_pRoot); cout<<endl; } void InOrder() { cout<<"InOrder"<<endl; _InOrder(_pRoot); cout<<endl; } void PostOrder() { cout<<"PostOrder"<<endl; _PostOrder(_pRoot); cout<<endl; } void LevelOrder() { cout<<"LevelOrder"<<endl; _LevelOrder(_pRoot); cout<<endl; } Node* Find(const T& value) { return _Find(_pRoot, value); } Node* LeftChild() { return _pRoot->_pLeft; } Node* RightChild() { return _pRoot->_pRight; } Node* Parent(Node* pCur) { return _Parent(_pRoot, pCur); } int BinaryTreeDepth() { return _BinaryTreeDepth(_pRoot); }private: void _CreateBinaryTree(Node* &pRoot, const T arr[], size_t size, size_t& index, const T& invalid) { if(index<size && arr[index] != invalid) { //创建根节点 pRoot = new Node(arr[index]); //创建左子树 _CreateBinaryTree(pRoot->_pLeft, arr, size, ++index, invalid); //创建右子树 _CreateBinaryTree(pRoot->_pRight, arr, size, ++index, invalid); } } Node* _CopyBinaryTree(Node* pRoot) { Node* pNode = NULL; if(pRoot) { pNode = new Node(pRoot->_value); pNode->_pLeft = _CopyBinaryTree(pRoot->_pLeft); pNode->_pRight = _CopyBinaryTree(pRoot->_pRight); } return pNode; } void _DestroyBinaryTree(Node*& pRoot) { if(pRoot) { _DestroyBinaryTree(pRoot->_pLeft); _DestroyBinaryTree(pRoot->_pRight); delete pRoot; pRoot = NULL; } } void _PreOrder(Node* pRoot) { if(pRoot) { cout<<pRoot->_value<<" "; _PreOrder(pRoot->_pLeft); _PreOrder(pRoot->_pRight); } } void _InOrder(Node* pRoot) { if(pRoot) { _InOrder(pRoot->_pLeft); cout<<pRoot->_value<<" "; _InOrder(pRoot->_pRight); } } void _PostOrder(Node* pRoot) { if(pRoot) { _PostOrder(pRoot->_pLeft); _PostOrder(pRoot->_pRight); cout<<pRoot->_value<<" "; } } void _LevelOrder(Node* pRoot) { if(pRoot == NULL) return ; queue<Node*> q; q.push(pRoot); while(!q.empty()) { Node* temp = q.front(); if(temp->_pLeft) q.push(temp->_pLeft); if(temp->_pRight) q.push(temp->_pRight); cout<<temp->_value<<" "; q.pop(); } } Node* _Find(Node* pRoot, const T& value) { if(pRoot == NULL) return NULL; if(pRoot->_value == value) return pRoot; Node* pNode = NULL; if(pNode = _Find(pRoot->_pLeft, value)) return pNode; return _Find(pRoot->_pRight, value); } Node* _Parent(Node* pRoot, Node* pCur) { assert(pCur != NULL || pRoot != NULL); if(pCur == pRoot) return NULL; if(pCur == pRoot->_pLeft) return pRoot; if(pCur == pRoot->_pRight) return pRoot; Node* temp = NULL; if(temp = _Parent(pRoot->_pLeft, pCur)) return temp; return _Parent(pRoot->_pRight, pCur); } int _BinaryTreeDepth(Node* pRoot) { int i = 0, j = 0; if(pRoot == NULL) return 0; if(pRoot->_pLeft) i = _BinaryTreeDepth(pRoot->_pLeft); else i = 0; if(_BinaryTreeDepth(pRoot->_pRight)) j = _BinaryTreeDepth(pRoot->_pRight); else j = 0; return i>j?i+1:j+1; }private: Node* _pRoot;//根节点};int main(){ char* arr = "124###35##6"; BinaryTree<char> bt1(arr, strlen(arr), '#'); //cout<<"depth = "<<bt1.BinaryTreeDepth()<<endl; //cout<<bt1.Parent(bt1.Find('4'))->_value; //bt1.PreOrder(); //bt1.InOrder(); //bt1.PostOrder(); //bt1.LevelOrder(); //bt1.Find('2'); //cout<<bt1.LeftChild()->_value<<endl; //cout<<bt1.RightChild()->_value<<endl; //BinaryTree<char> bt2(bt1); //BinaryTree<char> bt3; //bt3=bt1; system("pause"); return 0;}
- 递归类型的二叉树
- 二叉树的递归,非递归遍历
- 二叉树的递归+非递归遍历
- 二叉树的递归与非递归
- 二叉树的递归非递归遍历
- 二叉树的遍历--递归+非递归
- 二叉树的递归、非递归遍历
- 二叉树的递归和非递归
- 二叉树的递归与非递归
- 二叉树的递归和非递归
- 二叉树的递归非递归遍历
- 二叉树的递归与非递归
- 二叉树的递归建立
- 二叉树的递归遍历
- 二叉树的递归算法
- 二叉树的递归实现
- 二叉树的递归遍历
- 二叉树的递归遍历
- Spring中的@Controller注解和@RestController注解的相同点和不同点
- LightOJ1248-Dice (III)
- 工厂方法模式
- 简单拓扑-入门
- 小程序开发系列(五)悬浮搜索框
- 递归类型的二叉树
- XAMPP FTP(FileZilla)使用教程
- 浅谈simhash及其python实现
- c#通过txt文档利用打印机命令打印条码标签
- 如何更改MIDI OUT通道的音色
- OpenGL利用键盘控制模型旋转
- C语言经典算法
- Mybatis缓存配置
- Linux:Subversion客户端安装及配置