標籤:style blog http color os strong 資料 for
樹是一類重要的非線性資料結構,是以分支關係定義的階層
定義:樹(tree)是n(n>=0)個結點的有限集T,其中:
n=0時為空白樹
n>0時,有且僅有一個特定的結點,稱為樹的根(root)
當n>1時,其餘結點可分為m(m>0)個互不相交的有限集T1,T2,……Tm,
其中每一個集合本身又是一棵樹,稱為根的子樹(subtree)
特點:
非空樹中至少有一個結點——根
樹中各子樹是互不相交的集合
基本概念:
結點(node)——表示樹中的元素,包括資料項目及若干指向其子樹的分支
結點的度(degree)——結點擁有的子樹數
葉子(leaf)——度為0的結點
孩子(child)——結點子樹的根稱為該結點的孩子
雙親(parents)——孩子結點的上層結點叫該結點的~
兄弟(sibling)——同一雙親的孩子
樹的度——一棵樹中最大的結點度數
結點的層次(level)——從根結點算起,根為第一層,它的孩子為第二層……
深度(depth)——樹中結點的最大層次數
森林(forest)——m(m>=0)棵互不相交的樹的集合
二叉樹
定義:二叉樹是n(n>=0)個結點的有限集,它或為空白樹(n=0),或由一個根結點和兩棵分別稱為
左子樹和右子樹的互不相交的樹構成
特點:
每個結點至多有二棵子樹(即不存在度大於2的結點)
二叉樹的子樹有左、右之分,且其次序不能任意顛倒
性質:1.在二叉樹的第i層至多有 2i-1 個結點(i>=1)
2.深度為k的二叉樹至多有 2k-1 個結點(k>=1)
3.對任何一棵二叉樹T,如果其終端結點數為n0,度為2的結點數為n2,則n0=n2+1
證明:n1為二叉樹T中度為1的結點數
因為:二叉樹中所有結點的度均小於或等於2
所以:其結點總數n=n0+n1+n2
又二叉樹中,除根結點外,其餘結點都只有一個分支進入
設B為分支總數,則n=B+1
又:分支由度為1和度為2的結點射出,即 B=n1+2n2
於是,n=B+1=n1+2n2+1=n0+n1+n2
即:n0=n2+1
滿二叉樹
定義:一個深度為k,且有2k-1個結點的二叉樹
完全二叉樹
定義:深度為k,有n個結點的二叉樹若且唯若其每一個結點都
與深度為k的滿二叉樹中編號從1至n的結點一一對應
特點:
葉子結點只可能在層次最大的兩層上出現
對任一結點,若其右分支下子孫的最大層次為i,則其左分支下子孫的最大層次必為i或i+1
性質:4.具有k個結點的完全二叉樹,深度為(log2k)向下取整再加一
性質:5.如果對一棵有n個結點的完全二叉樹的結點按層序編號,則對任一結點i(1<=i<=n),有:
(1) 如果i=1,則結點i是二叉樹的根,無雙親;如果i>1,則其雙親是i/2
(2) 如果2i>n,則結點i無左孩子;如果2i<=n,則其左孩子是2i
(3) 如果2i+1>n,則結點i無右孩子;如果2i+1<=n,則其右孩子是2i+1
二叉樹的遍曆
方法
先序遍曆:先訪問根結點,然後分別先序遍曆左子樹、右子樹
中序遍曆:先中序遍曆左子樹,然後訪問根結點,最後中序遍曆右子樹
後序遍曆:先後序遍曆左、右子樹,然後訪問根結點
按層次遍曆:從上到下、從左至右訪問各結點
參考代碼:
void printq(Tree *T) { if(T!=NULL){ printf("%c",T->c); printq(T->l); printq(T->r); }}先序遍曆輸出
void printz(Tree *T) { if(T!=NULL){ printz(T->l); printf("%c",T->c); printz(T->r); }}中序遍曆輸出
void printh(Tree *T) { if(T!=NULL){ printh(T->l); printh(T->r); printf("%c",T->c); }}後序遍曆輸出
void ccbl(Tree *T) { q.push(T); while(!q.empty()){ T=q.front(); q.pop(); printf("%c",T->c); if(T->l!=NULL) q.push(T->l); if(T->r!=NULL) q.push(T->r); }}層次遍曆輸出