樹是一種非線性的數據結構,樹有根節點,子樹等概念。
二叉樹(Binary Tree):每個節點最多有兩顆子樹,並且子樹有左右之分。
概念:樹的深度,滿二叉樹,完全二叉樹,樹的節點樹
二叉樹包括順序存儲和鏈式存儲,這里只說鏈式存儲。二叉樹的每個節點和雙鏈表有些類似,但是樹的結構要比雙鏈表復雜,在構造樹的過程中涉及到遞歸調用的問題,遞歸的問題往往是很復雜的問題,因此,這里單獨說二叉樹的構建。
國際慣例,先上代碼:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<malloc.h> 4 5 //定義二叉樹 6 typedef struct node{ 7 int data;//數據元素 8 struct node *left;//指向左子樹 9 struct node *right;//指向右子樹 10 }BTree; 11 12 //構造二叉樹 13 int BTreeCreate(BTree **tp) 14 { 15 //構造方法,或者說構造順序:從左子樹開始構造 16 int x; 17 scanf("%d",&x); 18 if(x<0) 19 { 20 *tp=NULL;//指針為空,樹節點中的某個指針為空 21 return 0; 22 } 23 *tp=(BTree*)malloc(sizeof(BTree));//將樹節點中指針指向該地址空間 24 if(tp==NULL) 25 return 0; 26 (*tp)->data=x; 27 BTreeCreate(&((*tp)->left)); 28 BTreeCreate(&((*tp)->right)); 29 return 1; 30 } 31 32 int main() 33 { 34 BTree *tree; 35 printf("Create binary tree:\n"); 36 BTreeCreate(&tree); 37 38 return 0; 39 }
代碼看似比較簡單,核心就是BTreeCreate函數,該函數完成二叉樹的構建,根據函數定義,只有輸入正整數時才會新建節點。
二叉樹的構建過程如下:
先創建某一子樹的左子樹,如果左子樹不存在(輸入負數時),則創建其右子樹,如果左子樹存在,再創建該樹的左子樹,依次循環。需要注意的是,當某一子樹左子樹不存在則判斷其右子樹,右子樹不存在則返回其父節點再判斷右子樹。
特別要注意的是,一旦一個節點創建成功,則它的左子樹和右子樹都要判斷,不論它們存不存在,因為此BTreeCreate調用,輸入正整數,即節點創建成功后,都會去創建的left和right。
示例:就上面的程序,在第38行設置斷點,依次輸入1,2,-1,3,-1,-2,-3,tree指針的存儲結構如下(也就是樹的存儲結構)
根據輸入的數據,可以划出如下樹的結構圖:
對比上面的內存存儲情況,可以看得很明白,藍色的圈圈就是真正的樹節點。樹的構建過程如下:
輸入1,創建主節點,接下來創建1的左子樹,創建1右子樹的函數等待,設函數入口地址為ad1
輸入2,主節點1的左子樹創建成功,接下來創建2的左子樹,創建2右子樹的函數等待,設函數入口地址為ad2
輸入-1,節點2的左子樹創建失敗,返回執行等待的的函數(離當前最近的),即ad2,創建節點2的右子樹
輸入3,節點2的右子樹創建成功,接下來創建節點3的左子樹,創建3右子樹的函數等待,函數入口地址ad2
。。。。。。
直到函數遞歸調用完畢,沒有等待的函數為止。
下面創建一個完全二叉樹驗證結果,樹的結構圖下:
輸入:1,2,4,-1,-2,5,-3,-4,3,-5,-6,樹的內存存儲如下: