Mastering Algorithms with C(bitree)

(1)bitree.h

/*****************************************************************************
*                                                                            *
*  ------------------------------- bitree.h -------------------------------  *
*                                                                            *
*****************************************************************************/

#ifndef BITREE_H
#define BITREE_H

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

#include "bitree.h"

/*****************************************************************************
*                                                                            *
*  Define a structure for binary tree nodes.                                 *
*                                                                            *
*****************************************************************************/

typedef struct BiTreeNode_ {

void               *data; // 非明确数据类型,保存的是数据的地址
struct BiTreeNode_ *left; // 左孩子
struct BiTreeNode_ *right; // 右孩子
                   
} BiTreeNode;

/*****************************************************************************
*                                                                            *
*  Define a structure for binary trees.                                      *
*                                                                            *
*****************************************************************************/

typedef struct BiTree_ {

int                size; // 结点大小

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

BiTreeNode         *root; //  根结点指针

} BiTree;

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

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)

/*****************************************************************************
*                                                                            *
*  ------------------------------- bitree.c -------------------------------  *
*                                                                            *
*****************************************************************************/

/*****************************************************************************
*                                                                            *
*  ------------------------------ bitree_init -----------------------------  *
*                                                                            *
*****************************************************************************/

void bitree_init(BiTree *tree, void (*destroy)(void *data)) {

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

tree->size = 0;
tree->destroy = destroy;
tree->root = NULL;

return;

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- bitree_destroy ----------------------------  *
*                                                                            *
*****************************************************************************/

void bitree_destroy(BiTree *tree) {

/*****************************************************************************
*                                                                            *
*  Remove all the nodes from the tree.                                       *
*                                                                            *
*****************************************************************************/

bitree_rem_left(tree, NULL);

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

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

return;

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- bitree_ins_left ---------------------------  *
*                                                                            *
*****************************************************************************/

int bitree_ins_left(BiTree *tree, BiTreeNode *node, const void *data) {

					// 插入该结点的左孩子位置
BiTreeNode         *new_node,
                   **position;

/*****************************************************************************
*                                                                            *
*  Determine where to insert the node.                                       *
*                                                                            *
*****************************************************************************/

if (node == NULL) { // 这个表示的是该结点是否为空

   /**************************************************************************
   *                                                                         *
   *  Allow insertion at the root only in an empty tree.                     *
   *                                                                         *
   **************************************************************************/

   if (bitree_size(tree) > 0) // 空才可以插入根结点的位置
      return -1;

   position = &tree->root;

   }

else {

   /**************************************************************************
   *                                                                         *
   *  Normally allow insertion only at the end of a branch.                  *
   *                                                                         *
   **************************************************************************/

   if (bitree_left(node) != NULL) // 该结点左孩子不为空 插入失败
      return -1;

   position = &node->left;

}

/*****************************************************************************
*                                                                            *
*  Allocate storage for the node.                                            *
*                                                                            *
*****************************************************************************/

// 为新结点分配内存
if ((new_node = (BiTreeNode *)malloc(sizeof(BiTreeNode))) == NULL)
   return -1;

/*****************************************************************************
*                                                                            *
*  Insert the node into the tree.                                            *
*                                                                            *
*****************************************************************************/

new_node->data = (void *)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node; // position为双指针,可确保插入的结点位于正确的位置

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

tree->size++; // 数量加一

return 0;

}

/*****************************************************************************
*                                                                            *
*  --------------------------- bitree_ins_right ---------------------------  *
*                                                                            *
*****************************************************************************/

int bitree_ins_right(BiTree *tree, BiTreeNode *node, const void *data) {

					// 插入该结点的右孩子位置
BiTreeNode         *new_node,
                   **position;

/*****************************************************************************
*                                                                            *
*  Determine where to insert the node.                                       *
*                                                                            *
*****************************************************************************/

if (node == NULL) { // 这个表示的是该结点是否为空

   /**************************************************************************
   *                                                                         *
   *  Allow insertion at the root only in an empty tree.                     *
   *                                                                         *
   **************************************************************************/

   if (bitree_size(tree) > 0) // 空才可以插入根结点的位置
      return -1;

   position = &tree->root;

   }

else {

   /**************************************************************************
   *                                                                         *
   *  Normally allow insertion only at the end of a branch.                  *
   *                                                                         *
   **************************************************************************/

   if (bitree_right(node) != NULL) // 该结点左孩子不为空 插入失败
      return -1;

   position = &node->right;

}

/*****************************************************************************
*                                                                            *
*  Allocate storage for the node.                                            *
*                                                                            *
*****************************************************************************/

if ((new_node = (BiTreeNode *)malloc(sizeof(BiTreeNode))) == NULL)
   return -1;

/*****************************************************************************
*                                                                            *
*  Insert the node into the tree.                                            *
*                                                                            *
*****************************************************************************/

new_node->data = (void *)data;
new_node->left = NULL;
new_node->right = NULL;
*position = new_node; // position为双指针,可确保插入的结点位于正确的位置

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

tree->size++; // 结点数加一

return 0;

}

/*****************************************************************************
*                                                                            *
*  ---------------------------- bitree_rem_left ---------------------------  *
*                                                                            *
*****************************************************************************/

void bitree_rem_left(BiTree *tree, BiTreeNode *node) {
					// 删除node结点的左子树
BiTreeNode         **position;

/*****************************************************************************
*                                                                            *
*  Do not allow removal from an empty tree.                                  *
*                                                                            *
*****************************************************************************/

if (bitree_size(tree) == 0) // 空树无需删除
   return;

/*****************************************************************************
*                                                                            *
*  Determine where to remove nodes.                                          *
*                                                                            *
*****************************************************************************/

if (node == NULL) // 删除整棵子树
   position = &tree->root;
else
   position = &node->left; // 左子树的根结点

/*****************************************************************************
*                                                                            *
*  Remove the nodes.                                                         *
*                                                                            *
*****************************************************************************/

if (*position != NULL) { // 递归删除

   bitree_rem_left(tree, *position);
   bitree_rem_right(tree, *position);

   if (tree->destroy != NULL) {

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

      tree->destroy((*position)->data);

   }

   free(*position);
   *position = NULL;

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

   tree->size--;

}

return;

}

/*****************************************************************************
*                                                                            *
*  --------------------------- bitree_rem_right ---------------------------  *
*                                                                            *
*****************************************************************************/

void bitree_rem_right(BiTree *tree, BiTreeNode *node) {
					// 删除node结点的右子树
BiTreeNode         **position;

/*****************************************************************************
*                                                                            *
*  Do not allow removal from an empty tree.                                  *
*                                                                            *
*****************************************************************************/

if (bitree_size(tree) == 0) // 空树无需删除
   return;

/*****************************************************************************
*                                                                            *
*  Determine where to remove nodes.                                          *
*                                                                            *
*****************************************************************************/

if (node == NULL) // 删除整棵子树
   position = &tree->root;
else
   position = &node->right; // 右子树的根结点

/*****************************************************************************
*                                                                            *
*  Remove the nodes.                                                         *
*                                                                            *
*****************************************************************************/

if (*position != NULL) { // 递归删除

   bitree_rem_left(tree, *position);
   bitree_rem_right(tree, *position);

   if (tree->destroy != NULL) {

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

      tree->destroy((*position)->data);

   }

   free(*position);
   *position = NULL;

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

   tree->size--;

}

return;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- bitree_merge -----------------------------  *
*                                                                            *
*****************************************************************************/

int bitree_merge(BiTree *merge, BiTree *left, BiTree *right, const void
   *data) {
			// 合并二叉树,merge为根结点,left,right分别表示左右子树的根结点
/*****************************************************************************
*                                                                            *
*  Initialize the merged tree.                                               *
*                                                                            *
*****************************************************************************/

bitree_init(merge, left->destroy);

/*****************************************************************************
*                                                                            *
*  Insert the data for the root node of the merged tree.                     *
*                                                                            *
*****************************************************************************/

if (bitree_ins_left(merge, NULL, data) != 0) {

   bitree_destroy(merge);
   return -1;

}

/*****************************************************************************
*                                                                            *
*  Merge the two binary trees into a single binary tree.                     *
*                                                                            *
*****************************************************************************/

bitree_root(merge)->left = bitree_root(left);
bitree_root(merge)->right = bitree_root(right);

/*****************************************************************************
*                                                                            *
*  Adjust the size of the new binary tree.                                   *
*                                                                            *
*****************************************************************************/

merge->size = merge->size + bitree_size(left) + bitree_size(right); // 合并大小

/*****************************************************************************
*                                                                            *
*  Do not let the original trees access the merged nodes.                    *
*                                                                            *
*****************************************************************************/
// 合并后的树 只能通过merge中的根结点访问
left->root = NULL;
left->size = 0;
right->root = NULL;
right->size = 0;

return 0;

}


#endif

(2)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;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
There are many books on data structures and algorithms, including some with useful libraries of C functions. Mastering Algorithms with C offers you a unique combination of theoretical background and working code. With robust solutions for everyday programming tasks, this book avoids the abstract style of most classic data structures and algorithms texts, but still provides all of the information you need to understand the purpose and use of common programming techniques. Implementations, as well as interesting, real-world examples of each data structure and algorithm, are included. Using both a programming style and a writing style that are exceptionally clean, Kyle Loudon shows you how to use such essential data structures as lists, stacks, queues, sets, trees, heaps, priority queues, and graphs. He explains how to use algorithms for sorting, searching, numerical analysis, data compression, data encryption, common graph problems, and computational geometry. And he describes the relative efficiency of all implementations. The compression and encryption chapters not only give you working code for reasonably efficient solutions, they offer explanations of concepts in an approachable manner for people who never have had the time or expertise to study them in depth. Anyone with a basic understanding of the C language can use this book. In order to provide maintainable and extendible code, an extra level of abstraction (such as pointers to functions) is used in examples where appropriate. Understanding that these techniques may be unfamiliar to some programmers, Loudon explains them clearly in the introductory chapters. Contents include: Pointers Recursion Analysis of algorithms Data structures (lists, stacks, queues, sets, hash tables, trees, heaps, priority queues, graphs) Sorting and searching Numerical methods Data compression Data encryption Graph algorithms Geometric algorithms
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值