二叉树以及 二叉树的C++实现

来源:互联网 发布:淘宝无线端其他来源 编辑:程序博客网 时间:2024/06/14 02:34

二叉树是一种树型结构,特点是每个节点之多有两个子树(即而产生和中不存在度大于2的节点),并且,二叉树的子树有左右之分(左边的称“左子树” , 右边的称 “右子树 ”) ,其次序不能任意颠倒。



二叉树常用于二叉查找树和二叉堆。

下面给出二叉树的基本形态


几种特殊的二叉树

1. 斜树

所有结点都只有左子树的二叉树叫左斜树,所有结点都只有右子树的二叉树叫右斜树。斜树的每一层都只有一个结点,结点的个数与斜树的深度相同。


2. 满二叉树

在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子结点都在同一层上,这样的二叉树称为满二叉树。(上图中所示的二叉树,就是一棵满二叉树)

3. 完全二叉树

对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中的编号为i的结点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树。




二叉树的性质

性质1   在二叉树的第i层上,至多有 2i-1 个节点(根节点的层数为1 )

性质2   深度为k的二叉树至多有  2k-1个节点(k >=1)

性质3   一棵二叉树的叶子结点数为n0,度为2的结点数为n2,则n0 = n2 + 1

性质4    具有n个结点的完全二叉树的深度为floor(log2n) + 1 

性质5    如果对一棵有n个结点的完全二叉树(其深度为floor(log2n) + 1 )的结点按层序编号,则对任一结点i(1≤i≤n)有:
(1) 如果i = 1,则结点i是二叉树的根,无双亲;如果i > 1,则其双亲PARENT(i)是结点 floor((i)/2)
(2)如果2i > n,则结点i无左孩子;否则其左孩子LCHILD(i)是结点2i
(3)如果2i + 1 > n,则结点i无右孩子;否则其右孩子RCHILD(i)是结点2i + 1

二叉树的存储

 1、顺序存储结构

     二叉树可以用数组或线性表来存储,而且如果是完全二叉树,那么这种方法不会浪费空间


#define LENGTH 100typedef char datatype;typedef struct node{    datatype data;    int lchild,rchild;    int parent;}Node;Node tree[LENGTH];int length;int root;



并且这种紧凑排列,如果一个结点的索引为i,则它的子结点能在索引2i+1和2i+2找到,并且它的父节点(如果有)能在索引floor((i-1)/2)找到(假设根节点的索引为0)。

对于一般的二叉树,其层序编号不能反映出逻辑关系,但是可以将其按照完全二叉树编号,只不过把不存在的结点设置为NULL即可。但这么做有一个问题,就是会浪费存储空间。最坏情况下,一个深度为k的斜树(只有k个结点),却需要长度为2k-1的一维数组。所以顺序存储结构一般只用于完全二叉树。

2、链式存储结构

每个结点含有一个数据域和两个指针域(分别指向左右子树)。


二叉树的节点表示

struct BinaryTreeNode{char _data;struct BinaryTreeNode*  pLeft;        struct BinaryTreeNode* pRight;};

利用这种结点结构所得的二叉树存储结构称之为二叉链表。在二叉链表中,如果想找到某个结点的双亲,需要从根节点开始遍历,所以有时为了便于找到结点的双亲,还可以在结点结构中增加一个指向其双亲结点的指针域,相应的二叉树存储结构称之为三叉链表。


二叉树基本实现


//二叉树 节点结构template<class T>struct BinaryTreeNode{typedef BinaryTreeNode<T>*  Treepoint ;BinaryTreeNode(const T& data):_data(data), pLeft(NULL), pRight(NULL){}T _data;Treepoint pLeft;Treepoint pRight;};//二叉树的基本操作template<class T>class BinaryTree{public:BinaryTree():_pRoot(NULL){}BinaryTree(T arr[], size_t sz){size_t index = 0;_CreatNode(_pRoot, arr, sz, index);}BinaryTree(const BinaryTree<T>& t)//拷贝构造{_pRoot = _CopyTree(t._pRoot);}BinaryTreeNode<T>& operator=(const BinaryTree<T>& t) //赋值运算符重载{if (this != &t){_Destroy(this->_pRoot);this->_pRoot = _CopyTree(t._pRoot);}return *this;}~BinaryTree() //析构函数{if (this != NULL){_Destroy(this->_pRoot);}}private:BinaryTreeNode<T>* _pRoot;protected:void _CreatNode(BinaryTreeNode<T>*& Root, T arr[], size_t sz, size_t& index)//创建{                              //传的是引用                        //引用if (index < sz && arr[index] != '?'){//前序遍历 :创建过程  根-左-右Root = new BinaryTreeNode<T>(arr[index]);_CreatNode(Root->pLeft, arr, sz, ++index);_CreatNode(Root->pRight, arr, sz, ++index);}}BinaryTreeNode<T>* _CopyTree(const BinaryTreeNode<T>* Root) //拷贝{BinaryTreeNode<T>* NewRoot = NULL;if (Root != NULL){NewRoot = new BinaryTreeNode<T>(Root->_data);NewRoot->pLeft = _CopyTree(Root->pLeft);NewRoot->pRight = _CopyTree(Root->pRight);}return NewRoot;}void _Destroy(BinaryTreeNode<T>*& Root) //删除顺序 左-右-根{if (Root != NULL){_Destroy(Root->pLeft);_Destroy(Root->pRight);//_Destroy(Root);delete Root;Root = NULL;}}};







0 0
原创粉丝点击