樹形結構是元數據素(節點)之間有分支,並且具有層次關係的結構,可用於表示數據元素之間存在的一對多關係
一.樹的定義和術語
1.樹的定義
樹是由n(n>=0)個節點構成的有限集合,當n=0時稱爲空樹。若樹非空,則有以下兩個性質
(1)有且僅有一個特定的節點,此爲根(Root);
(2)其餘的節點可分爲m個互不相交的集合T1 ,T2, T3, ... ,Tm , 其中每一個集合是一棵樹,並且稱爲根的子樹
2.樹的基本術語
樹節點: 樹中一個獨立單元。
樹根: 樹中唯一沒有前驅的節點
節點的度: 節點擁有的子樹數
樹的度: 樹中各節點的度的最大值
樹葉: 度爲零的節點
樹的層次和深度: 從根算起,根爲第一層,根的孩子爲第二層,樹的任意節點的層次等於它的父節點的層次加一。
樹中各節點層次的最大值稱爲樹的深度
有序樹和無序數:如果樹中節點的各子樹從左到右是有此序的(即不能互換),則爲有序樹,否則爲無序;
森林: m(m>=0)顆互不相交的樹的集合。對樹中每個節點而言,其子樹的集合即爲森林
3.樹的表示
圖形表示法,凹入表示法,嵌套集合表示法, 廣義表表示法, 層號表示法
4.樹的遍歷
對樹中的所有節點進行訪問,且每個節點僅訪問一次,這就是樹的遍歷.
可把對節點的訪問看成打印節點的關鍵字,數據項,或節點編號,把遍歷看成是按序輸入節點表
1.樹的選根遍歷: 首先訪問根節點n, 其次依次按選根遍歷T1,按選根遍歷T2, ...
2.樹的後根遍歷: 選按後根遍歷n的所有子樹T1 , T2 , ..., Tm , 最後訪問根節點n
二. 二叉樹(Binary Tree)
二叉樹是度爲2的有序樹
1.二叉樹的定義
(1) 由n(n>=0)各節點所構成的集合,可以爲空
(2)二叉樹的根節點下可分爲兩個互不相交的子樹,子樹有左右之分,次序不能顛倒,稱爲左子樹和右子樹;
且左右子樹均爲二叉樹
2.二叉樹的性質
性質一: 在二叉樹的第i層上最多有2^(i-1) 個節點
性質二: 深度爲k的二叉樹最多有 2^(i) - 1 個節點
特別地,一顆深度爲k且有2^k - 1 個節點的二叉樹稱爲滿二叉樹;
完全二叉樹是將滿二叉樹從最後一層的最後的節點,依次拿掉節點,
3.二叉樹的存儲結構
1.鏈式存儲結構
/*二叉樹的二叉鏈表存儲結構*/
typedef struct BitNode{
int data;
struct BitNode *lchild, *rchild;
}BitNode,*BiTree;
4.遍歷二叉樹
void PreOrder(BiTree p)
{
if(p!=NULL)
{
printf("%d",p->data); //訪問根節點
PreOrder(p->lchild);
PreOrder(p->rchild);
}
}
void InOrder(BiTree p)
{
if(p!=NULL)
{
PreOrder(p->lchild);
printf("%d",p->data); //訪問根節點
PreOrder(p->rchild);
}
}
void PostOrder(BiTree p)
{
if(p!=NULL)
{
printf("%d",p->data); //訪問根節點
PreOrder(p->rchild);
PreOrder(p->lchild);
}
}
5.線索二叉樹
當結點的左指針爲空時(即無左子樹),令該指針指向按某種方式遍歷二叉樹時該結點的驅結點;
當結點的右指針爲空時,令該指針指向按某種遍歷二叉樹時該結點的後繼結點。爲了避免混淆,
可定義這種指向結點的前驅或後繼的指針信息爲線索
/**********二叉樹的二叉線索存儲表示***************************/
typedef struct BiThrNode
{
ElemType data;
struct BiThrNode *lchild ,*rchild; /*左右指針*/
int ltag,rtag; /*左右指針類型標誌,0表示指針,1表示線索*/
}
哈夫曼樹
哈夫曼樹是一種帶權路徑長度最小的樹
樹的路徑長度是從樹根到每一個結點的路徑長度之和.
樹的帶權路徑長度: 從樹根結點到該結點之間的路徑長度與該結點上權的乘積之和
WPL=wi*lI+...+...;
分支結點不帶權值,只有葉子結點才帶權值,權值越大的結點離樹根越近,則二叉樹的帶權路徑長度就越小