在介紹二叉樹之前大家一定要對樹有一定的瞭解,二叉樹是一種特殊的樹結構,二叉樹每個節點最多有兩個孩子節點,分別爲左孩子和右孩子。
*滿二叉樹:高度爲N的滿二叉樹有2^n-1個節點的二叉樹。
*完全二叉樹:若設二叉樹的深度爲h,除第h層外,其他各層(1~h-1)的節點數都達到最大個數,第h層所有的節點都連續集中在最左邊,這就是完全二叉樹。
*數組存儲表示
當在數據處理過程中,二叉樹的大小和形態不發生劇烈的動態變化時,可以採用數組的方式來表示二叉樹的抽象數據結構類型。
用數組方式存儲二叉樹結構,就是用一組連續的存儲單元存儲二叉樹的數據元素,爲了反映節點在二叉樹中的存儲位置及相互關係,必須適當安排節點的存儲
序。下面用數組來存儲一個完全二樹和一般二叉樹來。
*鏈表存儲表示
根據二叉樹定義,可以設計出二叉樹節點的構造。二叉樹的每個節點至少應該包括三個域:數據data、左子女節點指針和右子女節點指針rightChild,如圖(a)所示。這種鏈
表結構稱爲二叉樹鏈表,使用這種結構可以很方便地根據節點leftChild指針和rightChild指針找到他的左子女和右子女
*遍歷二叉樹的方法:
(1)前序遍歷(先根遍歷):根節點->左子樹->右子樹;【123456】
(2)中序遍歷:左子樹->根節點->右子樹;【324165】
(3)後序遍歷:左子樹->右子樹->根節點;【342651】
(4)層序遍歷:一層層節點依次遍歷。【125346】
當然遍歷二叉樹的方法不知這些,這只是比較簡單的幾種。
*代碼實現二叉樹
#include<iostream>
#include<stack>
#include<queue>
#include<assert.h>
using namespace std;
//節點定義
template<class T>
struct BinaryTreeNode
{
T _data;//數據
BinaryTreeNode<T>* _left;//左孩子
BinaryTreeNode<T>* _right;//右孩子
BinaryTreeNode(const T& x)
:_data(x)
,_left(NULL)
,_right(NULL)
{}
};
//定義二叉樹
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:root(NULL)
{}
BinaryTree(T* a,size_t n,const T&invalid)
{
size_t index=0;
_root=CreateTree(a,n,invalid,index);
}
Node* _copy(Node* root)
{
if(root==NULL)
return NULL;
Node* newRoot=new Node(root->_data);
newRoot->_left=_copy(root->_left);
newRoot->_right=_copy(root->_right);
return newRoot;
}
BinaryTree(const BinaryTree<T>& t)
{
_root=_copy(t._root);
}
BinaryTree<T>& operator=(BinaryTree<T> t)
{
swap(_root,t._root);
return *this;
}
~BinaryTree()
{
Destory(_root);
}
void Destory(Node* root)
{
if(root==NULL)
return;
Destory(root->_left);
Destory(root->_right);
delete root;
}
void PrevOrder()
{
_PrevOrder(_root);
cout<<endl;
}
void InOrder()
{
_InOrder(_root);
cout<<endl;
}
void PrevOrderNonR()
{
stack<Node*> s;
Node* cur=_root;
while(cur||!s.empty())
{
while(cur)
{
cout<<cur->_data<<" ";
s.push(cur);
cur=cur->_left;
}
//top從棧取出來表示這個節點的左子樹訪問過了
//剩餘右子樹還沒有訪問,循環子問題訪問右數
Node* top=s.top();
s.pop();
//子問題的方式訪問右數
cur=top->_right;
}
cout<<endl;
}
void InOrderNonR()//非遞歸實現先序遍歷
{
Node* cur=_root;
stack<Node*> s;
while(cur||!s.empty())
{
while(cur)
{
s.push(cur);
cur=cur->_left;
}
Node* top=s.top;
s.pop();
cout<<top->_data<<" ";
//子問題
cur=top->_right;
}
}
void PostOrderNonR()//非遞歸實現後序遍歷
{
Node* cur=_root;
stack<Node*> s;
Node* prev=NULL;
while(cur||!s.empty())
{
while(cur)
{
s.push(cur);
cur=cur->_left;
}
Node* front=s.top();
if(front->_right==NULL||front->_right==prev)
{
cout<<front->_data<<" ";
prev=front;
s.pop();
}
else
{
cur=front->_right;
}
}
cout<<endl;
}
void LevelOrder()//層序遍歷
{
queue<Node*> q;
if(_root)
{
q.push(_root);
}
while(!q.empty())
{
Node* front=q.front();
cout<<front->_data<<" ";
if(front->_left)
q.push(front->_left);
if(front->_right)
q.push(front->_right);
q.pop();
}
cout<<endl;
}
size_t Size()//求樹的大小
{
return _Size(_root);
}
size_t LeafSize()//求葉子節點的個數
{
return _LeafSize(_root);
}
size_t GetkLeavel(size_t k)//求第K層葉子結點的個數
{
assert(k>0);
return _GetkLeavel(_root,k);
}
Node* Find(const T& x)//查找某個節點
{
return _Find(_root,x);
}
size_t Depth()//求1樹的深度
{
return _Depth(_root);
}
protected://真正實現的部分
void _PrevOrder(Node* root)
{
if(root==NULL)
return;
cout<<root->_data;
_PrevOrder(root->_left);
_PrevOrder(root->_right);
}
void _InOrder(Node* root)
{
if(root==NULL)
return;
_InOrder(root->_left);
cout<<root->_data<<" ";
_InOrder(root->_right);
}
Node* CreateTree(T* a,size_t n,const T& invalid,size_t& index)
{
Node* root=NULL;
if(index<n&&a[index]!=invalid)
{
root=new Node(a[index]);
root->_left=CreateTree(a,n,invalid,++index);
root->_right=CreateTree(a,n,invalid,++index);
}
return root;
}
size_t _Size(Node* root)
{
if(root==NULL)
{
return 0;
}
return _Size(root->_left)+_Size(root->_right)+1;
}
size_t _LeafSize(Node* root)
{
if(root==NULL)
{
return 0;
}
if(root->_left==NULL||root->_right==NULL)
{
return 1;
}
return _LeafSize(root->_left)+_LeafSize(root->_right);
}
size_t _GetkLeavel(Node* root,size_t k)
{
if(root==NULL)
{
return 0;
}
if(k==1)
{
return 1;
}
return _GetkLeavel(root->_left,k-1)+_GetkLeavel(root->_right,k-1);
}
size_t _Depth(Node* root)
{
if(root==NULL)
return 0;
if(root->_left==NULL&&root->_right==NULL)
return 1;
size_t left=_Depth(root->_left);
size_t right=_Depth(root->_right);
return left>right?left+1:right+1;
}
Node* _Find(Node* root,const T&x)
{
if(root==NULL)
return NULL;
if(root->_data==x)
return root;
Node* ret=_Find(root->_left,x);
if(ret)
return ret;
return _Find(root->_right,x);
}
protected:
Node* _root;
};
void TestBinaryTree()
{
int array[10]={1,2,3,'#','#',4,'#','#',5,6};
BinaryTree<int> t1(array,sizeof(array)/sizeof(array[0]),'#');
t1.PrevOrder();
BinaryTree<int> t2(t1);
t2.PrevOrderNonR();
t1.PrevOrderNonR();
t1.PostOrderNonR();
t1.InOrder();
t1.LevelOrder();
cout<<"Size:"<<t1.Size()<<endl;
cout<<"kLeavel:"<<t1.GetkLeavel(4)<<endl;
cout<<"LeafSize:"<<t1.LeafSize()<<endl;
cout<<"Depth:"<<t1.Depth()<<endl;
}
int main()
{
TestBinaryTree();
return 0;
}