首先是關於樹,二叉樹,完全二叉樹的一些知識
一、樹
(一)、基本概念
1. 度:一個節點的子樹的個數
2. 葉子節點:度為零的節點
3. 內部節點:度不為零的節點
4. 節點的層次,從根開始為第一層,之后的每個孩子節點為第i層
二、二叉樹
(一)、基本性質
1.二叉樹的第i層 多有 2^(i-1) 個節點
2.高度為k的二叉樹最多有2^k - 1 個節點
3.對於任意的二叉樹 若其終端節點(葉子節點)為n0 度為2的節點個數為 n2 則有 n0 = n2 + 1
4.對於具有n個節點的完全二叉樹 深度為log(2)n 向下取整再加 1
三、完全二叉樹
完全二叉樹使用順序儲存將極大的節省空間
我們設節點的編號為i,節點的個數為n (1<= i <=n)
1. 若節點標號為 i = 0 則該節點為根節點;若 i>1 則該節點的雙親節點為i/2向下取整有,等價於雙親節點的編碼在1~n/2之間
2. 若 2*i <= n,則該節點的左孩子編號為2i,否則該節點沒有左孩子。
2. 若 2*i +1 <= n, 則該節點的右孩子編號為2*i+1,否則該節點沒有右孩子。
四、創建順序存儲結構的完全二叉樹
順序存儲結構的完全二叉樹結構簡單且節省空間 ,而一般二叉樹不適用於順序結構儲存
1 . 我們分析 完全二叉樹的編號規則,對於編碼是1~n 的 方式很容易實現,但是在順序存儲中(數組下標索引)是以0~n-1來編碼的。需要一些特殊的方法來實現。
2 . 對於第一個節點,它的編碼應該是0,那么它的 左右孩子節點分別應該是 1,2 但是如果按照2*i ,2*i+1的計算方式則是0,1。 明顯的他不能是自己的左孩子。
3 . 對於0開始的編碼,節點序號為i 他的左右子節點應該是 2*i+1, 2*i+2, 而它的雙親節點編碼應該是 1~ n/2-1。
4 . 對於判斷是否為左右孩子節點的公式嗎,因為我們從 1~n 的排序變為了 0~n-1 所以我們的判斷條件也變成了2*i+1<=n-1,2*i+2<=n-1。
圖解:

創建一個Struct
typedef struct BiTnode{ int data; struct BiTnode *lchild, *rchild; }BiTnode,*BiTree;
我們 malloc 一片連續的大小為BiTnode*n的空間 然后使用數組下標索引先將值賦予這些值 之后在將每個節點的左右孩子通過上面所得到的公式進行連接,
#include <stdio.h> #include <stdlib.h> typedef struct BiTnode{ int data; struct BiTnode *lchild, *rchild; }BiTnode,*BiTree; /*根據數組生成完全二叉樹*/ void Init(int data[], BiTree *T,int n){ int i; /*分配一片連續的空間,我們可以通過訪問下標來訪問在這片空間*/ *T = (BiTree)malloc(sizeof(BiTnode)*n); for(i=0;i<n;i++){ /*給這片連續的空間賦值,將數組的值存入,應為我們使用的順序儲存*/ (*T)[i].data = data[i]; (*T)[i].lchild = NULL; (*T)[i].rchild = NULL; } /*為雙親節點確定子節點 n/2 是雙親節點的個數(序號)限定*/ for(i=0;i<=(n/2)-1;i++){ if(2*i+2<=n){ (*T)[i].lchild = &((*T)[2*i+1]); } if(2*i+3<= n){ (*T)[i].rchild = &((*T)[2*i+2]); } } } int main(){ BiTree T; int data[] = {1,2,3,4,5,6}; Init(data,&T,6); return 0; }
通過內存查看 我們確定了創建成功