定義:有且只有一個被稱爲根的節點,由若干個互不相交的字數,這些字數本身也是一棵樹。
專業術語:節點 父節點 子節點
子孫 堂兄弟
深度:從根節點到最底層節點的層數 根節點是第一層
葉子節點:沒有子節點的節點
非終端節點:存在一個或多個子節點的節點
度:節點擁有的最大子節點的個數
樹的分類:一般樹 :任意一個節點的子節點的個數都不受限制
二叉樹 :任意一個節點的子節點的個數最多兩個,且子節點的位置不可更改
二叉樹分類:一般二叉樹 滿二叉樹(當一個k層的二叉樹存在2的k次方減1個節點時叫做滿二叉樹) 完全二叉樹(如果只是刪除了滿二叉樹最底層最右邊的連續若干個節點,這樣形成的二叉樹就是完全二叉樹)
森林 : n個互不相交的樹的集合
樹的存儲:
二叉樹的存儲
連續存儲【完全二叉樹 】
優點:查找某個節點的父節點和子節點速度快(也包括判斷是否存在子節點)
缺點:耗費內存空間過大
鏈式存儲
一般樹的存儲
雙親表示法 求父節點方便
孩子表示法 求子節點方便
雙親孩子表示法 兼顧雙親表示法與孩子表示法的優點
二叉樹表示法 把一個普通樹轉化爲二叉樹來存儲
具體轉換方式:左指針域指向它的第一個孩子
右指針域指向它的下一個堂兄弟
森林的存儲
除第一棵樹之外,其他樹的根節點作爲第一棵樹根節點的堂兄弟然後再根據上面的轉換方法進行轉換。
二叉樹操作
遍歷
先序遍歷
先訪問根節點 再先序訪問左子樹 再先序訪問右子樹
中序遍歷
中序遍歷左子樹 再訪問根節點 再中序遍歷右子樹
後序遍歷
後序遍歷左子樹 再後序遍歷右子樹 再訪問根節點
已知兩種遍歷序列求原始二叉樹
通過先序和中序 或者 中序和後序可以還原出原始的二叉樹
但是先序和後序這種組合是無法還原出原始的二叉樹的
樹的應用
樹是數據庫中數據組織的一種重要形式
操作系統子進程與父進程的關係本身就是一棵樹
面嚮對象語言中類的繼承關係
赫夫曼樹
代碼區
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<queue>
typedefstruct BTNode
{
char data;
structBTNode *pLchild; //左孩子
structBTNode *pRchild; //右孩子
} *Tree;
//動態創建一棵樹
Tree CreateBTree(Tree &root)
{
char data;
std::cout<<"請輸入節點內容:"<<std::endl;
std::cin>>data;
if(data =='#')
{
root = NULL;
}
else
{
root = (Tree)malloc(sizeof(BTNode));
root->data = data;
CreateBTree(root->pLchild);
CreateBTree(root->pRchild);
}
return root;
}
//先序遍歷一棵樹
void PreTraverseBTree(Tree pT)
{
if(pT !=NULL)
{
std::cout<<pT->data<<" "; //先輸出根節點
if(pT->pLchild !=NULL)
{
PreTraverseBTree(pT->pLchild); //再先序遍歷左子樹
}
if(pT->pRchild !=NULL)
{
PreTraverseBTree(pT->pRchild); //再先序遍歷右子樹
}
}
}
//中序遍歷一棵樹
void InTraverseBTree(Tree pT)
{
if(pT !=NULL)
{
if(pT->pLchild !=NULL)
{
InTraverseBTree(pT->pLchild);
}
std::cout<<pT->data<<" ";
if(pT->pRchild !=NULL)
{
InTraverseBTree(pT->pRchild);
}
}
}
//後序遍歷一棵樹
void PostTraverseBTree(Tree pT)
{
if(pT !=NULL)
{
if(pT->pLchild !=NULL)
{
PostTraverseBTree(pT->pLchild);
}
if(pT->pRchild !=NULL)
{
PostTraverseBTree(pT->pRchild);
}
std::cout<<pT->data<<" ";
}
}
//深度優先遍歷
void depthFirstSearch(Tree root){
std::stack<Tree> nodeStack; //使用C++的STL標準模板庫
nodeStack.push(root);
Tree node;
while(!nodeStack.empty()){
node = nodeStack.top();
std::cout<<node->data<<" "; //遍歷根結點
nodeStack.pop();
if(node->pRchild){
nodeStack.push(node->pLchild); //先將右子樹壓棧
}
if(node->pLchild){
nodeStack.push(node->pLchild); //再將左子樹壓棧
}
}
}
//廣度優先遍歷
voidbreadthFirstSearch(Tree root)
{
std::queue<Tree> nodeQueue; //使用C++的STL標準模板庫
nodeQueue.push(root);
Tree node;
while(!nodeQueue.empty()){
node = nodeQueue.front();
nodeQueue.pop();
std::cout<<node->data<<" ";
if(node->pLchild){
nodeQueue.push(node->pLchild); //先將左子樹入隊
}
if(node->pRchild){
nodeQueue.push(node->pRchild); //再將右子樹入隊
}
}
}
int main()
{
Tree pT;
CreateBTree(pT);
std::cout<<"先序遍歷:"<<std::endl;
PreTraverseBTree(pT);
std::cout<<std::endl;
std::cout<<"中序遍歷:"<<std::endl;
InTraverseBTree(pT);
std::cout<<std::endl;
std::cout<<"後序遍歷:"<<std::endl;
PostTraverseBTree(pT);
std::cout<<std::endl;
std::cout<<"深度優先遍歷:"<<std::endl;
depthFirstSearch(pT);
std::cout<<std::endl;
std::cout<<"廣度優先遍歷:"<<std::endl;
breadthFirstSearch(pT);
std::cout<<std::endl;
return0;
}