【数据结构与算法分析】第四章 树(二)
3.二叉树
二叉树是一棵树,其中每个节点都不能有多于两个的儿子。
4.表达式树
表达式树的树叶是操作数,如常量或变量,其他节点为操作符。其计算过程为中序遍历(左子树,节点,右子树)。
如图为一个表达式树:
左子树的值为a+(b*c),右子树的值是((d * e)+f)*g,整个树为(a+(b * c))+(((d * e)+f)*g),也称为中缀表达式
后序遍历(左子树,右子树,节点)输出结果为:abc*++de * f+g*+,表达式也称为后缀表达式
前序遍历(节点,左子树,右子树)输出结果为:++a*bc * +*defg,表达式也称为前缀表达式
5.二叉查找树
二叉树的一个重要的应用是它们在查找中的使用。
二叉查找树的性质:
-
若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
-
若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
如图,左边的树为二叉查找树
分析:
左图,(1)对于节点6,左子树上的每个值均小于6,右子树上的每个值都大于6,(2)对于节点2,左子树上的每个值均小于2,右子树上的每个值都大于2,(3)对于节点4,左子树上的每个值均小于4,无右子树
右图,对于节点6,左子树中含有子节点7大于节点6,所有不是二叉查找树
5.1程序实现
二叉查找树的声明:
#ifndif _Tree_H struct TreeNode; typedef struct TreeNode *Position; typedef struct TreeNode *SearchTree; SearchTree MakeEmpty(SearchTree T); Position Find(ElementType X,SeachTree T); Position FindMin(SeachTree T); Position FindMax(SeachTree T); SearchTree Insert(ElementType X,SeachTree T); SearchTree Delete(ElementType X,SeachTree T); ElementType Retrieve(Position P); #endif struct TreeNode { ElementType Element; SearchTree Left; SearchTree Right; };
建立一个空树:
SearchTree MakeEmpty(SearchTree T) { if(T!=NULL) { MakeEmpty(T->Left); MakeEmpty(T->Right); free(T); } return NULL; }
二叉查找树的Find操作:
Position Find(ElementType X,SearchTree T)//利用二叉查找树中每个节点的左子节点小于父节点,有子节点大于父节点的性质 { if(T==NULL) return NULL;//未查找到关键字X if(X<T->Element)//如果查找的关键字小于节点的关键字 return Find(X,T->Left);//用递归方式,查找节点的左子节点 else if(X>T->Element)//如果查找的关键字大于节点的关键字 return Find(X,T->Right);//用递归方式,查找节点的右子节点 else return T;//查找到关键字X,返回指向树T中具有关键字X的节点的指针 }
对二叉查找树的FindMin的递归实现:
Position FindMin(SearchTree T)//查找树中最小元素的位置,每个父节点的左子节点均小于父节点 { if(T==NULL) return NULL; else if(T->Left==NULL) return T; else return FindMin(T->Left); }
对二叉查找树的FindMax的非递归实现:
Position FindMax(SearchTree T) { if(T!= NULL) while(T->Right != NULL) T=T->Right; return T; }
对二叉查找树的FindMax的递归实现:
Position FindMax(SearchTree T)//查找树中最大元素的位置,每个父节点的右子节点均大于父节点 { if(T==NULL) return NULL; else if(T->Right==NULL) return T; else return FindMax(T->Right); }
插入元素到二叉查找树:
SearchTree Insert(ElementType X,SearchTree T)//将X插入树T,如果找到X,则什么也不做,否则,将插入X到遍历的路径上的最后一点 { if(T==NULL) { T=malloc(sizeof(struct TreeNode)); if(T==NULL) FatalError("out of space"); else { T->Element = X; T->Left = T->Right = NULL; } } else if(X<T->Element) T->Left=Insert(X,T->Left); else if(X>T->Element) T->Right = Inser(X,T->Right); return T; }
如图插入元素5:
5.2Delete
删除节点的几种情况:
(1)节点是树叶,它可以立即被删除
(2)节点有一个儿子,删除情况如图:
(3)节点有两个儿子,用删除节点2的右子树的最小数据3代替该节点的数据,并递归的删除那个节点3,因为右子树的最小数据无左儿子,第二次删除较容易,删除情况如图:
代码实现:
SearchTree Delete(ElementType X,SearchTree T) { Position Temp; if(T==NULL) Error("Element not found"); else if(X<T->Element)//go left T->Left=Delete(X,T->Left); else if(X>T->Element)//go right T->Right=Delete(X,T->Right); else if(T->Left&&T->Right)//如果有两儿子 { Temp=FindMin(T->Right);//找到右子树中最小元素的位置 T->Element=Temp->Element; T->Right=Delete(T->Element,T->Right); } else//如果有一个或没有儿子 { Temp=T; if(T->Left!=NULL)//有一个左儿子 T=T->Left; else if(T->Right!=NULL)//有一个右儿子 T=T->Right; free(temp); } return T; }