二叉树

来源:互联网 发布:数据量化方法 编辑:程序博客网 时间:2024/06/08 08:18

一、什么是二叉树

            二叉树 (binary tree) 是另一种树型结构,它的特点是每个结点至多只有二棵子 树 (即二叉树中不存在度大于 2的结点 ),并且,二叉树的子树有左右之分,其次序不能任意颠倒 。 二叉树是一种数据结构 ,是一对多的关系。


二、二叉树的创建

      第一步:想要构造一颗二叉树首先要创建二叉树的节点,然后将节点按照二叉树的规则连接起来就构成了一颗二叉树。二叉树的每个节点包含三个元素 ----->左指针域 pLeft ,右指针域 pRight ,数据域 data。

           

如图----->当有孩子时pLeft指向左孩子节点,pRight指向右孩子节点。

--------->当没有节点时指针指向空-->NULL

如何用代码创建节点:(创建一个模板类型的节点)

template<class T>struct Node{Node(){LChild = NULL;RChild = NULL;}Node(T d):data(d){LChild = NULL;RChild = NULL;}T data;Node<T>* LChild;Node<T>* RChild;};template<class T>struct Node{Node(){LChild = NULL;RChild = NULL;}Node(T d):data(d){LChild = NULL;RChild = NULL;}T data;Node<T>* LChild;Node<T>* RChild;};


第二步:
        开辟空间,将节点按照二叉树的规则连接
template<class T>class BinTree{typedef Node<T>* PNode;public:BinTree()                    //无参构造: _pRoot(NULL){}BinTree(const T* array, size_t size, const T& invalid)      //有参构造{size_t index = 0;_CreateBinTree(_pRoot, array, size, index, invalid);    //调用创建二叉树函数}BinTree(const BinTree& bt)             //拷贝构造{_pRoot = _CopyBinTree(bt._pRoot);        //调用拷贝函数}BinTree& operator=(const BinTree& bt)    //赋值运算符重载{if (this == &bt)return *this;if (_pRoot != NULL)_DestroyBinTree(_pRoot);    //调用销毁函数_pRoot = _CopyBinTree(bt._pRoot);     //调用拷贝函数return *this;}~BinTree()                         //析构函数{    _DestroyBinTree(_pRoot);         //调用销毁函数}}
将 创建函数,拷贝函数,销毁函数 定义成私有函数,只允许类的内部成员调用。

private:// 根+左子树+右子树 void _CreateBinTree(PNode& pRoot, const T* array, size_t size, size_t& index, const T& invalid){if (index >= size)return;if (index < size&&array[index]=='#')return;char ch = array[index];pRoot = new Node<T>(ch);_CreateBinTree(pRoot->LChild, array, size, ++index, invalid);_CreateBinTree(pRoot->RChild, array, size, ++index, invalid);}PNode _CopyBinTree(PNode pRoot)             //拷贝一个树{PNode newTree = NULL;if (pRoot){newTree = new Node<T>(pRoot->data);if (pRoot->LChild)newTree->LChild = _CopyBinTree(pRoot->LChild);if (pRoot->RChild)newTree->RChild = _CopyBinTree(pRoot->RChild);}return newTree;}void _DestroyBinTree(PNode& pRoot)       //释放节点{if (pRoot == NULL)return;if (pRoot->LChild == NULL&&pRoot == NULL){delete pRoot;pRoot = NULL;return;}_DestroyBinTree(pRoot->LChild);_DestroyBinTree(pRoot->RChild);delete pRoot;pRoot = NULL;}

到此一个二叉树的类就写好了,接下来写二叉树里的接口。

将要实现功能的函数都定义成私有函数,再写一个公有函数调用与其对应功能的私有函数,这样可以使对外接口使用起来更简单。

1.先序遍历

(1)递归实现

void _PreOrder(PNode pRoot)      //先序遍历  根--->根的左子树---->根的右子树 {if (pRoot != NULL){cout << pRoot->data << " ";_PreOrder(pRoot->LChild);_PreOrder(pRoot->RChild);}}
(2)非递归

void _XPreOder(PNode pRoot){if (pRoot == NULL)return;stack<PNode> s;s.push(pRoot);while (!s.empty()){PNode ret = s.top();s.pop();while (ret){cout << ret->data << " ";if (ret->RChild)s.push(ret->RChild);ret = ret->LChild;}}}

2.中序遍历

(1)递归形式

void _InOrder(PNode pRoot)    //中序遍历  左子树--->根节点--->右子树 {if (pRoot != NULL){_InOrder(pRoot->LChild);cout << pRoot->data << " ";_InOrder(pRoot->RChild);}} 
(2)非递归形式

void _XInOder(PNode pRoot){if (pRoot == NULL)return;stack<PNode> s;PNode ret = pRoot;while (ret || !s.empty()){while (ret){s.push(ret);ret = ret->LChild;}ret = s.top();cout << ret->data << " ";s.pop();ret = ret->RChild;}}
3.后序遍历

(1)递归形式

void _PostOrder(PNode pRoot)     //后序遍历  左子树--->右子树--->根节点 {if (pRoot != NULL){_PostOrder(pRoot->LChild);_PostOrder(pRoot->RChild);cout << pRoot->data<<" ";}}
(2)非递归形式

void _XPostOder(PNode pRoot){if (pRoot == NULL)return;stack<PNode> s;PNode ret = pRoot;PNode flag = NULL;while (ret || !s.empty()){while (ret){s.push(ret);ret = ret->LChild;}ret = s.top();if (ret->RChild == NULL || flag == ret->RChild){cout << ret->data << " ";flag = ret;s.pop();ret = NULL;}elseret =s.top()->RChild;}}
4.层序遍历



层序遍历就是一层一层访问

void _LevelOrder(PNode pRoot)      //层序遍历{if (pRoot == NULL)return;PNode ret = NULL;queue<PNode> q;q.push(pRoot);while (!q.empty()){ret = q.front();cout << ret->data <<" ";q.pop();if (ret->LChild)q.push(ret->LChild);if (ret->RChild)q.push(ret->RChild);}}
5.总节点个数

size_t _Size(PNode pRoot){if (pRoot == NULL)return 0;if (pRoot->LChild == NULL&&pRoot->RChild == NULL)return 1;return _Size(pRoot->LChild) + _Size(pRoot->RChild)+1;}

6.叶子节点的总个数

size_t _GetLeefCount(PNode pRoot){if (pRoot == NULL)return 0;if (pRoot->LChild == NULL&&pRoot->RChild == NULL)return 1;return _GetLeefCount(pRoot->LChild) + _GetLeefCount(pRoot->RChild);}

7.获取第k层节点的个数

size_t _GetKLevelCount(PNode pRoot,size_t k){if (pRoot == NULL || k < 1)return 0;if (k == 1)return 1;return _GetKLevelCount(pRoot->LChild, k - 1) + _GetKLevelCount(pRoot->RChild, k - 1);}

8.树的高度

size_t _Height(PNode pRoot){if (pRoot == NULL)return 0;if (pRoot->LChild == NULL&&pRoot->RChild == NULL)return 1;size_t Left = _Height(pRoot->LChild);size_t Right = _Height(pRoot->RChild);return (Left > Right ? Left + 1 : Right + 1);}

9.查找某节点的位置

PNode _Find(PNode pRoot, const T& data){if (pRoot == NULL)return NULL;if (pRoot->data == data)return pRoot;if (_Find(pRoot->LChild, data))return _Find(pRoot->LChild,data);if (_Find(pRoot->RChild, data))return _Find(pRoot->RChild,data);return NULL;}

10.查找指定节点的双亲节点

PNode _Parent(PNode pRoot, PNode pNode){if (pRoot == NULL)return NULL;if (pRoot->LChild == pNode || pRoot->RChild == pNode)return pRoot;if (_Parent(pRoot->LChild, pNode))return _Parent(pRoot->LChild,pNode);if (_Parent(pRoot->RChild, pNode))return _Parent(pRoot->RChild, pNode);return NULL;}

11.查找指定节点的左孩子节点

PNode LeftChild(PNode pNode)     //查找指定节点的左孩子节点{return pNode->LChild;}

12.查找指定节点的右孩子节点

PNode RightChild(PNode pNode)     //查找指定节点的右孩子节点{return pNode->RChild;}
13.二叉树镜像


(1)递归实现

void _BinTreeMirror(PNode &pRoot)        //递归实现{if (pRoot == NULL)return;swap(pRoot->LChild, pRoot->RChild);_BinTreeMirror(pRoot->LChild);_BinTreeMirror(pRoot->RChild);}

(2)非递归实现

void _XBinTreeMirror(PNode &pRoot)          //层序遍历实现{if (pRoot == NULL)return;queue<PNode> q;q.push(pRoot);PNode ret = NULL;while (!q.empty()){ret = q.front();q.pop();swap(ret->LChild, ret->RChild);if (ret->LChild)q.push(ret->LChild);if (ret->RChild)q.push(ret->RChild);}}

14.判断是否是完全二叉树

首先,分析二叉树

(1)当二叉树为空时,是完全二叉树

(2)当二叉树只有一个节点时,是完全二叉树

(3)当二叉树有多个节点时---->

        创建一个队,将根节点入队,然后进入循环;当对不为空,继续循环。

在循环外创建一个标记flag=false,在循环内使用;当false为true时,并且(ret->left!=NULL||ret->Right!=NULL)二叉树不是完全二叉树。

           a.左右子树都存在,入队

b.只有左子树,没有右子树;不饱和点,将左子树入队,将标记flag=true;

c.只有右子树,没有左子树,不是完全二叉树

d.没有左子树,没有右子树;不饱和点,将标记flag=true

bool _IsComplateBinTree(PNode pRoot)        //判断是否是完全二叉树{if (pRoot == NULL)return true;queue<PNode> q;q.push(pRoot);bool flag = false;PNode ret = NULL;while (!q.empty()){ret = q.front();q.pop();if (flag==true&&(ret->LChild||ret->RChild))return false;else{if (ret->LChild&&ret->RChild){q.push(ret->LChild);q.push(ret->RChild);}else if (ret->LChild&&ret->RChild == NULL){q.push(ret->LChild);flag = true;}else if (ret->LChild == NULL&&ret->RChild)return false;else{flag = true;}}}return true;}


三、完整的二叉树代码

#include<iostream>#include<queue>#include<stack>using namespace std;template<class T>struct Node{Node(){LChild = NULL;RChild = NULL;}Node(T d):data(d){LChild = NULL;RChild = NULL;}T data;Node<T>* LChild;Node<T>* RChild;};template<class T>class BinTree{typedef Node<T>* PNode;public:BinTree(): _pRoot(NULL){}BinTree(const T* array, size_t size, const T& invalid){size_t index = 0;_CreateBinTree(_pRoot, array, size, index, invalid);}BinTree(const BinTree& bt){_pRoot = _CopyBinTree(bt._pRoot);}BinTree& operator=(const BinTree& bt){if (this == &bt)return *this;if (_pRoot != NULL)_DestroyBinTree(_pRoot);_pRoot = _CopyBinTree(bt._pRoot);return *this;}~BinTree()                         //析构函数{    _DestroyBinTree(_pRoot);}void PreOrder()   //先序遍历{_PreOrder(_pRoot);}void InOrder()    //中序遍历{_InOrder(_pRoot);}void PostOrder()     //后序遍历{_PostOrder(_pRoot);}void LevelOrder()      //层序遍历{_LevelOrder(_pRoot);}/////////////////////////////////////////////////////////////////////////////////////////非递归遍历void XPreOder()    //非递归前序遍历{_XPreOder(_pRoot);}void XInOder()     //非递归中序遍历{_XInOder(_pRoot);}void XPostOder()    //非递归后序遍历{_XPostOder(_pRoot);}/////////////////////////////////////////////////////////二叉树镜像void BinTreeMirror()    //递归实现{_BinTreeMirror(_pRoot);}void XBinTreeMirror()      //层序遍历实现{_XBinTreeMirror(_pRoot);}///////////////////////////////////////////////////////////////////////////////////////size_t Size()    //总结点个数{return _Size(_pRoot);}size_t GetLeefCount()    //叶子节点的总个数{return _GetLeefCount(_pRoot);}size_t GetKLevelCount(size_t K)      // 获取第K层结点的个数 {return _GetKLevelCount(_pRoot, K);}size_t Height()          //树的高度{return _Height(_pRoot);}PNode Find(const T& data)   //查找某个节点的位置{return _Find(_pRoot, data);}PNode Parent(PNode pNode)      //查找指定位置的双亲节点{return _Parent(_pRoot, pNode);}PNode LeftChild(PNode pNode)     //查找指定节点的左孩子节点{return pNode->LChild;}PNode RightChild(PNode pNode)     //查找指定节点的右孩子节点{return pNode->RChild;}bool IsComplateBinTree()               //判断是否是完全二叉树{return _IsComplateBinTree(_pRoot);     }private:// 根+左子树+右子树 void _CreateBinTree(PNode& pRoot, const T* array, size_t size, size_t& index, const T& invalid){if (index >= size)return;if (index < size&&array[index]=='#')return;char ch = array[index];pRoot = new Node<T>(ch);_CreateBinTree(pRoot->LChild, array, size, ++index, invalid);_CreateBinTree(pRoot->RChild, array, size, ++index, invalid);}PNode _CopyBinTree(PNode pRoot)             //拷贝一个树{PNode newTree = NULL;if (pRoot){newTree = new Node<T>(pRoot->data);if (pRoot->LChild)newTree->LChild = _CopyBinTree(pRoot->LChild);if (pRoot->RChild)newTree->RChild = _CopyBinTree(pRoot->RChild);}return newTree;}void _DestroyBinTree(PNode& pRoot)       //释放节点{if (pRoot == NULL)return;if (pRoot->LChild == NULL&&pRoot == NULL){delete pRoot;pRoot = NULL;return;}_DestroyBinTree(pRoot->LChild);_DestroyBinTree(pRoot->RChild);delete pRoot;pRoot = NULL;}void _PreOrder(PNode pRoot)      //先序遍历  根--->根的左子树---->根的右子树 {if (pRoot != NULL){cout << pRoot->data << " ";_PreOrder(pRoot->LChild);_PreOrder(pRoot->RChild);}}void _InOrder(PNode pRoot)    //中序遍历  左子树--->根节点--->右子树 {if (pRoot != NULL){_InOrder(pRoot->LChild);cout << pRoot->data << " ";_InOrder(pRoot->RChild);}} void _PostOrder(PNode pRoot)     //后序遍历  左子树--->右子树--->根节点 {if (pRoot != NULL){_PostOrder(pRoot->LChild);_PostOrder(pRoot->RChild);cout << pRoot->data<<" ";}}void _LevelOrder(PNode pRoot)      //层序遍历{if (pRoot == NULL)return;PNode ret = NULL;queue<PNode> q;q.push(pRoot);while (!q.empty()){ret = q.front();cout << ret->data <<" ";q.pop();if (ret->LChild)q.push(ret->LChild);if (ret->RChild)q.push(ret->RChild);}}////////////////////////////////////////////////////////////////////////////////////////////非递归遍历函数定义void _XPreOder(PNode pRoot){if (pRoot == NULL)return;stack<PNode> s;s.push(pRoot);while (!s.empty()){PNode ret = s.top();s.pop();while (ret){cout << ret->data << " ";if (ret->RChild)s.push(ret->RChild);ret = ret->LChild;}}}void _XInOder(PNode pRoot){if (pRoot == NULL)return;stack<PNode> s;PNode ret = pRoot;while (ret || !s.empty()){while (ret){s.push(ret);ret = ret->LChild;}ret = s.top();cout << ret->data << " ";s.pop();ret = ret->RChild;}}void _XPostOder(PNode pRoot){if (pRoot == NULL)return;stack<PNode> s;PNode ret = pRoot;PNode flag = NULL;while (ret || !s.empty()){while (ret){s.push(ret);ret = ret->LChild;}ret = s.top();if (ret->RChild == NULL || flag == ret->RChild){cout << ret->data << " ";flag = ret;s.pop();ret = NULL;}elseret =s.top()->RChild;}}////////////////////////////////////////////////////////////////////////////////////////////二叉树镜像void _BinTreeMirror(PNode &pRoot)        //递归实现{if (pRoot == NULL)return;swap(pRoot->LChild, pRoot->RChild);_BinTreeMirror(pRoot->LChild);_BinTreeMirror(pRoot->RChild);}void _XBinTreeMirror(PNode &pRoot)          //层序遍历实现{if (pRoot == NULL)return;queue<PNode> q;q.push(pRoot);PNode ret = NULL;while (!q.empty()){ret = q.front();q.pop();swap(ret->LChild, ret->RChild);if (ret->LChild)q.push(ret->LChild);if (ret->RChild)q.push(ret->RChild);}}//////////////////////////////////////////////////////////////////////////////////////////size_t _GetKLevelCount(PNode pRoot,size_t k){if (pRoot == NULL || k < 1)return 0;if (k == 1)return 1;return _GetKLevelCount(pRoot->LChild, k - 1) + _GetKLevelCount(pRoot->RChild, k - 1);}size_t _Size(PNode pRoot){if (pRoot == NULL)return 0;if (pRoot->LChild == NULL&&pRoot->RChild == NULL)return 1;return _Size(pRoot->LChild) + _Size(pRoot->RChild)+1;}size_t _GetLeefCount(PNode pRoot){if (pRoot == NULL)return 0;if (pRoot->LChild == NULL&&pRoot->RChild == NULL)return 1;return _GetLeefCount(pRoot->LChild) + _GetLeefCount(pRoot->RChild);}size_t _Height(PNode pRoot){if (pRoot == NULL)return 0;if (pRoot->LChild == NULL&&pRoot->RChild == NULL)return 1;size_t Left = _Height(pRoot->LChild);size_t Right = _Height(pRoot->RChild);return (Left > Right ? Left + 1 : Right + 1);}PNode _Find(PNode pRoot, const T& data){if (pRoot == NULL)return NULL;if (pRoot->data == data)return pRoot;if (_Find(pRoot->LChild, data))return _Find(pRoot->LChild,data);if (_Find(pRoot->RChild, data))return _Find(pRoot->RChild,data);return NULL;}PNode _Parent(PNode pRoot, PNode pNode){if (pRoot == NULL)return NULL;if (pRoot->LChild == pNode || pRoot->RChild == pNode)return pRoot;if (_Parent(pRoot->LChild, pNode))return _Parent(pRoot->LChild,pNode);if (_Parent(pRoot->RChild, pNode))return _Parent(pRoot->RChild, pNode);return NULL;}bool _IsComplateBinTree(PNode pRoot)        //判断是否是完全二叉树{if (pRoot == NULL)return true;queue<PNode> q;q.push(pRoot);bool flag = false;PNode ret = NULL;while (!q.empty()){ret = q.front();q.pop();if (flag==true&&(ret->LChild||ret->RChild))return false;else{if (ret->LChild&&ret->RChild){q.push(ret->LChild);q.push(ret->RChild);}else if (ret->LChild&&ret->RChild == NULL){q.push(ret->LChild);flag = true;}else if (ret->LChild == NULL&&ret->RChild)return false;else{flag = true;}}}return true;}private:PNode _pRoot;};void test1()      ///////////////////////////////////////从此开始下面的函数是测试函数{char *p = "ABC###DE##F";BinTree<char> t1(p, strlen(p), '#');/*t1.PreOrder();cout << endl;t1.InOrder();cout << endl;t1.PostOrder();cout << endl;*///BinTree<char> t2(t1);BinTree<char> t3;t3 = t1;}void test2(){char *p = "ABC###DE##FG";BinTree<char> t1(p, strlen(p), '#');BinTree<char> t2;cout << t1.Size() << endl;cout << t1.GetLeefCount() << endl;cout << t1.Height() << endl;//char ret = 'F';     //if (t1.Find(ret))   //找节点//{//cout << t1.Find(ret)->data << endl;//}cout << t1.Parent(t1.Find('D'))->data << endl;      //找双亲节点cout << t1.GetKLevelCount(4) << endl;t1.LevelOrder();}void test3(){char *p = "ABC###DE##F";BinTree<char> t1(p, strlen(p), '#');t1.PreOrder();cout << endl;t1.XPreOder();cout << endl;t1.InOrder();cout << endl;t1.XInOder();cout << endl;t1.PostOrder();cout << endl;t1.XPostOder();}void test4()               //测试镜像{char *p = "ABC###DE##FG";BinTree<char> t1(p, strlen(p), '#');char *p2 = "ABC##D##EF###";BinTree<char> t2(p2, strlen(p2), '#');t1.PreOrder();cout << endl;t2.PreOrder();cout << endl;/*t1.BinTreeMirror();t1.PreOrder();cout << endl;t1.XBinTreeMirror();t1.PreOrder();*/cout << t1.IsComplateBinTree() << endl;cout << t2.IsComplateBinTree() << endl;}int main(){//test1();//test2();//test3();test4();system("pause");return 0;}

























原创粉丝点击