# [数据结构]——二叉树（Binary Tree）、二叉搜索树（Binary Search Tree）及其衍生算法

1）二叉树（Binary Tree）

/*   A simple binary tree
*        A ---------> A is root node
*       / \
*      /   \
*     B     C
*    /     / \
*   /     /   \
*   D     E    F ---> leaves: D, E, F
*
*       (1)      ---> Height: 3
* */


/*  Complete Binary Tree (CBT) and Full Binary Tree (FBT)
*        A              A                A
*       / \            / \              / \
*      /   \          /   \            /   \
*     B     C        B     C          B     C
*    / \            / \   / \              / \
*   /   \          /   \ /   \            /   \
*   D    E        D    E F    G          D     E
*
*      (2)             (3)               (4)
*      CBT             FBT             not CBT
* */


2）二叉树的构建和遍历

// A simple binary tree node define
typedef struct __TreeNode
{
int val;
struct __TreeNode *left, *right;
}TreeNode;


// root is in middle order travel, (1):D->B->A->E->C->F
void inorder(TreeNode *root)
{
if (root == NULL) return;
inorder(root->left);
printf("%d ",root->val);	// visit
inorder(root->right);
}
// previous visit root order travel, (1):A->B->D->C->E->F
void preorder(TreeNode *root)
{
if (root == NULL) return;
printf("%d ",root->val);	// visit
preorder(root->left);
preorder(root)
}
// post vist root order travel, (1):D->B->E->F->C->A
void postorder(TreeNode *root)
{
if (root == NULL) return;
postorder(root->left);
postorder(root->right);
printf("%d ",root->val);	// visit
}


// level order travel, (1):A->B->C->D->E->F
void levelorder(TreeNode *root)
{
if(root==NULL) return;
queue<TreeNode*> q;
for(q.push(root); q.size(); q.pop()){
TreeNode *r = q.front();
printf("%d ",r->val);	// visit
if (r->left) q.push(r->left);
if (r->right) q.push(r->right);
}
}


3）二叉树的序列化（serialize）和反序列化（deserialize）

/*  A simple binary tree four typical traversals
*           A
*          / \        in order   : D->B->A->E->C->F
*         /   \       pre order  : A->B->D->C->E->F
*        B     C      post order : D->B->E->F->C->A
*       /     / \     level order: A->B->C->D->E->F
*      /     /   \
*     D     E     F
*
*          (1)
* */


// Using In order and Pre order to deserialize
/*
*        A*               A              A             A
*       / \    ====>     / \            / \           / \
*      /   \            /   \          /   \         /   \
*    D-B  E-C-F        B*  E-C-F      B   E-C-F     B    C*
*                     / \            /             /    / \
*                    /   \          /             /    /   \
*                   D    NULL      D*             D   E     F
*         root         root       root             root
*          |             |          |               |
*  IN: D-B-A-E-C-F     D-B          D             E-C-F
*  PRE:A-B-D-C-E-F     B-D-C-E-F    D-C-E-F       C-E-F
*      |               |            |             |
*     root           root          root          root
* */


// Using In order and Pre order to deserialize
TreeNode *deserialize(int pre[], int in[], int n, int begin, int end)
{
static int id = 0;				// current position in PRE order
if (begin==0 && end==n) id=0;	// reset id
TreeNode *r = (TreeNode*)malloc(sizeof(TreeNode));
int pos;						// current root position in IN order
for (pos=begin; pos<end && in[pos]!=pre[id]; ++pos);
if (in[pos]!=pre[id]) exit(-1);	// preorder or inorder is error
r->val = pre[id++];
r->left = deserialize(pre,in,n,begin,pos);
r->right= deserialize(pre,in,n,pos+1,end);
return r;
}


4）二叉搜索树（Binary Search Tree）

// Asuming each node value is not equal
/*  A simple binary search tree
*           6                  6
*          / \                / \
*         /   \              /   \
*        3     8            3     8
*       /     / \          /     / \
*      /     /   \        /     /   \
*     2     7     9      2     4*    9
*
*       (A) BST             (B) Not BST
* */


// Initialize a bst
TreeNode *bst_init(int arr[], int n)
{
if (n<1) return NULL;
TreeNode *r = (TreeNode*)malloc(sizeof(TreeNode));
r->val = arr[0];		// ensure bst_append will not update root address
r->left = r->right = NULL;
for (; --n; bst_append(r,arr[n]));
return r;
}


// Append a node to bst, return add count
int bst_append(TreeNode *r, int val)
{
// find insertion position
for (; r && r->val!=val;){
if (r->val < val && r->right) r=r->right;
else if (r->val > val && r->left) r=r->left;
else break;
}
if (r==NULL || r->val==val) return 0;
TreeNode *tn = (TreeNode*)malloc(sizeof(TreeNode));
tn->left = tn->right = NULLL;
tn->val = val;
if (r->val < val) r->right = tn;
else r->left = tn;
return 1;
}


// Find value in bst, return node address
TreeNode *bst_find(TreeNode *r, int val)
{
for (; r && r->val!=val;){
if (r->val < val) r=r->right;
else if (r->val > val) r=r->left;
}
return r;
}


/* Erase node from a bst - sketch, i' is special for erase 6 (i)
*       6            d=6,(3)       f=6           6           d=6,(5)
*      / \            / \          / \          / \           /  \
*     /   \          /   \        /   \        /   \         /    \
*    3    8        p=3    8     d=3    8      3   f=8      f=3     8
*   /    / \        /    / \     /    / \     /    / \      / \   / \
*  /    /   \      /    /   \   /    /   \   /    /   \    /   \ /   \
*  2    7    9    2    7    9   2    7    9  2   d=7  9   2  p=5 7   9
*                                                             /
*     BST             (i)           (ii)        (iii)        /  (i')
*                   erase 6      erase 3      erase 7       4
* */


(i) 待删除的节点有两个子节点：以删除6为例，为了便于说明，这里将待删除节点称为d=6，其前驱节点为p=3。按照(i)图示方法，可以将其前驱节点p的值替换待删除节点d，并删除前驱节点。注意，如果前驱节点p仍有子节点（子树），则其必然是左节点（左子树），为什么？请自行思考。这里将前驱节点p的父节点称为f，此时的f正好是d，但不是所有情况都是。对于(i')图示，前驱节点p=5的父节点为f=3，当删除d=6时，可以将f的右子节点指向p的左子节点；对于(i)，由于f与d相同，所以可以直接将d的左子节点指向p的左子节点。

(ii)待删除的节点有一个子节点：以删除3为例，由于只有一个子节点，所以可将d节点的子节点继承d，此时需要将d的父节点f=6的子节点指向继承节点。并且需要区分当前删除节点d是父节点f的左子节点还是右子节点，以及d节点的子节点是左子还是右子。图示d为f的左子节点，d有左子节点，所以将f的左子节点指向d的左子节点。

(iii)待删除的节点无子节点：以删除7为例，很简单，将其直接删除，并且将其父节点f的子节点指向空。同样需要判断d是f的左子还是右子。

int bst_erase(TreeNode *r, int val)
{
TreeNode *f, *p, *d;
// f is father node
// p is precursor node
// d is to be deleted node
for (f=NULL,d=r; d && d->val!=val;){
f = d;
if (d->val < val) d=d->right;
else d=d->left;
}
if (d==NULL) return 0;			// cannot find erase node

if (d->left && d->right){		// deletion has two children
// find deletion node d's precursor
for (f=d,p=d->left; p->right; f=p, p=p->right);
d->val = p->val;			// replace deletion val by precursor
if (f==d) d->left = p->left;// case (i)
else f->right = p->left;	// case (i')
}
else if (d->left==NULL && d->right==NULL){
if (d==r) return -1;		// deletion is single root, this will
// deal this at calling procedure.
// deletion is leaf
if (f->left == d) f->left=NULL;
else if (f->right == d) f->right=NULL;
free(d);
}
else {	// deletion has single child node or branch
p = (d->left ? d->left : d->right);
d->val = p->val;
d->left = p->left;
d->right = p->right;
free(p);
}
return 1;	// return erase node count
}


binary tree deserialize : https://git.oschina.net/eudiwffe/codingstudy/blob/master/src/binarytree/btdeserialize.c

binary search tree : https://git.oschina.net/eudiwffe/codingstudy/blob/master/src/binarytree/bst.c

posted @ 2016-12-21 14:29  eudiwffe  阅读(16455)  评论(0编辑  收藏  举报