【經常使用數據結構——二叉樹(還有三叉四叉...? )】

---恢復內容開始---c++

簡介

  在計算機科學中,二叉樹是每一個結點最多有兩個子樹的有序樹。一般子樹的根被稱做「左子樹」(left subtree)和「右子樹」(right subtree)。二叉樹常被用做二叉查找樹和二叉堆或是二叉排序樹。spa

基本術語 

  1. 子樹:除了根節點外,每一個子節點均可以分爲多個不相交的子樹。
  2. 孩子與雙親:若一個結點有子樹,那麼該結點稱爲子樹根的"雙親",子樹的根是該結點的"孩子"。
  3. 兄弟:具備相同雙親的節點互爲兄弟。
  4. 節點的度:一個節點擁有子樹的數目。
  5. 葉子:沒有子樹,也便是度爲0的節點。
  6. 分支節點:除了葉子節點以外的節點,也便是度不爲0的節點。
  7. 內部節點:除了根節點以外的分支節點。
  8. 層次:根節點爲第一層,其他節點的層次等於其雙親節點的層次加1.
  9. 樹的高度:也稱爲樹的深度,樹中節點的最大層次。
  10. 有序樹:樹中節點各子樹之間的次序是重要的,不能夠隨意交換位置。
  11. 無序樹:樹種節點各子樹之間的次序是不重要的。能夠隨意交換位置。
  12. 森林:0或多棵互不相交的樹的集合。

基本形態

也就五種,從左往右分別是空樹,只有根節點的樹,根節點和左兒子,根節點和右孩子,根節點和左右孩子。3d

基本性質

1.二叉樹第i層上的結點數目最多爲2i-1(i>=1)code

2.深度爲k的二叉樹至多有2k-1個結點(k>=1)blog

3.包含n個結點的二叉樹的高度至少爲(log2n)+1排序

4.在任意二叉樹中,若度爲0的個數爲n0,度爲2的結點數爲n2,則n0=n2+1遞歸

5.若是對一棵有n個節點的徹底二叉樹的節點按層序編號(從第一層開始到最下一層,每一層從左到右編號),對任一節點i有:ci

  1. 若是i=1 ,則節點爲根節點,沒有雙親。
  2. 若是2*i > n ,則節點i沒有左孩子 ;不然其左孩子節點爲2*i (n爲節點總數)
  3. 若是2*i+1>n ,則節點i沒有右孩子;不然其右孩子節點爲2*1+1

滿二叉樹

  就像它的名字同樣,它是滿的(廢話)get

  滿二叉樹是指一個高度爲n的樹有2^(n-1)個結點(其實就是每一個點都有兩個孩子,除了最後一層的單身狗)string

 

徹底二叉樹

  徹底二叉樹是指一顆二叉樹的葉子結點只在最後兩層,而且最後一層的葉子結點都集中在左邊。顯然,滿二叉樹也是一顆徹底二叉樹。

遍歷二叉樹

  對於二叉樹的遍歷,咱們分爲三種狀況:

一,前序遍歷       根結點->左子樹->右子樹

如下順序就是124583796

1 void work(int x)
2 {
3     if(!x)return;//若是這個點有效 
4     printf("%d ",x);//
5     work(l[x]);//左子樹 
6     work(r[x]);//右子樹 
7 }

 

 

二,中序遍歷       左子樹->根結點->右子樹

如下順序就是428519736

 

1 void work(int x)
2 {
3     if(!x)return;//若是這個點有效 
4     work(l[x]);//左子樹 
5     printf("%d ",x);//
6     work(r[x]);//右子樹 
7 }

 

三,後序遍歷      右子樹 ->左子樹->根結點

如下順序就是485297631

 

void work(int x)
{
    if(!x)return;//若是這個點有效 
    work(r[x]);//右子樹 
    work(l[x]);//左子樹 
    printf("%d ",x);//
}        

 然而它們之間有神奇的關係

中、後序求先序

P1030 求先序排列

 

圖中粉色的表示這一個序分紅了根,左,右三部分(也可能沒有左或右)

首先,你要知道,後序的最後一個確定是根結點,而後你要知道,在一串中序中,找到了它的根結點,那麼它左邊就是左子樹,右邊就是右子樹。

咱們先找到根結點A,而後把中序分爲FDBE和CHG左右子樹,而左子樹的後序就是FDEB,右子樹的後序就是HGC,而後一步一步分解下去,知道不能分解,由於咱們求先序,因此先輸出根結點,而後分別遞歸左、右子樹。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 void beford(string s2,string s3)//中序and後序 
 4 {
 5     if(s2.size()==0)return;
 6     char root=s3[s3.size()-1];//找到根結點 
 7     cout<<root; //輸出根結點 
 8     int k=s2.find(root);
 9     beford(s2.substr(0,k),s3.substr(0,k));//左子樹 
10     beford(s2.substr(k+1),s3.substr(k,s2.size()-k-1));//右子樹 
11 }
12 int main()
13 {
14     string s2,s3;//1,2,3分別對應前,中,後 
15     cin>>s2>>s3; 
16     beford(s2,s3);
17  } 

中、先序求後序

與上面同理,只須要稍微改動一點便可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 void beford(string s1,string s2)//先序and中序 
 4 {
 5     if(s1.size()==0)return;
 6     char root=s1[0];//找到根結點 
 7     int k=s2.find(root);
 8     beford(s1.substr(1,k),s2.substr(0,k));//左子樹 
 9     beford(s1.substr(k+1),s2.substr(k+1));//右子樹 
10     cout<<root; //輸出根結點 
11 }
12 int main()
13 {
14     string s1,s2;//1,2,3分別對應前,中,後 
15     cin>>s1>>s2; 
16     beford(s1,s2);
17 } 
相關文章
相關標籤/搜索