樹的基本概念:ios
樹是n(n>=0)個有限個數據的元素集合,形狀像一顆倒過來的樹。數組
結點:結點包含數據和指向其它結點的指針。ide
根節點:樹第一個結點稱爲根節點。函數
結點的度:結點擁有的子節點個數。this
葉節點:沒有子節點的節點(度爲0)。spa
父子節點:一個節點father指向另外一個節點child,則child爲孩子節點,father爲父親結點。3d
兄弟節點:具有相同父節點的節點互爲兄弟節點。指針
節點的祖先:從根節點開始到該節點所經的全部節點均可以稱爲該節點的祖先。orm
子孫:以某節點爲根的子樹中任一節點都稱爲該節點的子孫。blog
樹的高度:樹中距離根節點最遠結點的路徑長度。
二叉樹的概念:
二叉樹是一棵特殊的樹,二叉樹每一個節點最多有兩個孩子結點,分別稱爲左孩子和右孩子。
二叉樹的存儲方式:
(1)數組存儲方式 即用一組連續的存儲單元存儲二叉樹的數據元素。
例如:
(2)鏈式存儲方式
這裏咱們主要討論每一個結點包含三個域的狀況
二叉樹的結點的結構
template<class T>
struct BinaryTreeNode
{
BinaryTreeNode(const T& x) //構造函數
:_data(x)
,_left(NULL)
,_right(NULL)
{ }
T _data; //結點的值
BinaryTreeNode<T>* _left; //指向左子樹的結點
BinaryTreeNode<T>* _right; //指向右子樹的結點
};
部分代碼以下:
二叉樹的遍歷(前序、中序、後序、層次)
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);
}
void _PosOrder(Node* root) //後序遍歷打印二叉樹
{
if(root == NULL)
return;
_PosOrder(root->_left);
_PosOrder(root->_right);
cout<<root->_data<<" ";
}
void _LevelOrder(Node* root) //層次遍歷
{
queue<Node*> p;
if(root == NULL)
{
return;
}
p.push(root);
while (!p.empty())
{
if(p.front()->_left != NULL)
{
p.push(p.front()->_left);
}
if(p.front()->_right != NULL)
{
p.push(p.front()->_right);
}
cout<<p.front()->_data<<" ";
p.pop();
}
}
二叉樹中結點的個數
size_t _Size(Node* root) //求結點的個數
{
if(root == NULL)
return 0;
return _Size(root->_left) + _Size(root->_right) + 1;
}
二叉樹的深度
size_t _Depth(Node* root) //樹的深度
{
if(root == NULL)
return 0;
size_t leftdepth = _Depth(root->_left);
size_t rightdepth = _Depth(root->_right);
return leftdepth > rightdepth ? leftdepth + 1 : rightdepth + 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);
}
二叉樹的鏡像(即交換二叉樹每個結點的左右子結點)
void _MirrorRecursively(Node* root)//二叉樹的鏡像
{
//判斷根節點及左右子樹是否爲空
if(root == NULL || (root->_left == NULL && root->_right == NULL))
return;
Node* temp = root->_left; //交換左右子節點
root->_left = root->_right;
root->_right = temp;
if(root->_left != NULL)
_MirrorRecursively(root->_left);
if(root->_right != NULL)
_MirrorRecursively(root->_right);
}
判斷子樹問題
bool HasSubtree(Node* root2)//判斷root2是不是_root的子樹
{
bool result = false;
if(_root != NULL && root2 != NULL)
{
if(_root->_data == root2->_data)
{
result = DoseTree1HaveTree2(_root,root2);
}
if(!result)
result = HasSubtree(_root->_left,root2);
if(!result)
result = HasSubtree(_root->_right,root2);
}
return result;
}
bool DoseTree1HaveTree2(Node* root2)//判斷在tree1中是否有以tree2根節點的左右子樹結構
{
if(root2 == NULL)
return true;
if(_root == NULL)
return false;
if(_root->_data != root2->_data)
return false;
return DoseTree1HaveTree2(_root->_left,root2->_left) && DoseTree1HaveTree2(_root->_right,root2->_right);
}
以上只是部分代碼,具體源代碼以下:
#pragma once
#include<iostream>
#include<queue>
using namespace std;
//二叉樹中結點的結構
template<class T>
struct BinaryTreeNode
{
BinaryTreeNode(const T& x) //構造函數
:_data(x)
,_left(NULL)
,_right(NULL)
{ }
T _data; //結點的值
BinaryTreeNode<T>* _left; //指向左子樹的結點
BinaryTreeNode<T>* _right; //指向右子樹的結點
};
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;//簡化命名
public:
BinaryTree() //默認構造函數
:_root(NULL)
{ }
BinaryTree(const T* a,size_t size,const T& invalid) //構造函數
:_root(NULL)
{
size_t index = 0;
_root = _CreateTree(a,size,invalid,index); //建立一個二叉樹
}
BinaryTree(const BinaryTree<T>& t) //拷貝構造函數
:_root(NULL)
{
_Copy(t._root);
}
BinaryTree<T>& operator=(const BinaryTree<T>& t) //賦值函數
{
if(this != &t)
{
_Destroy(t._root);
_Copy(t._root);
}
return *this;
}
~BinaryTree() //析構函數
{
if(_root)
{
_Destroy(_root);
}
}
void PrevOrder() //前序遍歷打印二叉樹
{
cout<<"前序遍歷:";
_PrevOrder(_root);
cout<<endl;
}
void InOrder()//中序遍歷打印二叉樹
{
cout<<"中序遍歷:";
_InOrder(_root);
cout<<endl;
}
void PosOrder()//後續序遍歷打印二叉樹
{
cout<<"後序遍歷:";
_PosOrder(_root);
cout<<endl;
}
void LevelOrder() //層次遍歷
{
cout<<"層次遍歷:";
_LevelOrder(_root);
cout<<endl;
}
size_t Size() //求結點的個數
{
return _Size(_root);
}
size_t Depth()//樹的深度
{
return _Depth(_root);
}
size_t LeafSize() //葉子節點個數
{
return _LeafSize(_root);
}
bool HasSubtree(Node* root2)//判斷root2是不是_root的子樹
{
bool result = false;
if(_root != NULL && root2 != NULL)
{
if(_root->_data == root2->_data)
{
result = DoseTree1HaveTree2(_root,root2);
}
if(!result)
result = HasSubtree(_root->_left,root2);
if(!result)
result = HasSubtree(_root->_right,root2);
}
return result;
}
void MirrorRecursively()//二叉樹的鏡像
{
_MirrorRecursively(_root);
}
protected:
Node* _CreateTree(const T* a,size_t size,const T& invalid,size_t& index) //建立一個二叉樹
{
Node* root = NULL;
if(a[index] != invalid && index < size)
{
root = new Node(a[index]);
root->_left = _CreateTree(a,size,invalid,++index);
root->_right = _CreateTree(a,size,invalid,++index);
}
return root;
}
void _Copy(Node* sroot)//拷貝函數
{
Node* root = NULL;
if(sroot == nul) //判斷根節點
return;
if(sroot->_left && sroot->_right) //判斷根節點的左右子樹
{
root = new Node(sroot->_data);
return ;
}
root->_left = _Copy(sroot->_left);//依次拷貝左子樹
root->_right = _Copy(sroot->_right);//依次拷貝右子樹
}
void _Destroy(Node* root)//銷燬二叉樹
{
if(root == NULL)
{
return;
}
if(root->_left && root->_right)
{
delete root;
root = NULL;
return;
}
_Destroy(root->_left);
_Destroy(root->_right);
}
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);
}
void _PosOrder(Node* root) //後序遍歷打印二叉樹
{
if(root == NULL)
return;
_PosOrder(root->_left);
_PosOrder(root->_right);
cout<<root->_data<<" ";
}
void _LevelOrder(Node* root) //層次遍歷
{
queue<Node*> p;
if(root == NULL)
{
return;
}
p.push(root);
while (!p.empty())
{
if(p.front()->_left != NULL)
{
p.push(p.front()->_left);
}
if(p.front()->_right != NULL)
{
p.push(p.front()->_right);
}
cout<<p.front()->_data<<" ";
p.pop();
}
}
void _MirrorRecursively(Node* root)//二叉樹的鏡像
{
//判斷根節點及左右子樹是否爲空
if(root == NULL || (root->_left == NULL && root->_right == NULL))
return;
Node* temp = root->_left; //交換左右子節點
root->_left = root->_right;
root->_right = temp;
if(root->_left != NULL)
_MirrorRecursively(root->_left);
if(root->_right != NULL)
_MirrorRecursively(root->_right);
}
size_t _Size(Node* root) //求結點的個數
{
if(root == NULL)
return 0;
return _Size(root->_left) + _Size(root->_right) + 1;
}
size_t _Depth(Node* root) //樹的深度
{
if(root == NULL)
return 0;
size_t leftdepth = _Depth(root->_left);
size_t rightdepth = _Depth(root->_right);
return leftdepth > rightdepth ? leftdepth + 1 : rightdepth + 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);
}
bool DoseTree1HaveTree2(Node* root2)//判斷在tree1中是否有以tree2根節點的左右子樹結構
{
if(root2 == NULL)
return true;
if(_root == NULL)
return false;
if(_root->_data != root2->_data)
return false;
return DoseTree1HaveTree2(_root->_left,root2->_left) && DoseTree1HaveTree2(_root->_right,root2->_right);
}
protected:
Node* _root;//根節點
};
void Test()
{
int a1[10] = {1,2,3,'#','#',4,'#','#',5,6};
int a2[15] = {1,2,'#',3,'#','#',4,5,'#',6,'#',7,'#','#',8,};
int a3[5] = {2,3,'#','#',4};
BinaryTree<int> t1(a1,10,'#');
BinaryTree<int> t2(a2,15,'#');
BinaryTree<int> t3(a3,5,'#');
cout<<"t1遍歷二叉樹(前序,中序,後序,層次):"<<endl;
t1.PrevOrder();
t1.InOrder();
t1.PosOrder();
t1.LevelOrder();
cout<<"二叉樹結點的個數:"<<t1.Size()<<endl;
cout<<"二叉樹的深度:"<<t1.Depth()<<endl;
cout<<"二叉樹的葉子節點數:"<<t1.LeafSize()<<endl;
cout<<"二叉樹的鏡像:"<<endl;
t1.MirrorRecursively();
t1.PrevOrder();
cout<<endl;
cout<<"t2遍歷二叉樹(前序,中序,後序,層次):"<<endl;
t2.PrevOrder();
t2.InOrder();
t2.PosOrder();
t2.LevelOrder();
cout<<"二叉樹結點的個數:"<<t2.Size()<<endl;
cout<<"二叉樹的深度:"<<t2.Depth()<<endl;
cout<<"二叉樹的葉子節點數:"<<t2.LeafSize()<<endl;
cout<<"二叉樹的鏡像:"<<endl;
t2.MirrorRecursively();
t2.PrevOrder();
cout<<endl;
}