常用数据结构之链式存储二叉树

来源:互联网 发布:hgame推荐 知乎 编辑:程序博客网 时间:2024/05/29 19:41

       树:是n(n>=0)个节点的有限集合。有且仅有一个特定的根节点。每个节点的子节点的个数称为节点的度,树的度是树内各个节点度的最大值。除了根节点,每个节点都有其双亲,同一双亲的节点称为兄弟节点,子节点位于其双亲节点的下一层,其中根节点为第一层。树中节点的最大层次为树的深度或高度。树中各子树次序不可换的称为有序树,否则为无序树。

     树的三种表示法:

     1、双亲表示法。既每个节点中,附设一个指示其双亲节点位置的链接(下标)。

     2、孩子表示法。每个节点都有指向一个单链表,用于存储其孩子节点的单链表。

     3、孩子兄弟表示法。任意一颗树,它的第一个孩子如果存在就是唯一的,他的右兄弟如果存在也是唯一的,通过设置两个指针分别指向该节点的第一个孩子和此节点的右兄弟。此表示法的最大好处就是它把一颗复杂的树变成一颗二叉树。

      二叉树:由根节点和两个不相交的左子树和右子树组成,左右子树是有顺序的。

      三种特殊的二叉树:

      1、斜树,所有节点都只有左子树或右子树的二叉树。

      2、满二叉树:所有的分支节点都在左子树和右子树,并且所有也只都在同一层上,这样的二叉树称为满二叉树。

      3、完全二叉树 :对于一个n个节点的二叉树按层序编号,如果编号i(1<= i <=n)的节点于同样深度的满二叉数中编号为i的节点在二叉树中的位置完全相同,则这课二叉树称为完全二叉树。满二叉树一定是完全二叉树,反之未必。

      二叉树的性质:

     1、在二叉树的第i层上至多有powl(2,i-1)个节点。(i>=1)

     2、深度为k的二叉树最多有powl(2,k)-1个节点。

     3、若度为0的节点数为n0,度为2的节点数为n2,则有n2+1=n0。推导方法根据二叉树的接线总数n的规律:

         n = n0+n1+n2;

        n-1 = n1 +2n2;

     二叉树的遍历方法:

      1、前序遍历:先遍历节点,然后前序遍历左子树,再前序遍历右子树。

       2、中序遍历:先中序遍历左子树,然后遍历节点,再中序遍历右子树。

       3、后序遍历:先后序遍历左子树,然后后序遍历右子树,再遍历节点。

       4、层序遍历:按照树的层次结构从上至下,从左至右遍历各个节点。


下面是用C++模板类实现的二叉树

/* * ===================================================================================== * *       Filename:  linkbitree.h * *    Description:  linked binary tree using nodes of type binaryTreeNode * *        Version:  1.0 *        Created:  2012年03月17日 10时58分21秒 *       Revision:  none *       Compiler:  gcc * *         Author:  Lavey Luo (lavey), luoyi.smt@gmail.com *   Organization:   * * ===================================================================================== */#ifndef __LINKBITREE_H__#define __LINKBITREE_H__#include "../lists/3linkqueue.h"#include <iostream>namespace st{template <class T> class Bitree;template <class T> class BitreeNode;template<class T>void output(BitreeNode<T>* theNode);template <class T>class BitreeNode {public:  explicit BitreeNode(T d):data(d), leftChild(NULL), rightChild(NULL){};BitreeNode(){ leftChild = NULL; rightChild = NULL;}friend class Bitree<T>;friend void output<T>(BitreeNode<T>* theNode);protected:T data;BitreeNode<T>*  leftChild;BitreeNode<T>*  rightChild;};template<class T>void output(BitreeNode<T>* theNode){if (!theNode) return;std::cout << theNode->data << " ";}template <class T>class Bitree{public:Bitree():_len(0), _root(NULL){};~Bitree(){};public:bool Empty()const { return(_len == 0); }int Length()const { return _len;}T* GetRoot() const{ if (_len == 0) return NULL;elsereturn &_root->data;}BitreeNode<T>*  GetRootNode(){ return _root;}/* 初始条件: 二叉树为空 *//* 操作结果: 将左子树和右子树合并, 根节点的值为e*/bool Maketree(T e,  Bitree<T>* leftChild,  Bitree<T>* rightChild);/* 初始条件: 二叉树存在 *//* 操作结果: 前序递归遍历 */void PreOrder(void(*Visit)(BitreeNode<T>*)){ PreOrder(Visit, _root);}/* 初始条件: 二叉树存在 *//* 操作结果: 中序递归遍历 */void InOrder(void(*Visit)(BitreeNode<T>*)){ InOrder(Visit,  _root);};/* 初始条件: 二叉树存在 *//* 操作结果: 后序递归遍历 */void PostOrder(void(*Visit)(BitreeNode<T>*)){ PostOrder(Visit, _root);};/* 初始条件: 二叉树存在 *//* 操作结果: 层序递归遍历 */void LevelOrder(void(*Visit)(BitreeNode<T> *));/* 初始条件: 二叉树存在。操作结果: 销毁二叉树 */void Destroy(void){ Destroy(_root);};/* 初始条件: 二叉树存在。操作结果: 返回二叉树的深度 */int Height(void) { return Height(_root);};private:int _len;BitreeNode<T>* _root;void Destroy(BitreeNode<T>* node);int Height(BitreeNode<T>* node);void PostOrder(void(*Visit)(BitreeNode<T>*),  BitreeNode<T>* node);void InOrder(void(*Visit)(BitreeNode<T>*),  BitreeNode<T>* node);void PreOrder(void(*Visit)(BitreeNode<T>*),  BitreeNode<T>* node);};template<class T>bool Bitree<T>::Maketree(T e,  Bitree<T>* leftChild,  Bitree<T>* rightChild){if (_len != 0)return false;Destroy();                                  /* 销毁树的原来的节点 */ _root =  new BitreeNode<T>;   /* 新建一个根节点 */if (!_root)return false;_len = 1;_root->data = e;if (leftChild){_len += leftChild->Length();_root->leftChild  = leftChild->GetRootNode();}else_root->leftChild  = NULL;if (rightChild){_len += rightChild->Length();_root->rightChild = rightChild->GetRootNode();}else_root->leftChild  = NULL;return true;}template<class T>void Bitree<T>::PreOrder(void(*Visit)(BitreeNode<T>*),  BitreeNode<T>* node){if (!node)return ;Visit(node);PreOrder(Visit, node->leftChild);PreOrder(Visit, node->rightChild);}template<class T>void Bitree<T>::InOrder(void(*Visit)(BitreeNode<T>*),  BitreeNode<T>* node){if (!node)return ;InOrder(Visit, node->leftChild);Visit(node);InOrder(Visit, node->rightChild);}template<class T>void Bitree<T>::PostOrder(void(*Visit)(BitreeNode<T>*),  BitreeNode<T>* node){if (!node)return ;PostOrder(Visit, node->leftChild);PostOrder(Visit, node->rightChild);Visit(node);}template<class T>void Bitree<T>::LevelOrder(void(*Visit)(BitreeNode<T>*)){if (_len == 0)return ;linkqueue<BitreeNode<T>*> q;q.Init();Visit(_root);q.EnQueue(_root->leftChild);q.EnQueue(_root->rightChild);while (q.Empty() != OK){BitreeNode<T>* n;q.DeQueue(&n);Visit(n);if (NULL != n->leftChild)q.EnQueue(n->leftChild);if (NULL != n->rightChild)q.EnQueue(n->rightChild);}}template<class T>void  Bitree<T>::Destroy(BitreeNode<T>* node){if (node == NULL)return; Destroy(node->leftChild); Destroy(node->rightChild); delete node; _len--;}template<class T>int Bitree<T>::Height(BitreeNode<T>* node){if (node == NULL)return 0;int left = Height(node->leftChild);int right = Height(node->rightChild);return (left > right ? left+1: right+1);}}#endif // __LINKBITREE_H__

测试用例:

/* * ===================================================================================== * *       Filename:  test_bitree.cpp * *    Description:  test case of link binary tree * *        Version:  1.0 *        Created:  2012年03月17日 13时07分45秒 *       Revision:  none *       Compiler:  gcc * *         Author:  Lavey Luo (lavey), luoyi.smt@gmail.com *   Organization:   * * ===================================================================================== */#include "linkbitree.h"#include <stdio.h>int test_linkbitree(int argc,  char** argv){st::Bitree<char> tA;st::Bitree<char> tB;st::Bitree<char> tC;st::Bitree<char> tD;st::Bitree<char> tE;st::Bitree<char> tF;st::Bitree<char> tG;printf("1: size of tA: %d\n",  tA.Length());tG.Maketree('G', NULL, NULL);tF.Maketree('F', NULL, NULL);tE.Maketree('E', NULL, NULL);tD.Maketree('D', NULL, NULL);tC.Maketree('C', &tF, &tG);tB.Maketree('B', &tD, &tE);tA.Maketree('A', &tB, &tC);printf("2: size of tA: %d\n ",  tA.Length());printf("前序遍历:");tA.PreOrder(st::output);puts("\n");printf("中序遍历:");tA.InOrder(st::output);puts("\n");printf("后序遍历:");tA.PostOrder(st::output);puts("\n");printf("层序遍历:");tA.LevelOrder(st::output);puts("\n");printf("3: size of tA: %d\n",  tA.Length());printf("heigth of tA: %d\n",  tA.Height());puts(" destroy the tA");tA.Destroy();printf("4: size of tA: %d\n",  tA.Length());return 0;}


测试结果:

1: size of tA: 0
2: size of tA: 7
 前序遍历:A B D E C F G 


中序遍历:D B E A F C G 


后序遍历:D E B F G C A 


层序遍历:A B C D E F G 


3: size of tA: 7
heigth of tA: 3
 destroy the tA
4: size of tA: 0