二叉树

来源:互联网 发布:amtemu v0.8.1 mac 编辑:程序博客网 时间:2024/06/13 22:25

一、二叉树的概念

二叉树:一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上左右两棵子树的二叉树组成的。

二叉树的特点:

1.每个结点最多有两棵子树(即二叉树不存在度大于2的结点,度为0、1、2);

2.二叉树的子树有左右之分,其子树的次序不能颠倒。


二叉树是通过上述几个情况的组合或嵌套形成的。

满二叉树:在一棵二叉树中,如果所有的分支结点都存在左右子树,并且所有的叶子结点都在同一层上。

完全二叉树:若一棵具有N个结点的二叉树的结构与满二叉树的前N个结点的结构相同,称为完全二叉树。


二、二叉树的性质

1.若规定根结点的层数为1,则一棵非空二叉树第i层上最多有2i-1个结点;

2.若规定只有根节点的二叉树的深度为1,则深度为K 的二叉树的最大结点数为2k-1;

3.任何一棵二叉树,度为0的结点个数为n0,度为1的结点个数为n1,则有n0=n1+1;


4.结点个数为n的完全二叉树,深度K=log2(n+1)。

5.一棵完全二叉树,从上到下,从左到右,对所有的结点排序(从0开始),对于序号为i的结点有:

a.若i>0,双亲结点p=(i-1)/2;若i=0,为根结点;

b.若2i+1<n,序号为i的结点双亲结点的序号为2i+1;若2i+1>n,则序号为i的结点无左孩子结点;

c.若2i+2<n,序号为i的结点双亲结点的序号为2i+2;若2i+2>n,则序号为i的结点无右孩子结点;

三、二叉树的存储结构

1.顺序存储


优点:存取完全二叉树,节省空间;

缺点:类似遇到单支树的情况,不方便存储。

2.链式存储

#include <iostream>using namespace std;#include <stack>#include <string.h>#include <queue>template <class T>struct BinNode{BinNode(const T& data = T()):data(data), left(NULL), right(NULL){}T data;BinNode<T>* left;BinNode<T>* right;};template <class T>class BinTree{typedef BinNode<T> Node;typedef BinNode<T>* pNode;public://构造函数BinTree():_pRoot(NULL){}//创建一棵二叉树,前序创建BinTree(const T* arr,size_t size,const T& invalid){size_t index = 0;_pRoot=_Create(arr, size, index, invalid);}//拷贝构造函数BinTree(const BinTree& sm){if (this != &sm){_pRoot = _Copy(sm._pRoot);}}//赋值运算符重载BinTree& operator=(const BinTree& sm){if (this != &sm){_DestoryTree(_pRoot);//销毁当前树_pRoot = _Copy(sm._pRoot);}return *this;}//析构函数~BinTree(){    _DestoryTree(_pRoot);_pRoot = NULL;}//前序遍历二叉树void PreOrder(){_PreOrder(_pRoot);cout << endl;}void PreOrderTraversal(){_PreOrderTraversal(_pRoot);cout << endl;}//中序遍历二叉树void InOrder(){_InOrder(_pRoot);cout << endl;}void InOrderTraversal(){_InOrderTraversal(_pRoot);cout << endl;}//后序遍历二叉树void PostOrder(){_PostOrder(_pRoot);cout << endl;}void PostOrderTraversal(){_PostOrderTraversal(_pRoot);cout << endl;}//层序遍历void LevelOrder(){_LevelOrder(_pRoot);cout << endl;}//结点个数size_t Node_Count(){return _Node_Count(_pRoot);}//叶结点的个数size_t LeafNode_Count(){return _LeafNode_Count(_pRoot);}//第K层结点的个数size_t KNode_Count(size_t K){return _KNode_Count(_pRoot, K);}//二叉树的高度size_t Hight(){return _Hight(_pRoot);}//值为data的元素的位置pNode Find(const T& data){return _Find(_pRoot, data);}//双亲结点pNode ParentNode(pNode curNode){return _ParentNode(_pRoot, curNode);}//左孩子结点pNode Left_Child(pNode curNode){return _Left_Child(_pRoot, curNode);}//右孩子结点pNode Right_Child(pNode curNode){return _Right_Child(_pRoot, curNode);}//二叉树的镜像void MirrorBinTree(){_MirrorBinTree(_pRoot);}bool IsCompleteBinTree(){return _IsCompleteBinTree(_pRoot);}private:pNode _Create(const T* arr, size_t size, size_t& index,const T& invalid){if (NULL == arr)return NULL;pNode pRoot = NULL;if (index < size && arr[index] != invalid){//创建根结点pRoot = new Node(arr[index]);//创建左子树pRoot->left=_Create(arr, size, ++index, invalid);//创建右子树pRoot->right=_Create(arr, size, ++index, invalid);}return pRoot;}//拷贝二叉树pNode _Copy(pNode pRoot){if (pRoot){//拷贝根结点pNode newpRoot = new Node(pRoot->data);//拷贝左子树if (pRoot->left)newpRoot->left = _Copy(pRoot->left);//拷贝右子树if (pRoot->right)newpRoot->right = _Copy(pRoot->right);}return pRoot;}//销毁二叉树,后序销毁void _DestoryTree(pNode pRoot){if (pRoot)return;if (pRoot->left == NULL&&pRoot->right == NULL){delete pRoot;return;}//销毁左子树if (pRoot->left){_DestoryTree(pRoot->left);pRoot->left = NULL;}//销毁右子树if (pRoot->right){_DestoryTree(pRoot->right);pRoot->right = NULL;}//销毁根结点delete pRoot;}//前序遍历二叉树--->递归实现void _PreOrder(pNode pRoot){if (!pRoot)return;//访问根结点cout << pRoot->data << " ";//访问左子树_PreOrder(pRoot->left);//访问右子树_PreOrder(pRoot->right);}//前序遍历二叉树--->循环实现void _PreOrderTraversal(pNode pRoot){if (pRoot == NULL)return;stack<pNode> s;pNode pCur = NULL;s.push(pRoot);while (!s.empty()){pCur = s.top();s.pop();while (pCur){cout << pCur->data << " ";if (pCur->right)//如果右子树存在,先压右子树s.push(pCur->right);pCur = pCur->left;}}}//中序遍历二叉树void _InOrder(pNode pRoot){if (!pRoot)return;//访问左子树_InOrder(pRoot->left);//访问根结点cout << pRoot->data << " ";//访问右子树_InOrder(pRoot->right);}//中序遍历二叉树---->循环实现void _InOrderTraversal(pNode pRoot){if (pRoot == NULL)return;stack<pNode> s;pNode pCur = pRoot;while (pCur||!s.empty()){while (pCur)//保存左侧路径的所有结点{s.push(pCur);pCur = pCur->left;}pCur = s.top();//取栈顶元素cout << pCur->data << " ";//访问s.pop();//出栈pCur = pCur->right;//对当前结点的右子树继续做同样的事情}}//后序遍历二叉树void _PostOrder(pNode pRoot){if (!pRoot)return;//访问左子树_PostOrder(pRoot->left);//访问右子树_PostOrder(pRoot->right);//访问根结点cout << pRoot->data << " ";}//后序遍历二叉树---->循环实现void _PostOrderTraversal(pNode pRoot){if (pRoot == NULL)return;pNode pCur = pRoot;pNode pPre = NULL;stack<pNode> s;while (!s.empty()||pCur){while (pCur)//保存左侧路径的所有结点{s.push(pCur);pCur = pCur->left;}if (s.empty())return;pNode top = s.top();if (top->right == NULL || pPre == top->right)//当前结点的右子树为空{cout << top->data << " ";//访问pPre = top;s.pop();}elsepCur = top->right;}}//层序遍历void _LevelOrder(pNode pRoot){if (pRoot == NULL)return;queue<pNode> q;q.push(pRoot);while (!q.empty()){pNode pcur = q.front();cout << pcur->data << " ";q.pop();if (pcur->left)q.push(pcur->left);if (pcur->right)q.push(pcur->right);}}//结点个数size_t _Node_Count(pNode pRoot){//空树if (pRoot == NULL)return 0;//其他情况else{return _Node_Count(pRoot->left) + _Node_Count(pRoot->right) + 1;}}//叶结点的个数size_t _LeafNode_Count(pNode pRoot){//空树if (pRoot == NULL)return 0;//只有一个结点if (pRoot->left == NULL&&pRoot->right == NULL)return 1;//多个结点elsereturn _LeafNode_Count(pRoot->left) + _LeafNode_Count(pRoot->right);}//二叉树的高度size_t _Hight(pNode pRoot){if (pRoot == NULL)return 0;if (pRoot->left == NULL&&pRoot->right == NULL)return 1;else{return (_Hight(pRoot->left) > _Hight(pRoot->right)) ? _Hight(pRoot->left)+1 : _Hight(pRoot->right)+1;}}//值为data的元素的位置pNode _Find(pNode pRoot, const T& data){//空树if (pRoot == NULL)return NULL;//寻找的值为根结点的值if (pRoot->data == data)return pRoot;if (pRoot->left)_Find(pRoot->left, data);if (pRoot->right)_Find(pRoot->right, data);return pRoot;}//双亲结点pNode _ParentNode(pNode pRoot, pNode curNode){//结点为空,树为空,为根结点if (pRoot == NULL || curNode == NULL || pRoot = curNode)return NULL;//根为双亲结点if (pRoot->left == curNode || pRoot->right == curNode)return pRoot;//左子树if (pRoot->left)_ParentNode(pRoot->left, curNode);if (pRoot->right)_ParentNode(pRoot->right, curNode);}//左孩子结点pNode _Left_Child(pNode pRoot, pNode curNode){if (pRoot == NULL || curNode == NULL)return NULL;return curNode->left;}//右孩子结点pNode _Right_Child(pNode pRoot, pNode curNode){if (pRoot == NULL || curNode == NULL)return NULL;return curNode->right;}//二叉树的镜像void _MirrorBinTree(pNode pRoot){if (pRoot == NULL)return;//镜像结点    swap(pRoot->left, pRoot->right);//镜像左子树_MirrorBinTree(pRoot->left);//镜像右子树_MirrorBinTree(pRoot->right);}//第K层结点的个数size_t _KNode_Count(pNode pRoot,size_t k){if (pRoot == NULL || k==0)return 0;if (k==1)return 1;return _KNode_Count(pRoot->left, k - 1) + _KNode_Count(pRoot->right, k - 1);}//判断一棵二叉树是否为完全二叉树bool _IsCompleteBinTree(pNode pRoot){//空树if (pRoot == NULL)return true;//一个结点if (pRoot->left == NULL&&pRoot->right == NULL)return true;queue<pNode> q;pNode pCur = NULL;//多个结点while (pCur || !q.empty()){if (pCur->right&&NULL == pCur->left)//右子树存在,左子树不存在return false;if (pCur->left&&pCur->right)//饱和结点{q.push(pCur);}}}private:pNode _pRoot;};
测试函数:

void test1(){char arr[] = "ABCD##E##F##GMN###Q##";int len = strlen(arr);BinTree<char> tree1(arr, len, '#');tree1.PreOrder();//前序tree1.InOrder();//中序tree1.PostOrder();//后序BinTree<char> tree2(tree1);//拷贝tree2.PreOrder();BinTree<char> tree3 = tree1;//赋值tree3.PreOrder();int a = tree1.Node_Count();cout << "The number of Node is " << a << endl;int b = tree1.LeafNode_Count();cout << "The number of LeafNode is " << b << endl;int c = tree1.Hight();cout << "The Hight of Tree is " << c << endl;cout << "G的地址为:" << tree1.Find('G') << endl;tree1.LevelOrder();//层序遍历}void test2(){char arr[] = "AB#MDE##F";int len = strlen(arr);BinTree<char> tree1(arr, len, '#');cout << "前序遍历:  ";tree1.PreOrderTraversal();cout << "中序遍历:  ";tree1.InOrderTraversal();cout << "后序遍历:  ";tree1.PostOrderTraversal();tree1.MirrorBinTree();cout << "镜像后前序遍历:  ";tree1.PreOrderTraversal();size_t b = 3;int a = tree1.KNode_Count(b);cout << "第<<b<<层结点的个数:" << a << endl;if (tree1.IsCompleteBinTree())cout << "此树是一棵完全二叉树" << endl;else    cout << "此树不是一棵完全二叉树" << endl;}int main(){test2();system("pause:");return 0;}

原创粉丝点击