二叉查找树
时间:2014-07-22 23:05:15
收藏:0
阅读:231
一棵树是N个节点和N-1条边的集合。因为,每条边都将某个节点连接到它的父亲,而除去根节点外每一个节点都有一个父亲。
使二叉树成为二叉查找树的性质是,对于树中的每个节点X,它的左子树中所有关键字值小于X的关键字值,而它的右子树中所有关键字值大于X的关键字值。
在程序中,一定要记得处理的根节点为空的情况。除了删除节点的操作外,其它操作都比较容易实现,通常是递归地编写这些操作例程。删除节点的规则如下:
- 如果节点是树叶,立即删除它。
- 如果节点有一个儿子,那么将该节点的父节点调整为指向该儿子,然后删除该节点。
- 如果节点有两个儿子,那么查找该节点右子树中的最小数据,用最小数据替换该节点的数据,然后删除拥有最小数据的那个节点。因为右子树中最小数据的节点必定不会有做孩子,所以又回到了情况1或情况2.
例程:
#include <stdio.h>typedef int ElementType;typedef struct TreeNode *Position;typedef struct TreeNode *SearchTree;struct TreeNode{ // 自身数据加上指向左右子树的指针 ElementType Element; SearchTree Left; SearchTree Right;};SearchTree MakeEmpty(SearchTree T){ if (T != NULL) { MakeEmpty(T->Left); MakeEmpty(T->Right); free(T); } return T;}// 返回包含查找元素的指针或NULLPosition Find(SearchTree T, ElementType x){ if (T == NULL) return NULL; else if (T->Element < x) return Find(T->Right, x); else if (T->Element > x) return Find(T->Left, x); else return T;}Position FindMin(SearchTree T){ // 这个判断是必须的 if (T != NULL) while (T->Left) T = T->Left; return T;}// 递归版本Position FindMin_recurse(SearchTree T){ if (T == NULL) return NULL; else if (T->Left == NULL) return T; else return FindMin(T->Left);}Position FindMax(SearchTree T){ // 这个判断是必须的 if (T != NULL) while (T->Right) T = T->Right; return T;}// 相同节点已在树中,则不做任何操作// 返回指向新树根的指针SearchTree Insert(SearchTree T, ElementType x){ if (T == NULL) { T = malloc(sizeof(struct TreeNode)); if (T == NULL) return NULL; T->Element = x; T->Left = T->Right = NULL; } else if (x < T->Element) T->Left = Insert(T->Left, x); else if (x > T->Element) T->Right = Insert(T->Right, x); return T;}SearchTree Delete(SearchTree T, ElementType x){ Position tmp; if (T == NULL) return NULL; if (x < T->Element) T->Left = Delete(T->Left, x); else if (x > T->Element) T->Right = Delete(T->Right, x); else // 找到要删除的节点 { if (T->Left && T->Right) // 该节点有两个儿子 { tmp = FindMin(T->Right); T->Element = tmp->Element; T->Right = Delete(T->Right, tmp->Element); } else // 有一个儿子或没有儿子 { tmp = T; if (T->Left == NULL) T = T->Right; else if (T->Right == NULL) T = T->Left; free(tmp); } } return T;}SearchTree CreateTree(){ // 一定要初始化指针,因为Insert函数根据指针是否为空进行插入 SearchTree t = NULL; return t;}int main(){ SearchTree tree = CreateTree(); int i; for (i = 0; i < 10; i++) tree = Insert(tree, i); printf("Max = %d\n", FindMin(tree)->Element); printf("Max = %d\n", FindMax(tree)->Element); return 0;}
普通的二叉查找树期望的任意操作的平均时间为O(logN),而由于在删除的时候,我们总是用右子树的最小节点代替被删除节点,导致左子树比右子树深度更深。
参考:
《数据结构于算法分析》 P70、P73.
评论(0)