1. 程式人生 > >軟考:資料結構基礎——建立順序完全二叉樹

軟考:資料結構基礎——建立順序完全二叉樹

  首先是關於樹,二叉樹,完全二叉樹的一些知識

一、樹     (一)、基本概念            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;
}

  

  通過記憶體檢視 我們確定了建立成功