中序遍历
递归的方法
x 为指针
INORDER-TREE-WALK(x)
If(x != NULL)
INORDER-TREE-WALK(x.left)
print x.key
INORDER-TREE-WALK(x.right)
非递归的方法:(将递归的实现进行翻译)
INORDER-TREE-WALK(x)
if(x== NULL)
return
top= x
stack inorder
while top != NULL or inorder 不为空
if(top != NULL)
inorder.push(top)
top = top.left
else
top = inorder.top()
inorder.pop()
print(top)
top = top.right
方法三:先调用TREE-MINMUM找到这棵树中的最小节点,再调用n – 1次TREE-SUCCESSOR(利用前驱的效果是一样的
其他递归见对应的代码
查询二叉搜索树
输入一个指向树根的指针和一个关键词key,如果这个节点存在,TREE-SEARCH返回一个指向关键词为key的指针,否则返回NULL
递归算法:
TREE-SEARCH(x , key)
Ifx == NULL or k == x.key
return x;
if(x.key < key)
TREE-SEARCH(x.right, key)
else
TREE-SEARCH(x.left, key)
非递归算法:
TREE-SEARCH(x , key)
while x != NULL and key != x.key
if(key < x.key)
x = x.left
else
x = x.right
return x
得到二叉搜索树的最大值或最小值
根据定义最大值为最右侧的节点,最小值为最左侧的节点
返回一个指向给定节点x为根的子树的最小元素,不存在返回NULL
非递归
TREE-MINMUM(x)
while x.left != NULL
x. = x.left
return x
递归:
TREE-MINMUM(x)
if(x.left == NULL)
return x
TREE-MINMUM(x.left)
思路:判断有无左节点,如果没有则输出,如果有,则将其赋为左节点,循环下去
TREE-MAXMUM(x)
while x.right != NULL
x = x.right
return x
二叉搜索树某个节点的后继和前驱
后继的定义:大于某个节点x的最小关键词
前驱的定义:小于某个节点x的最大关键词
可以用中序遍历来验证其的正确性
如果后继存在,返回一棵二叉搜索树中的节点x的后继,否则返回NULL
TREE-SUCCESSOR(x)
ifx.right != NULL
return TREE-MINMUM(x.right)
y =x.parent
while y != NULL and x == y.right
x = y
y = x.parent
return y
思路:
根据后继的定义:
若x节点存在右子树,则后继一定位于右子树,又由于为最小关键词,即右子树的最小节点
若x节点没有右子树,只能查找其父。包含该元素的最小左子树的节点即为后继
O(最小左子树的节点)
/
O
\
O
\
O(x)
TREE-PREDECESSOR(x)
ifx.left != NULL
return MAXMUM(x.left)
y= x.parent
whiley != NULL and x == y.left
x = y
y = x.parent
return y
二叉搜索树的插入
该过程中将节点z作为输入,其中z,key= v ,z.left = NULL ,z.right = NULL ,将z插入到树中相应的位置
思路:从树根出发,指针x记录了一条向下的简单路径,并查找要替换的输入项z的NULL
采用非递归的方法
TREE-INSERT(T,z)
y= NULL; //父节点
x = T.root //遍历指针
while x != NULL
y = x
if x.key < x.key
x = x.left
else
x = x.right
z.p = y
if y == NULL
T.root = z
else if z.key < y.key
y.left = z
else
y.right = z;
二叉搜索树的删除
root为查找到的节点
一共有四种情况
1. 要删除的节点没有左右子树,即为叶子节点
条件:root -> left == NULL , root -> right ==NULL
此时要删除这个节点,则得判断其父辈的情况
若parent ==NULL,则证明要删除的节点root是根节点,则此时只需要将head变为空指针,即head = NULL
否则,即parent!= NULL,则需要将parent的某一个孩子节点赋为空
利用root -> data和parent-> data的大小,判断root是位于那一边,并将父节点的那一边赋为NULL
删除节点root
2. 要删除的节点有左子树,没有右子树
条件:root -> left != NULL root-> right == NULL
此时要删除root,则需要用左子树的根节点来代替root
若parent == NULL,则证明要删除的节点root是根节点,则此时只需要将head指向左子树的根节点即head = root –> left
否则,即parent !=NULL,
第一步:root ->left -> parent = parent
第二步:判断root位于parent哪一棵子树,将parent的那一棵子树赋为root -> left.
删除节点root
3. 要删除的节点有右子树,没有左子树(类似于上面)
4. 要删除的节点有左右子树
条件:root -> left!= NULL root -> right != NULL
此时要删除root,则需要用root的后继来代替root(由于右子树存在,实际上是取右子树的最小值)
第一步:找到root的后继
第二步: 判断后继的位置
若后继恰好是root的右子树节点,即root -> right == successor无须修改后继的parent,则只需将root的左子树赋给后继,即successor -> left = root -> left root -> left -> parent = successor
否则,则需先修改后继的parent,讲后继的右子树赋给parent的左子树,即successor -> parent -> left= successor -> right successor -> right -> parent = successor -> parent,然后讲root的左右子树赋给successor(successor-> left = root -> left root ->left -> parent = successor successor-> right = root -> right root-> right -> parent = successor
第三步:successor -> parent = parent
第四步:
若parent == NULL,则证明root是根节点,则此时只需要head = successor
否则parent != NULL,判断root位于哪一棵子树,将那一棵子树赋为successor
删除节点root
为了在二叉搜索树内移动子树,定义一个子过程TRANSPLANT,它是用另一棵子树替代一棵子树并成为其双亲的孩子节点。当TRANSPLANT用一棵以v为根的子树来替换一棵以u为根的子树时,节点u的双亲就变成v的双亲,并且最后v成为u的双亲相应的孩子
TRANSPLANT(T,u,v)
if(u,parent == NULL)
T.root = v
else if(u == u,parent.left)
u.parent.left = v
else
u,parent.right = v
if(v != NULL)
v,p = u.p
下面是从二叉搜索树T中删除节点z的删除过程
TREE-DELETE(T,z)
if(z.left == NULL)
TRANSPLANT(T,z,z.right)
else if(z.right == NULL)
TRANSPLANT(T,z,z.left)
else
y = TREE-MINMUM(z.right) //y是没有左孩子的
if(y.p != z)
//若y不是z的右孩子,则须将y的父辈先处理好在进行操作
TRANSPLANT(T,y,y.right)(在这个过程中y.right.parent = y.parent,y,paret.left = y.right)
y.right = z.right
z.right.parent = y.
TRANSPLANT(T,z,y)
//将root的子树赋给后继,并修改子树的根节点
y.left = z.left
z.left.parent = y
delete z