1. 程式人生 > 實用技巧 >基於ADT構建完全二叉樹-資料結構

基於ADT構建完全二叉樹-資料結構

一、完全二叉樹介紹

對於一棵樹高為h的二叉樹,若其第0層至第h-1層的節點都滿,且最下一層所有的節點在左邊連續排列,空位在右。這樣的二叉樹就是一棵完全二叉樹。

由完全二叉樹特性可知,可以依據節點數量構建空完全二叉樹。

二、完全二叉樹的構建(c++)

1. 方法一 (陣列儲存)

<實現思想>

設由n個節點,結點編號由0到n。
如果i=0,為根節點,如果i>0,則對應雙親的序號為[(i-1)/2] (其中[x]表示不超過x的最大整數)
如果2i+1>n,則該結點無左孩子;
如果2i+2>n,則該結點無右孩子;
由此,可以從根節點開始,進行遞迴,得到完全二叉樹。

<遞迴部分>

void create_completetree(int* arr, int n, Node* node, int index)
//arr預存陣列,node樹節點,index序號 
{  
	if (2 * index + 1 < n)
	{
		Node* left_child = new Node(arr[2 * index + 1]);
		node->left = left_child;
		create_completetree(arr, n , left_child , 2 * index + 1);
	}
	if (2 * index + 2 < n)
	{
		Node* right_child = new Node(arr[2 * index + 2]);
		node->right = right_child;
		create_completetree(arr, n, right_child, 2 * index + 2);
	}
}  

2. 方法二(基於二叉樹ADT實現)

<實現思想>

  1. 根據節點數量得到樹的高度h
  2. 構建空樹,將樹0 ~(h-1)層完全充滿,將最後一層由左向右構建,直到節點數等於n
  3. 得到空完全二叉樹
  4. 可以對樹進行前序/中序/後序/層次遍歷,填充節點數值

構造完全二叉樹-遞迴

BinNode<int>* set_node(int level){              //根據層數構建
    BinNode<int>* node = new BinNode<int>;       //BinNode為樹節點類
    node->setValue(0);                          //初始化0
	if(level < height){
        if(level < height-1 || mod < num-pow(2,(height-1))+1)      //左孩子,mod用於計數目前最下層節點個數
            node->setLeft(set_node(level+1));
        if(level < height-1 || mod < num-pow(2,(height-1))+1)      //右孩子
            node->setRight(set_node(level+1));
	}
	else mod++;

    return node;
}

例項
下面展示基於一個輸入序列,構建一棵完全二叉樹,且二叉樹符合BST(二叉搜尋樹)。
注:二叉搜尋樹(左孩子節點值<根節點值<右孩子節點值),特點為中序遍歷時,輸出序列為遞增序列。

主程式程式碼(不包括樹ADT部分)

#include "Binary_ADT.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

vector<int> a;                                //a 輸入序列
int num;
int height;
int cnt=0,mod=0;                              //計數

void getheight(int n) {                       //獲得完全二叉樹高度
	int temp=0;
	for(int i=0;;i++){
		temp += pow(2,i);
		if(temp>=n)
		{
			height=i+1;
			break;
		}
	}
}

BinNode<int>* set_node(int level){  
    BinNode<int>* node = new BinNode<int>;
    node->setValue(0);
	if(level!=height){
        if(level<height-1 || mod<num-pow(2,(height-1))+1)
            node->setLeft(set_node(level+1));
        if(level<height-1 || mod<num-pow(2,(height-1))+1)
            node->setRight(set_node(level+1));
	}
	else mod++;

    return node;
}

void inOrder(BinNode<int>* node)            //中序遍歷,對節點進行賦值
{
    if(node->left()!=NULL)
        inOrder(node->left());
    node->setValue(a[cnt]);
    cnt++;
    if(node->right()!=NULL)
        inOrder(node->right());
}

void createtree(BinTree<int> *bst){
    bst->setRoot(set_node(1));                         //構造
    inOrder(bst->getRoot());                           //賦值
}

void levelordervisit(BinNode<int>* tmp)                //層次遍歷
{
    if (tmp == NULL)
        return;
    queue<BinNode<int>*> que;
    que.push(tmp);
    BinNode<int>* curr;
    while(!que.empty())
    {
        curr = que.front();
        if (curr->left() != NULL)
            que.push(curr->left());
        if (curr->right() != NULL)
            que.push(curr->right());
        que.pop();
        cout<<curr->getValue()<<" ";
    }
}

int main()
{
    int temp;
    cin>>num;
    for(int i=0 ; i<num ; i++){
        cin>>temp;
        a.push_back(temp);
    }
    sort(a.begin(),a.end());                   //得到遞增序列

    getheight(num);
    BinTree<int> *bst = new BinTree<int>gt;       //構造樹

    createtree(bst);

    levelordervisit(bst->getRoot());           //層次遍歷輸出

    return 0;
}