基於ADT構建完全二叉樹-資料結構
阿新 • • 發佈:2020-11-27
一、完全二叉樹介紹
對於一棵樹高為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實現)
<實現思想>
- 根據節點數量得到樹的高度h
- 構建空樹,將樹0 ~(h-1)層完全充滿,將最後一層由左向右構建,直到節點數等於n
- 得到空完全二叉樹
- 可以對樹進行前序/中序/後序/層次遍歷,填充節點數值
構造完全二叉樹-遞迴
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;
}