二叉樹的實現與分析(源碼及解析)
回顧一下,二叉樹的結點由一個資料成員和兩個指向其子結點的指標組成。
結構體BiTreeNode代表二叉樹中的一個單獨的結點,這個結構體由上述的3個成員組成。
結構體BiTree代表二叉樹這種資料結構。這個結構體包含4個成員:size表示樹中的結點的個數,compare成員在二叉樹中暫時不會用到,而是等到其他資料類型繼承二叉樹時才會派上用場。destroy作為參數傳遞給bitree_init函數。最後,root是一個指向結點層次體系中最高點的指標,也就是指向根結點的指標。
樣本1:二叉樹抽象資料類型的標頭檔
/*bitree.h*/
#ifndef BITREE_H
#define BITREE_H
#include <stdlib.h>
/*定義二叉樹結點結構體*/
typedef struct BiTreeNode_
{
void *data;
struct BiTreeNode_ *left;
struct BiTreeNode_ *right;
}BiTreeNode;
/*定義二叉樹結構體*/
typedef struct BiTree_
{
int size;
int (*compare)(const void *key1,const void *key2);
void (*destroy)(void *data);
BiTreeNode *root;
}BiTree;
/*公用介面部分*/
void bitree_init(BiTree *tree,void (*destroy)(void *data));
void bitree_destroy(BiTree *tree);
int bitree_ins_left(BiTree *tree,BiTreeNode *node,const void *data);
int bitree_ins_right(BiTree *tree,BiTreeNode *node,const void *data);
void bitree_rem_left(BiTree *tree,BiTreeNode *node);
void bitree_rem_right(BiTree *tree,BiTreeNode *node);
int bitree_merge(BiTree *merge,BiTree *left,BiTree *right,const void *data);
#define bitree_size(tree)((tree)->size)
#define bitree_root(tree)((tree)->root)
#define bitree_is_eob(node)((node) == NULL)
#define bitree_is_leaf(node)((node)->left == NULL && (node)->right == NULL)
#define bitree_data(node)((node)->data)
#define bitree_left(node)((node)->left)
#define bitree_right(node)((node)->right)
#endif // BITREE_H
樣本2:二叉樹抽象資料類型的實現
#include <stdlib.h>
#include <string.h>
#include "bitree.h"
/*bitree_init 初始化二叉樹*/
void bitree_init(BiTree *tree,void (*destroy)(void *data))
{
tree->size = 0;
tree->destroy = destroy;
tree->root = NULL;
return ;
}
/*bitree_destroy 銷毀二叉樹*/
void bitree_destroy(BiTree *tree)
{
/*移除樹中的所有結點*/
bitree_rem_left(tree,NULL);
/*不再允許其他動作,清除樹結構*/
memset(tree,0,sizeof(BiTree));
return ;
}
/*bitree_ins_left 插入左子結點*/
int bitree_ins_left(BiTree *tree,BiTreeNode *node,const void *data)
{
BiTreeNode *new_node,**position;
/*決定在何處插入結點*/
if(node == NULL)
{
/*允許只在空樹中插入根結點*/
if(bitree_size(tree)>0)
return -1;
position = &tree->root;
}
else
{
/*通常只允許在一個分支的末端進行插入*/
if(bitree_left(node) != NULL)
return -1;
position = &node->left;
}
/*為結點分配空間*/
if((new_node = (BiTreeNode*)malloc(sizeof(BiTreeNode)))==NULL)
return -1;
new_node->data = (void*)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node;
tree->size++;
return 0;
}
/*bitree_ins_right 插入右結點*/
int bitree_ins_right(BiTree *tree,BiTreeNode *node,void *data)
{
BiTreeNode *new_node, **position;
/*決定將結點插入哪一位置*/
if(node == NULL)
{
/*僅允許在空樹中插入根結點*/
if(bitree_size(tree)>0)
return -1;
position = &tree->root;
}
else
{
/*通常只允許在一個分支的末端進入插入*/
if(bitree_right(node)!=NULL)
return -1;
position = &node->right;
}
/*為結點分配空間*/
if((new_node = (BiTreeNode*)malloc(sizeof(BiTreeNode)))==NULL)
return -1;
/*將結點插入樹中*/
new_node->data = (void*)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node;
tree->size++;
return 0;
}
/*bitree_rem_left 移除以指定結點的左子結點為根的子樹*/
void bitree_rem_left(BiTree *tree,BiTreeNode *node)
{
BiTreeNode **position;
/*從一顆空樹中移除節點是不被允許的*/
if(bitree_size == 0)
return;
/*決定從何處移除分支*/
if(node == NULL)
position = &tree->root;
else
position = &node->left;
/*按後序遍曆的順序移除分支*/
if(*position != NULL)
{
bitree_rem_left(tree,*position);
bitree_rem_right(tree,*position);
if(tree->destroy != NULL)
{
/*調用自訂的解構函式釋放動態空間*/
tree->destroy((*position)->data);
}
free(*position);
*position = NULL;
tree->size--;
}
return;
}
/*bitree_rem_left 移除以指定結點的右子結點為根的子樹*/
void betree_rem_right(BiTree *tree,BiTreeNode *node)
{
BiTreeNode **position;
if(bitree_size(tree) == 0)
return ;
if(node == NULL)
position = &tree->root;
else
position = &node->right;
if(position != NULL)
{
bitree_rem_left(tree,*position);
bitree_rem_right(tree,*position);
if(tree->destroy != NULL)
{
tree->destroy((*position)->data);
}
free(*position);
*position = NULL;
tree->size--;
}
return ;
}
/*bitree_merge 將兩顆二叉樹合并為單顆二叉樹*/
int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void *data)
{
/*初始化合并樹*/
bitree_init(merge,left->destroy);
/*將傳入的data插入到新樹的根結點中*/
if(bitree_ins_left(merge,NULL,data) != 0)
{
bitree_destroy(merge);
return -1;
}
/*合并後的樹的左右子結點,分別設定為left和right的根結點*/
bitree_root(merge)->left = bitree_root(left);
bitree_root(merge)->right = bitree_root(right);
/*調整合并後的樹的結點的數量為本身的數量與左右兩顆樹的結點數量之和*/
merge->size = merge->size + bitree->size(left) + bitree_size(right);
/*解除原來樹中的結點關係,並分別將size設定為0*/
left->root = NULL;
left->size = 0;
right->root = NULL;
right->size = 0;
return 0;
}
二叉樹的層次遍曆
重建二叉樹
二叉樹的代碼實現
二叉樹常見面試題(進階)
二叉樹資料結構的實現