二叉查找树是 左子节点 <= 根节点 <= 右子节点 的树形结构,其平均时间复杂度:O(log2n)(简单地说搜索方式跟二分法差不多)。
二叉排序树是一种动态树表。其特点是:树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的节点时再进行插入。
新插入的结点一定是一个新添加的叶子节点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。
先定义二叉树和树节点:
typedef struct BST_node{ int data; struct BST_node* left; struct BST_node* right; }BST_Node; typedef struct BST{ BST_Node* root; size_t size; };
再给出创建节点和删除的函数:
//定义一个函数用来用传入的数据创建节点 BST_Node* creat(int data){ BST_Node* node= (BST_Node*)malloc(sizeof(BST_Node)); node->data = data; node->left = NULL; node->right = NULL; return node; } //定义一个函数用来删除某个节点void destroy(BST_Node* node){ free(node);}
然后实现二叉查找树的主要部分在于插入、删除操作该如何实现。
首先来看插入:
要插入一个数据,同时保持树的特性不改变。这里根据要插入的数据与根节点数据的大小关系来选择插入左子树还是右子树,当根节点为空节点时就放到根节点中;
//该函数用来向以root为根的子树中插入node节点 void insert(BST_Node* node, BST_Node** root){ //这里用二级指针的目的在于直接修改root为根的子树,函数体中对源节点的修改要用一级指针的形式(二级解引用) if(!*root) *root = node; else if( node->data < (*root)->data) insert(node, &(*root)->left); //要插入左子树时可以看成向左子节点为根的二叉树中插入node,于是递归调用,这个递归终止条件就是*root为空,也就是说当找到某一路径的最底层子节点的子节点时插入; //查找树的特性通过if()中的判断选择来维持; else insert( node, &(*root)->right); } //插入函数 void bst_insert(BST* bstree, int data){ insert( creat(data), &bstree->root); ++size; }
插入ok,再来删除:
//先定义一个函数用来返回在以root为根节点的子树中,查找到数据data的节点,然后如下图所示: // 1 // / \ // 0 3 ->例如,要删除3,找到3的节点,然后将节点3的左子树挪到3的右子树的最左下 // / \ (也就是把2插入到3的右子树,当然结果肯定是在右子树的最左下) // 2 4 (删除的调整方法有两种) // / \ / \ BST_Node* tofind(int data, BST_Node** root){ if((*root)->data == data || !*root) return root; if(data < (*root)->data) tofind(data, &(*root)->left); if(data > (*root)->data) tofind(data, &(*root)->right); } bool delete(int data,BST* bstree){ BST_Node** node = tofind(data, &(bstree->root)); if(*node){ insert((*node)->left, (*node)->right); BST_Node* node_tmp = *node; *node = (*node)->right; destroy(node_tmp); --size; return true; } else return false; }
删除ok,其他的功能可以在插入、删除的功能上扩展出来,不重复了。
时间: 2024-10-23 07:31:11