树:是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