Mastering Algorithms with C(C語言bistree)

(1)bistree.h

/*****************************************************************************
*                                                                            *
*  ------------------------------- bistree.h ------------------------------  *
*                                                                            *
*****************************************************************************/

#ifndef BISTREE_H
#define BISTREE_H

#include "bitree.h"

/*****************************************************************************
*                                                                            *
*  Define balance factors for AVL trees.                                     *
*                                                                            *
*****************************************************************************/

#define            AVL_LFT_HEAVY         1
#define            AVL_BALANCED          0
#define            AVL_RGT_HEAVY        -1

/*****************************************************************************
*                                                                            *
*  Define a structure for nodes in AVL trees.                                *
*                                                                            *
*****************************************************************************/

typedef struct AvlNode_ {

void               *data;  // 結點數據
int                hidden; // 這裏的刪除僅僅是將該結點隱藏
int                factor; // 平衡因子

} AvlNode;

/*****************************************************************************
*                                                                            *
*  Implement binary search trees as binary trees.                            *
*                                                                            *
*****************************************************************************/

typedef BiTree BisTree;

/*****************************************************************************
*                                                                            *
*  --------------------------- Public Interface ---------------------------  *
*                                                                            *
*****************************************************************************/

void bistree_init(BisTree *tree, int (*compare)(const void *key1, const void
   *key2), void (*destroy)(void *data));

void bistree_destroy(BisTree *tree);

int bistree_insert(BisTree *tree, const void *data);

int bistree_remove(BisTree *tree, const void *data);

int bistree_lookup(BisTree *tree, void **data);

#define bistree_size(tree) ((tree)->size)

#endif

(2)bistree.c

/*****************************************************************************
*                                                                            *
*  ------------------------------- bistree.c ------------------------------  *
*                                                                            *
*****************************************************************************/

#include <stdlib.h>
#include <string.h>

#include "bistree.h"


static void destroy_right(BisTree *tree, BiTreeNode *node);


/*****************************************************************************
*                                                                            *
*  ------------------------------ rotate_left -----------------------------  *
*                                                                            *
*****************************************************************************/

static void rotate_left(BiTreeNode **node) { 
				// node 表示最近的不平衡祖先結點,平衡因子絕對值爲2
				// 注意雙指針的使用,確保修改值的正確性
BiTreeNode         *left, // left = node->left
                   *grandchild; // grandchild = left->child,child->{left,right}

left = bitree_left(*node);

if (((AvlNode *)bitree_data(left))->factor == AVL_LFT_HEAVY) { // LL

	// 原始二叉樹中的數據 void *data,現在變爲AvlNode *data
   /**************************************************************************
   *                                                                         *
   *  Perform an LL rotation.                                                *
   *                                                                         *
   **************************************************************************/

   // left pointer of A to the right child of left
   bitree_left(*node) = bitree_right(left); 
   // right pointer of left to A
   bitree_right(left) = *node;
   // 調節平衡因子
   ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
   ((AvlNode *)bitree_data(left))->factor = AVL_BALANCED;
   // pointer referencing A to lef
   *node = left; // 修改的是原地址中的數據

   }

else { // LR

   /**************************************************************************
   *                                                                         *
   *  Perform an LR rotation.                                                *
   *                                                                         *
   **************************************************************************/

   // grandchild be the right child of left
   grandchild = bitree_right(left);
   // right child of left to the left child of grandchild
   bitree_right(left) = bitree_left(grandchild);
   // left child of grandchild to left
   bitree_left(grandchild) = left;
   // left child of A to the right child of grandchild
   bitree_left(*node) = bitree_right(grandchild);
   // right child of grandchild to A
   bitree_right(grandchild) = *node;

   // 根據grandchild的平衡因子分情況調整各結點的平衡因子
   switch (((AvlNode *)bitree_data(grandchild))->factor) {

      case AVL_LFT_HEAVY: // 1

      ((AvlNode *)bitree_data(*node))->factor = AVL_RGT_HEAVY; // -1
      ((AvlNode *)bitree_data(left))->factor = AVL_BALANCED; // 0
      break;

      case AVL_BALANCED: // 0

      ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; // 0
      ((AvlNode *)bitree_data(left))->factor = AVL_BALANCED; // 0
      break;

      case AVL_RGT_HEAVY: // -1

      ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; // 0
      ((AvlNode *)bitree_data(left))->factor = AVL_LFT_HEAVY; // 1
      break;

   }

   ((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED; // 0
   // pointer referencing A to grandchild
   *node = grandchild;

}

return;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- rotate_right -----------------------------  *
*                                                                            *
*****************************************************************************/

static void rotate_right(BiTreeNode **node) {

				// node 表示最近的不平衡祖先結點,平衡因子絕對值爲2
				// 注意雙指針的使用,確保修改值的正確性
BiTreeNode         *right, // right = node->right
                   *grandchild; // grandchild = right->child,child->{left,right}

right = bitree_right(*node);

if (((AvlNode *)bitree_data(right))->factor == AVL_RGT_HEAVY) { // RR
	
	// 原始二叉樹中的數據 void *data,現在變爲AvlNode *data

   /**************************************************************************
   *                                                                         *
   *  Perform an RR rotation.                                                *
   *                                                                         *
   **************************************************************************/

   // right pointer of A to the left child of right
   bitree_right(*node) = bitree_left(right);
   // left pointer of right to A
   bitree_left(right) = *node;
   // 調節平衡因子
   ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; // 0
   ((AvlNode *)bitree_data(right))->factor = AVL_BALANCED; // 0
   // pointer referencing A to right
   *node = right;

   }

else { // RL

   /**************************************************************************
   *                                                                         *
   *  Perform an RL rotation.                                                *
   *                                                                         *
   **************************************************************************/
   
   // grandchild be the left child of right
   grandchild = bitree_left(right);
   // left child of right to the right child of grandchild
   bitree_left(right) = bitree_right(grandchild);
   // right child of grandchild to right
   bitree_right(grandchild) = right;
   // right child of A to the left child of grandchild
   bitree_right(*node) = bitree_left(grandchild);
   // left child of grandchild to A
   bitree_left(grandchild) = *node;

   // 根據grandchild的平衡因子分情況調整各結點的平衡因子
   switch (((AvlNode *)bitree_data(grandchild))->factor) {

      case AVL_LFT_HEAVY: // 1

      ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; // 0
      ((AvlNode *)bitree_data(right))->factor = AVL_RGT_HEAVY; // -1
      break;

      case AVL_BALANCED: // 0

      ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; // 0
      ((AvlNode *)bitree_data(right))->factor = AVL_BALANCED; // 0
      break;

      case AVL_RGT_HEAVY: // -1

      ((AvlNode *)bitree_data(*node))->factor = AVL_LFT_HEAVY; // 1
      ((AvlNode *)bitree_data(right))->factor = AVL_BALANCED; // 0
      break;

   }

   ((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED; // 0
   // pointer referencing A to grandchild
   *node = grandchild;

}

return;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- destroy_left -----------------------------  *
*                                                                            *
*****************************************************************************/

static void destroy_left(BisTree *tree, BiTreeNode *node) {

BiTreeNode         **position; // 指針的地址,方便後續的釋放操作

/*****************************************************************************
*                                                                            *
*  Do not allow destruction of an empty tree.                                *
*                                                                            *
*****************************************************************************/

if (bitree_size(tree) == 0) // 空樹無需摧毀
   return;

/*****************************************************************************
*                                                                            *
*  Determine where to destroy nodes.                                         *
*                                                                            *
*****************************************************************************/

if (node == NULL)
   position = &tree->root; // 刪除根結點
else
   position = &node->left; // 左子樹的根結點

/*****************************************************************************
*                                                                            *
*  Destroy the nodes.                                                        *
*                                                                            *
*****************************************************************************/

if (*position != NULL) { // 遞歸刪除

   destroy_left(tree, *position);
   destroy_right(tree, *position);

   if (tree->destroy != NULL) {

      /***********************************************************************
      *                                                                      *
      *  Call a user-defined function to free dynamically allocated data.    *
      *                                                                      *
      ***********************************************************************/

      tree->destroy(((AvlNode *)(*position)->data)->data); // 釋放分配的數據 data

   }

   /**************************************************************************
   *                                                                         *
   *  Free the AVL data in the node, then free the node itself.              *
   *                                                                         *
   **************************************************************************/

   free((*position)->data); // 釋放分配的結構體 AvlNode
   free(*position); // 釋放分配的結點 BiTreeNode
   *position = NULL; // 指針指向NULL

   /**************************************************************************
   *                                                                         *
   *  Adjust the size of the tree to account for the destroyed node.         *
   *                                                                         *
   **************************************************************************/

   tree->size--; // 結點數量減一

}

return;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- destroy_right ----------------------------  *
*                                                                            *
*****************************************************************************/

static void destroy_right(BisTree *tree, BiTreeNode *node) {

BiTreeNode         **position; // 指針的地址,方便後續的釋放操作

/*****************************************************************************
*                                                                            *
*  Do not allow destruction of an empty tree.                                *
*                                                                            *
*****************************************************************************/

if (bitree_size(tree) == 0) // 空樹無需摧毀
   return;

/*****************************************************************************
*                                                                            *
*  Determine where to destroy nodes.                                         *
*                                                                            *
*****************************************************************************/

if (node == NULL)
   position = &tree->root; // 刪除根結點
else
   position = &node->right; // 右子樹的根結點

/*****************************************************************************
*                                                                            *
*  Destroy the nodes.                                                        *
*                                                                            *
*****************************************************************************/

if (*position != NULL) { // 遞歸刪除

   destroy_left(tree, *position);
   destroy_right(tree, *position);

   if (tree->destroy != NULL) {

      /***********************************************************************
      *                                                                      *
      *  Call a user-defined function to free dynamically allocated data.    *
      *                                                                      *
      ***********************************************************************/

      tree->destroy(((AvlNode *)(*position)->data)->data); // 釋放分配的數據 data

   }

   /**************************************************************************
   *                                                                         *
   *  Free the AVL data in the node, then free the node itself.              *
   *                                                                         *
   **************************************************************************/

   free((*position)->data); // 釋放分配的結構體 AvlNode
   free(*position); // 釋放分配的結點 BiTreeNode
   *position = NULL; // 指針指向NULL

   /**************************************************************************
   *                                                                         *
   *  Adjust the size of the tree to account for the destroyed node.         *
   *                                                                         *
   **************************************************************************/

   tree->size--; // 結點數量減一

}

return;

}

/*****************************************************************************
*                                                                            *
*  -------------------------------- insert --------------------------------  *
*                                                                            *
*****************************************************************************/

static int insert(BisTree *tree, BiTreeNode **node, const void *data, int
   *balanced) {
				 // node 表示從哪個結點開始比較,尋找插入的位置
AvlNode            *avl_data; // 爲新數據分配內存,指向該地址

int                cmpval, // 比較方向,向左還是向右判斷
                   retval; // 判斷插入數據是否成功

/*****************************************************************************
*                                                                            *
*  Insert the data into the tree.                                            *
*                                                                            *
*****************************************************************************/

if (bitree_is_eob(*node)) { // 樹爲空

   /**************************************************************************
   *                                                                         *
   *  Handle insertion into an empty tree.                                   *
   *                                                                         *
   **************************************************************************/

   if ((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) // 分配內存失敗
      return -1;

   avl_data->factor = AVL_BALANCED; // 默認平衡因子爲0
   avl_data->hidden = 0; // 顯示,不隱藏
   avl_data->data = (void *)data; // 賦值

   return bitree_ins_left(tree, *node, avl_data); // 直接插入

   }

else {

   /**************************************************************************
   *                                                                         *
   *  Handle insertion into a tree that is not empty.                        *
   *                                                                         *
   **************************************************************************/

   // 與當前值比較大小
   cmpval = tree->compare(data, ((AvlNode *)bitree_data(*node))->data);

   if (cmpval < 0) { // 在左子樹中比較

      /***********************************************************************
      *                                                                      *
      *  Move to the left.                                                   *
      *                                                                      *
      ***********************************************************************/

      if (bitree_is_eob(bitree_left(*node))) { // 左孩子爲空,插入

         if ((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) // 分配數據
            return -1;

         avl_data->factor = AVL_BALANCED; // 默認平衡因子爲0
         avl_data->hidden = 0; // 顯示,不隱藏
         avl_data->data = (void *)data; // 賦值

         if (bitree_ins_left(tree, *node, avl_data) != 0) // 插入
            return -1;

         *balanced = 0;

         }

      else { // 左孩子不爲空,遞歸判斷

         if ((retval = insert(tree, &bitree_left(*node), data, balanced))
            != 0) { // 插入失敗,返回

            return retval; // -1

         }

      }

      /***********************************************************************
      *                                                                      *
      *  Ensure that the tree remains balanced.                              *
      *                                                                      *
      ***********************************************************************/

      if (!(*balanced)) { // 不平衡,插入的位置是葉子節點的孩子時,可能不平衡

         switch (((AvlNode *)bitree_data(*node))->factor) {

            case AVL_LFT_HEAVY: // 這種情況不可能出現在遞歸的末尾,即插入的結點的父節點身上
			// 當從最後一層遞歸返回時,判斷最近的平衡因子可能爲+-2的結點
            rotate_left(node);
            *balanced = 1; // 整體爲平衡
            break;

            case AVL_BALANCED: // 0
            // 右孩子爲空,左孩子不爲空
            ((AvlNode *)bitree_data(*node))->factor = AVL_LFT_HEAVY; // 1,有可能改變原始樹的平衡性
            break;

            case AVL_RGT_HEAVY: // -1
            // 左右平衡
            ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; // 0
            *balanced = 1; // 並沒有改變原始樹的平衡性

         }

      }

      } /* if (cmpval < 0) */

   else if (cmpval > 0) { // 在右子樹中查找

      /***********************************************************************
      *                                                                      *
      *  Move to the right.                                                  *
      *                                                                      *
      ***********************************************************************/

      if (bitree_is_eob(bitree_right(*node))) { // 右孩子爲空,插入

         if ((avl_data = (AvlNode *)malloc(sizeof(AvlNode))) == NULL) // 分配數據
            return -1;

         avl_data->factor = AVL_BALANCED; // 默認平衡因子爲0
         avl_data->hidden = 0; // 顯示,不隱藏
         avl_data->data = (void *)data; // 賦值

         if (bitree_ins_right(tree, *node, avl_data) != 0) // 插入
            return -1;

         *balanced = 0; // 可能不平衡,進入判斷階段

         }

      else { // 右孩子不爲空,遞歸判斷

         if ((retval = insert(tree, &bitree_right(*node), data, balanced))
            != 0) { // 插入失敗,返回

            return retval; // -1

         }

      }

      /***********************************************************************
      *                                                                      *
      *  Ensure that the tree remains balanced.                              *
      *                                                                      *
      ***********************************************************************/

      if (!(*balanced)) { // 不平衡,插入的位置是葉子節點的孩子時,可能不平衡

         switch (((AvlNode *)bitree_data(*node))->factor) {

            case AVL_LFT_HEAVY: // -1
            // 插入之前,左孩子不爲空,插入右孩子之後,不改變樹的整體平衡性
            ((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED; // 0
            *balanced = 1; // 整體平衡
            break;

            case AVL_BALANCED:  // 0
            // 左孩子爲空,右孩子不爲空
            ((AvlNode *)bitree_data(*node))->factor = AVL_RGT_HEAVY; // -1,有可能改變原始樹的平衡性
            break;

            case AVL_RGT_HEAVY: // 這種情況不可能出現在遞歸的末尾,即插入的結點的父節點身上
			// 當從最後一層遞歸返回時,判斷最近的平衡因子可能爲+-2的結點
            rotate_right(node); // 旋轉之後
            *balanced = 1; // 整體爲平衡

         }

      }

      } /* if (cmpval > 0) */

   else {  // 插入數據重複

      /***********************************************************************
      *                                                                      *
      *  Handle finding a copy of the data.                                  *
      *                                                                      *
      ***********************************************************************/

      if (!((AvlNode *)bitree_data(*node))->hidden) { // 如果這個數已經存在於樹中

         /********************************************************************
         *                                                                   *
         *  Do nothing since the data is in the tree and not hidden.         *
         *                                                                   *
         ********************************************************************/

         return 1;

         }

      else {

         /********************************************************************
         *                                                                   *
         *  Insert the new data and mark it as not hidden.                   *
         *                                                                   *
         ********************************************************************/

         if (tree->destroy != NULL) {

            /*****************************************************************
            *                                                                *
            *  Destroy the hidden data since it is being replaced.           *
            *                                                                *
            *****************************************************************/
			// 刪除該位置原始的數據,賦值即可
            tree->destroy(((AvlNode *)bitree_data(*node))->data);

         }

         ((AvlNode *)bitree_data(*node))->data = (void *)data; // 賦值
         ((AvlNode *)bitree_data(*node))->hidden = 0; // 顯示

         /********************************************************************
         *                                                                   *
         *  Do not rebalance because the tree structure is unchanged.        *
         *                                                                   *
         ********************************************************************/

         *balanced = 1; // 整體平衡

      }

   }

}

return 0;

}

/*****************************************************************************
*                                                                            *
*  --------------------------------- hide ---------------------------------  *
*                                                                            *
*****************************************************************************/

static int hide(BisTree *tree, BiTreeNode *node, const void *data) {

int                cmpval, // 比較大小
                   retval; // 返回值

if (bitree_is_eob(node)) { // 結點爲空,返回

   /**************************************************************************
   *                                                                         *
   *  Return that the data was not found.                                    *
   *                                                                         *
   **************************************************************************/

   return -1;

}

cmpval = tree->compare(data, ((AvlNode *)bitree_data(node))->data); // 比較大小

if (cmpval < 0) { // 左子樹查找

   /**************************************************************************
   *                                                                         *
   *  Move to the left.                                                      *
   *                                                                         *
   **************************************************************************/

   retval = hide(tree, bitree_left(node), data);

   }

else if (cmpval > 0) { // 右子樹查找

   /**************************************************************************
   *                                                                         *
   *  Move to the right.                                                     *
   *                                                                         *
   **************************************************************************/

   retval = hide(tree, bitree_right(node), data);

   }

else { // 找到該值

   /**************************************************************************
   *                                                                         *
   *  Mark the node as hidden.                                               *
   *                                                                         *
   **************************************************************************/

   ((AvlNode *)bitree_data(node))->hidden = 1; // 隱藏該結點
   retval = 0;

}

return retval;

}

/*****************************************************************************
*                                                                            *
*  -------------------------------- lookup --------------------------------  *
*                                                                            *
*****************************************************************************/

static int lookup(BisTree *tree, BiTreeNode *node, void **data) {
					// 從node開始查找數據
int                cmpval, // 比較
                   retval; // 返回值

if (bitree_is_eob(node)) { // 爲空返回

   /**************************************************************************
   *                                                                         *
   *  Return that the data was not found.                                    *
   *                                                                         *
   **************************************************************************/

   return -1;

}

cmpval = tree->compare(*data, ((AvlNode *)bitree_data(node))->data); // 比較大小標誌

if (cmpval < 0) { // 轉向左子樹

   /**************************************************************************
   *                                                                         *
   *  Move to the left.                                                      *
   *                                                                         *
   **************************************************************************/

   retval = lookup(tree, bitree_left(node), data); // 遞歸查找

   }

else if (cmpval > 0) { // 轉向右子樹

   /**************************************************************************
   *                                                                         *
   *  Move to the right.                                                     *
   *                                                                         *
   **************************************************************************/

   retval = lookup(tree, bitree_right(node), data); // 遞歸查找

   }

else {

   if (!((AvlNode *)bitree_data(node))->hidden) { // 結點沒有被隱藏

      /***********************************************************************
      *                                                                      *
      *  Pass back the data from the tree.                                   *
      *                                                                      *
      ***********************************************************************/

      *data = ((AvlNode *)bitree_data(node))->data; // 傳參
      retval = 0;

      }

   else { // 該數據不在該樹中

      /***********************************************************************
      *                                                                      *
      *  Return that the data was not found.                                 *
      *                                                                      *
      ***********************************************************************/

      return -1;

   }

}

return retval;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- bistree_init -----------------------------  *
*                                                                            *
*****************************************************************************/

void bistree_init(BisTree *tree, int (*compare)(const void *key1, const void
   *key2), void (*destroy)(void *data)) {

/*****************************************************************************
*                                                                            *
*  Initialize the tree.                                                      *
*                                                                            *
*****************************************************************************/

bitree_init(tree, destroy);
tree->compare = compare;

return;

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- bistree_destroy ---------------------------  *
*                                                                            *
*****************************************************************************/

void bistree_destroy(BisTree *tree) {

/*****************************************************************************
*                                                                            *
*  Destroy all nodes in the tree.                                            *
*                                                                            *
*****************************************************************************/

destroy_left(tree, NULL);

/*****************************************************************************
*                                                                            *
*  No operations are allowed now, but clear the structure as a precaution.   *
*                                                                            *
*****************************************************************************/

memset(tree, 0, sizeof(BisTree));

return;

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- bistree_insert ----------------------------  *
*                                                                            *
*****************************************************************************/

int bistree_insert(BisTree *tree, const void *data) {

int                balanced = 0;

return insert(tree, &bitree_root(tree), data, &balanced);

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- bistree_remove ----------------------------  *
*                                                                            *
*****************************************************************************/

int bistree_remove(BisTree *tree, const void *data) {

return hide(tree, bitree_root(tree), data);

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- bistree_lookup ----------------------------  *
*                                                                            *
*****************************************************************************/

int bistree_lookup(BisTree *tree, void **data) {

return lookup(tree, bitree_root(tree), data);

}

(3)ex-1.c

/*****************************************************************************
*                                                                            *
*  ex-1.c                                                                    *
*  ======                                                                    *
*                                                                            *
*  Description: Illustrates using a binary tree (see Chapter 9).             *
*                                                                            *
*****************************************************************************/

#include <stdio.h>
#include <stdlib.h>

#include "bitree.h"
#include "traverse.h"

/*****************************************************************************
*                                                                            *
*  ---------------------------- print_preorder ----------------------------  *
*                                                                            *
*****************************************************************************/

static void print_preorder(const BiTreeNode *node) {

/*****************************************************************************
*                                                                            *
*  Display the binary tree rooted at the specified node in preorder.         *
*                                                                            *
*****************************************************************************/

if (!bitree_is_eob(node)) {

   fprintf(stdout, "Node=%03d\n", *(int *)bitree_data(node));

   if (!bitree_is_eob(bitree_left(node)))
      print_preorder(bitree_left(node));

   if (!bitree_is_eob(bitree_right(node)))
      print_preorder(bitree_right(node));

}

return;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- print_inorder ----------------------------  *
*                                                                            *
*****************************************************************************/

static void print_inorder(const BiTreeNode *node) {

/*****************************************************************************
*                                                                            *
*  Display the binary tree rooted at the specified node in inorder.          *
*                                                                            *
*****************************************************************************/

if (!bitree_is_eob(node)) {

   if (!bitree_is_eob(bitree_left(node)))
      print_inorder(bitree_left(node));

   fprintf(stdout, "Node=%03d\n", *(int *)bitree_data(node));

   if (!bitree_is_eob(bitree_right(node)))
      print_inorder(bitree_right(node));

}

return;

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- print_postorder ---------------------------  *
*                                                                            *
*****************************************************************************/

static void print_postorder(const BiTreeNode *node) {

/*****************************************************************************
*                                                                            *
*  Display the binary tree rooted at the specified node in postorder.        *
*                                                                            *
*****************************************************************************/

if (!bitree_is_eob(node)) {

   if (!bitree_is_eob(bitree_left(node)))
      print_postorder(bitree_left(node));

   if (!bitree_is_eob(bitree_right(node)))
      print_postorder(bitree_right(node));

   fprintf(stdout, "Node=%03d\n", *(int *)bitree_data(node));

}

return;

}

/*****************************************************************************
*                                                                            *
*  ------------------------------ insert_int ------------------------------  *
*                                                                            *
*****************************************************************************/

static int insert_int(BiTree *tree, int i) {

BiTreeNode         *node,
                   *prev;

int                direction,
                   *data;

/*****************************************************************************
*                                                                            *
*  Insert i assuming a binary tree organized as a binary search tree.        *
*                                                                            *
*****************************************************************************/

node = tree->root;
direction = 0;

while (!bitree_is_eob(node)) {

   prev = node;

   if (i == *(int *)bitree_data(node)) {

      return -1;

      }

   else if (i < *(int *)bitree_data(node)) {

      node = bitree_left(node);
      direction = 1;

      }

   else {

      node = bitree_right(node);
      direction = 2;

   }

}

if ((data = (int *)malloc(sizeof(int))) == NULL)
   return -1;

*data = i;

if (direction == 0)
   return bitree_ins_left(tree, NULL, data);

if (direction == 1)
   return bitree_ins_left(tree, prev, data);

if (direction == 2)
   return bitree_ins_right(tree, prev, data);

return -1;

}

/*****************************************************************************
*                                                                            *
*  ------------------------------ search_int ------------------------------  *
*                                                                            *
*****************************************************************************/

static BiTreeNode *search_int(BiTree *tree, int i) {

BiTreeNode         *node;

/*****************************************************************************
*                                                                            *
*  Look up i assuming a binary tree organized as a binary search tree.       *
*                                                                            *
*****************************************************************************/

node = bitree_root(tree);

while (!bitree_is_eob(node)) {

   if (i == *(int *)bitree_data(node)) {

      return node;

      }

   else if (i < *(int *)bitree_data(node)) {

      node = bitree_left(node);

      }

   else {

      node = bitree_right(node);

   }

}

return NULL;

}

/*****************************************************************************
*                                                                            *
*  --------------------------------- main ---------------------------------  *
*                                                                            *
*****************************************************************************/

int main(int argc, char **argv) {

BiTree             tree;
BiTreeNode         *node;

int                i;

/*****************************************************************************
*                                                                            *
*  Initialize the binary tree.                                               *
*                                                                            *
*****************************************************************************/

bitree_init(&tree, free);

/*****************************************************************************
*                                                                            *
*  Perform some binary tree operations.                                      *
*                                                                            *
*****************************************************************************/

fprintf(stdout, "Inserting some nodes\n");

if (insert_int(&tree, 20) != 0)
   return 1;

if (insert_int(&tree, 10) != 0)
   return 1;

if (insert_int(&tree, 30) != 0)
   return 1;

if (insert_int(&tree, 15) != 0)
   return 1;

if (insert_int(&tree, 25) != 0)
   return 1;

if (insert_int(&tree, 70) != 0)
   return 1;

if (insert_int(&tree, 80) != 0)
   return 1;

if (insert_int(&tree, 23) != 0)
   return 1;

if (insert_int(&tree, 26) != 0)
   return 1;

if (insert_int(&tree, 5) != 0)
   return 1;

fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
fprintf(stdout, "(Preorder traversal)\n");
print_preorder(bitree_root(&tree));

i = 30;

if ((node = search_int(&tree, i)) == NULL) {

   fprintf(stdout, "Could not find %03d\n", i);

   }

else {

   fprintf(stdout, "Found %03d...Removing the left tree below it\n", i);
   bitree_rem_left(&tree, node);
   fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
   fprintf(stdout, "(Preorder traversal)\n");
   print_preorder(bitree_root(&tree));

}

i = 99;

if ((node = search_int(&tree, i)) == NULL) {

   fprintf(stdout, "Could not find %03d\n", i);

   }

else {

   fprintf(stdout, "Found %03d...Removing the right tree below it\n", i);
   bitree_rem_right(&tree, node);
   fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
   fprintf(stdout, "(Preorder traversal)\n");
   print_preorder(bitree_root(&tree));

}

i = 20;

if ((node = search_int(&tree, i)) == NULL) {

   fprintf(stdout, "Could not find %03d\n", i);

   }

else {

   fprintf(stdout, "Found %03d...Removing the right tree below it\n", i);
   bitree_rem_right(&tree, node);
   fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
   fprintf(stdout, "(Preorder traversal)\n");
   print_preorder(bitree_root(&tree));

}

i = bitree_is_leaf(bitree_root(&tree));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (0=OK)\n", i);
i = bitree_is_leaf(bitree_left((bitree_root(&tree))));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (0=OK)\n", i);
i = bitree_is_leaf(bitree_left(bitree_left((bitree_root(&tree)))));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (1=OK)\n", i);
i = bitree_is_leaf(bitree_right(bitree_left((bitree_root(&tree)))));
fprintf(stdout, "Testing bitree_is_leaf...Value=%d (1=OK)\n", i);

fprintf(stdout, "Inserting some nodes\n");

if (insert_int(&tree, 55) != 0)
   return 1;

if (insert_int(&tree, 44) != 0)
   return 1;

if (insert_int(&tree, 77) != 0)
   return 1;

if (insert_int(&tree, 11) != 0)
   return 1;

fprintf(stdout, "Tree size is %d\n", bitree_size(&tree));
fprintf(stdout, "(Preorder traversal)\n");
print_preorder(bitree_root(&tree));
fprintf(stdout, "(Inorder traversal)\n");
print_inorder(bitree_root(&tree));
fprintf(stdout, "(Postorder traversal)\n");
print_postorder(bitree_root(&tree));

/*****************************************************************************
*                                                                            *
*  Destroy the binary tree.                                                  *
*                                                                            *
*****************************************************************************/

fprintf(stdout, "Destroying the tree\n");
bitree_destroy(&tree);

return 0;

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章