1.樹在本質上其實就是不包含迴路的連通無向圖;
java
2.關於樹的一些特色:
(1).任意兩個結點有且只有惟一的一條路徑鏈接;
(2).n個結點,那麼恰好n-1條邊;
(3).在一棵樹中加一條邊將會構成一個迴路;
3.根:一棵樹有且只有一個根結點,好比上圖中的數值爲1的點就是根結點;
子結點:上圖中除了1其他都是子結點,沒有父結點的結點是根結點(祖先);
葉結點:沒有子結點的結點就是葉結點,如上圖的3.4.5
其他既不是根結點又不是葉結點的叫作內部結點,如上圖的2;
最後每一個結點是有深度的,好比3號節點的深度(從根結點到這一層的層數)是2;數組
1.定義:每一個結點最多有兩個兒子,分別是左兒子、右兒子;遞歸定義:二叉樹要麼爲空,要麼由根結點、左子樹、右子樹組成;二叉樹又分爲滿二叉樹和徹底二叉樹;
2.滿二叉樹:每一個內部結點都有兩個兒子,也就是全部的葉結點都有相同的深度;
3d
3.滿二叉樹深度與結點的關係:假如深度爲n,那麼結點2n-1;第n層上,結點爲2(n-1);
4.徹底二叉樹:除了最右邊位置上有一個或者幾個葉結點缺乏外,其他都是豐滿的
code
(1).對於徹底二叉樹:咱們能夠用一個一維數組來存儲它,從根結點開始
blog
(2).若是給父結點編號爲k,那麼他的左兒子就是2k,右兒子2k+1;
(3).若是一棵二叉樹有N個結點,那麼這個徹底二叉樹的高度爲log2N(2)爲底;
徹底二叉樹的最典型應用就是——堆;排序
import java.util.Scanner; public class D堆排序 { static Scanner in=new Scanner(System.in); static int n;static int num=in.nextInt(); static int []h=new int [num+1]; public static void swap(int x,int y) { int t; t=h[x]; h[x]=h[y]; h[y]=t; return; } public static void siftdown(int i) { int t,flag=0; while(i*2<=n&&flag==0) { if(h[i]>h[i*2]) { t=i*2; } else t=i; if(i*2+1<=n) { if(h[t]>h[i*2+1]) t=i*2+1; } if(t!=i) { swap(t,i); //i=t; } else flag=1; } return; } public static void creat() { int i; for(i=n/2;i>=1;i--) { //從最後一個非葉結點到第一個結點依次進行向下調整 siftdown(i); } return; } public static int deletemax() { int t; t=h[1]; h[1]=h[n]; n--; siftdown(1); return t; } public static void main(String[] args) { // TODO Auto-generated method stub int i=0; for(i=1;i<=num;i++) { h[i]=in.nextInt(); } n=num; creat();//建堆 for(i=1;i<=num;i++) { System.out.print(deletemax()+" "); } } }
1.建立堆(最小堆)遞歸
public static void creat() { int i; for(i=n/2;i>=1;i--) { //從最後一個非葉結點到第一個結點依次進行向下調整 siftdown(i); } return; }
爲何是從n/2開始呢?由於全部的葉結點都沒有兒子,天然而然葉結點都符合最小堆的特色,因此這裏就再也不須要考慮葉結點,直接從最後一個非葉結點開始起進行調整,一直到第一個結點。class
2.在建立堆的過程當中,對全部的子樹進行調整,當全部的子樹知足條件時,整棵樹就必定知足了條件。import
3.採用刪除最大元素的方式來輸出二叉樹
public static int deletemax() { int t; t=h[1]; h[1]=h[n]; n--; siftdown(1); return t; }
將堆頂的元素返回輸出,而後將最大的元素放到堆頂再進行調整,n--,直到爲空。