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

       树:是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;
					else
						return &_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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值