二叉查找树C语言实现及其可视化

来源:互联网 发布:最终幻想猫女捏脸数据 编辑:程序博客网 时间:2024/05/01 12:38
0, 二叉搜索树的定义:(二叉查找树)(二叉排序树)
      (1)若左子树非空,则左子树上的所有的节点的值都小于根节点的值
      (2)若右子树非空,则右子树上的所有的节点的值都大于根节点的值

      (3)其左右子树都是二叉搜索树

                 

1,二叉查找树的表示法

struct TreeNode;typedef struct TreeNode *PtrSearchTree;typedef PtrSearchTree SearchTree;struct TreeNode{int value;PtrSearchTree left;PtrSearchTree right;};

2,二叉查找树的插入:插入的元素始终位于叶子节点。

void insert(SearchTree* tree, int value){if( *tree == NULL ){if( ! ((*tree) = (PtrSearchTree)malloc(sizeof(struct TreeNode))) ){printf("insert malloc error\n");exit(0);}(*tree)->value = value;(*tree)->left = (*tree)->right = NULL;}else{if( value < (*tree)->value )insert(&((*tree)->left), value);elseinsert(&((*tree)->right), value);}}
3,二叉查找树的创建,调用插入函数即可。

note:

1  SearchTree tree = NULL;其中的 “= NULL”,在window下的gcc进行编译运行时可以省略, 但是在linux编译运行时如果没有将其值设置为NULL, 则提醒了“段错误”。应该是编译器的不同造成的, 不过为每个指针赋值,而不是由其变为野指针确实是个好的习惯。

2   getchar()是为了吃掉用户输入的数字之间的空格,并且在用户输入完成按下Enter键之后可以捕获到‘\n’.

SearchTree create(){SearchTree tree = NULL;printf("Create Binary Search Tree\nplease enter the element, seperated by space, and stop input by Enter:\n");int key;while(1){scanf("%d", &key);insert(&tree, key);if( getchar() == '\n' )break;}return tree;}
4, 二叉查找树的可视化。为了对其进行可视化,需要借助与graphviz,他的安装在上一篇中有简单的介绍,并且其中使用的dot语言可在官网查看,很容易学习。

void visualization(SearchTree tree, char* filename){FILE *fw;if( NULL == (fw = fopen(filename, "w")) ){printf("open file error");exit(0);}fprintf(fw, "digraph\n{\nnode [shape = Mrecord, style = filled, color = black, fontcolor = white];\n");write2dot(tree, fw);fprintf(fw, "}");fclose(fw);}void write2dot(SearchTree tree, FILE* fw){if(tree == NULL)return ;else{fprintf(fw, "%d [label = \"<f0> | <f1> %d | <f2> \", color = black, fontcolor = white, style = filled];\n", tree->value, tree->value);}if(tree->left){fprintf(fw, "%d [label = \"<f0> | <f1> %d | <f2> \", color = black, fontcolor = white, style = filled];\n", tree->left->value, tree->left->value);fprintf(fw, "%d:f0:sw -> %d:f1;\n", tree->value, tree->left->value);}if(tree->right){fprintf(fw, "%d [label = \"<f0> | <f1> %d | <f2> \", color = black, fontcolor = white, style = filled];\n", tree->right->value, tree->right->value);fprintf(fw, "%d:f2:se -> %d:f1;\n", tree->value, tree->right->value);}write2dot(tree->left, fw);write2dot(tree->right, fw);}
函数注释:

         (1)  visualization函数将参数tree指定的树,使用dot语言写入到参数filename指定的文件中(文件以.dot为后缀)

         (2) write2dot函数相当于一个遍历树的过程,在遍历过程中, 构成该树的dot文件。

程序的运行过程实例如下:

运行完成后会在同目录下产生一个.dot文件,在本程序中文件名为:searchtree.dot

使用dot命令产生图片,如下图所示,就生成了名为searchtree.png的图片。

查看图片如下:

                         

5, 二叉树的删除

若删除元素为叶子节点,则直接删除,将原本指向该节点的双亲节点的相应的指针域置空,

若删除度为1的节点,将其输出节点的子树直接挂在删除节点的父节点上,

若删除度为2的节点,找其左子树的最大值或者右子树的最小值替代该节点的值,然后在其左子树或者右子树删除找到的最大值或者最小值。

SearchTree delete(SearchTree tree, int value){PtrSearchTree temp = NULL;if( !tree ){printf("have no element(delete): %d\n", value);return NULL;}else if( value < tree->value )tree->left = delete(tree->left, value);else if( value > tree->value )tree->right = delete(tree->right, value);else{if( tree->left && tree->right ){temp = find_min(tree->right);tree->value = temp->value;tree->right = delete(tree->right, temp->value);}else{temp = tree;if( !(tree->left) )tree = tree->right;else if( !(tree->right) )tree = tree->left;free(temp);}}return tree;}
在程序中删除83,得到如下的二叉树:

                                

6,查找(递归和迭代)

                  note:函数的返回类型为指针类型。

SearchTree find_recursion(SearchTree tree, int value){if( !tree ){printf("have no element(find): %d\n", value);return NULL;}if( value < tree->value )find_recursion(tree->left, value);else if( value > tree->value )find_recursion(tree->right, value);elsereturn tree;}SearchTree find_iteration(SearchTree tree, int value){while(tree){if( value < tree->value )tree = tree->left;else if( value > tree->value )tree = tree->right;elsereturn tree;}printf("have no element(find): %d\n", value);return NULL;}



源码

#include<stdio.h>#include<stdlib.h>struct TreeNode;typedef struct TreeNode *PtrSearchTree;typedef PtrSearchTree SearchTree;struct TreeNode{int value;PtrSearchTree left;PtrSearchTree right;};SearchTree create();void insert(SearchTree* tree, int value);void write2dot(SearchTree tree, FILE* fw);void visualization(SearchTree tree, char* filename);SearchTree find_min(SearchTree tree);SearchTree find_max(SearchTree tree);SearchTree find_iteration(SearchTree tree, int value);SearchTree find_recursion(SearchTree tree, int value);SearchTree delete(SearchTree tree, int value);int main(int argc, char** argv){SearchTree s_tree_1 = create();visualization(s_tree_1, "searchtree.dot");PtrSearchTree min = find_min(s_tree_1);PtrSearchTree max = find_max(s_tree_1);printf("the min and max is %d, %d, respectively\n", min->value, max->value);int search = 83;PtrSearchTree find_result_1 = find_iteration(s_tree_1, search);PtrSearchTree find_result_2 = find_iteration(s_tree_1, search);if( find_result_1 && find_result_2 )printf("search for %d, and the result from iteration and recursion is: %d, %d\n", search, find_result_1->value, find_result_2->value);s_tree_1 = delete(s_tree_1, 83);visualization(s_tree_1, "searchtree_afterdelete.dot");return 0;}SearchTree create(){SearchTree tree = NULL;printf("Create Binary Search Tree\nplease enter the element, seperated by space, and stop input by Enter:\n");int key;while(1){scanf("%d", &key);insert(&tree, key);if( getchar() == '\n' )break;}return tree;}void insert(SearchTree* tree, int value){if( *tree == NULL ){if( ! ((*tree) = (PtrSearchTree)malloc(sizeof(struct TreeNode))) ){printf("insert malloc error\n");exit(0);}(*tree)->value = value;(*tree)->left = (*tree)->right = NULL;}else{if( value < (*tree)->value )insert(&((*tree)->left), value);elseinsert(&((*tree)->right), value);}}void visualization(SearchTree tree, char* filename){FILE *fw;if( NULL == (fw = fopen(filename, "w")) ){printf("open file error");exit(0);}fprintf(fw, "digraph\n{\nnode [shape = Mrecord, style = filled, color = black, fontcolor = white];\n");write2dot(tree, fw);fprintf(fw, "}");fclose(fw);}void write2dot(SearchTree tree, FILE* fw){if(tree == NULL)return ;else{fprintf(fw, "%d [label = \"<f0> | <f1> %d | <f2> \", color = black, fontcolor = white, style = filled];\n", tree->value, tree->value);}if(tree->left){fprintf(fw, "%d [label = \"<f0> | <f1> %d | <f2> \", color = black, fontcolor = white, style = filled];\n", tree->left->value, tree->left->value);fprintf(fw, "%d:f0:sw -> %d:f1;\n", tree->value, tree->left->value);}if(tree->right){fprintf(fw, "%d [label = \"<f0> | <f1> %d | <f2> \", color = black, fontcolor = white, style = filled];\n", tree->right->value, tree->right->value);fprintf(fw, "%d:f2:se -> %d:f1;\n", tree->value, tree->right->value);}write2dot(tree->left, fw);write2dot(tree->right, fw);}SearchTree find_min(SearchTree tree){if( !tree )return NULL;elseif( !(tree->left) ) return tree;elsefind_min(tree->left);}SearchTree find_max(SearchTree tree){if( !tree )return NULL;elseif( !(tree->right) ) return tree;else find_max(tree->right);}SearchTree find_recursion(SearchTree tree, int value){if( !tree ){printf("have no element(find): %d\n", value);return NULL;}if( value < tree->value )find_recursion(tree->left, value);else if( value > tree->value )find_recursion(tree->right, value);elsereturn tree;}SearchTree find_iteration(SearchTree tree, int value){while(tree){if( value < tree->value )tree = tree->left;else if( value > tree->value )tree = tree->right;elsereturn tree;}printf("have no element(find): %d\n", value);return NULL;}SearchTree delete(SearchTree tree, int value){PtrSearchTree temp = NULL;if( !tree ){printf("have no element(delete): %d\n", value);return NULL;}else if( value < tree->value )tree->left = delete(tree->left, value);else if( value > tree->value )tree->right = delete(tree->right, value);else{if( tree->left && tree->right ){temp = find_min(tree->right);tree->value = temp->value;tree->right = delete(tree->right, temp->value);}else{temp = tree;if( !(tree->left) )tree = tree->right;else if( !(tree->right) )tree = tree->left;free(temp);}}return tree;}


0 0