# 查找(1) 二叉搜索树

## 定义和表示

class TreeNode:
def __init__(self,key=None):
self.key = key
self.parent = None
self.left = None
self.right = None

class BinarySearchTree:
def __init__(self):
self.root = None
self.nodeNum = 0

def getRoot(self):
return self.root

def getNodeNum(self):
return self.nodeNum

## 遍历

    #中根遍历递归版
def inOrderRec(self,r):
if r:
self.inOrderRec(r.left)
print(r.key,end=' ')
self.inOrderRec(r.right)

#中根遍历非递归版，借用栈
def inOrderWithStack(self):
s = Stack()
r = self.getRoot()
while r or not s.isEmpty():
if r:
s.push(r)
r = r.left
else:
r = s.pop()
print(r.key,end = ' ')
r = r.right

#中根遍历非递归非栈版，Joseph M.Morris实现。主要思想利用线索二叉树
#利用所有叶子结点的右指针，指向其后继结点，组成一个环，
#在第二次遍历到这个结点时，由于其左子树已经遍历完了，则访问该结点。
def inOrderNoRecNoStack(self):
p = self.getRoot()
r = None
while p:
q = p.left
if q:
while q is not r and q.right:
q = q.right
if q is not r:
q.right = p
p = p.left
continue
else:
q.right = None
print(p.key,end=' ')
r = p
p = p.right

#中根遍历非递归版，借用后继，该版本使用到了父指针进行回溯。
def inOrder(self):
r = self.getRoot()
p = self.minMum(r)
while p:
print(p.key,end= ' ')
p = self.successor(p)

#先根遍历递归版
def preOrderRec(self,r):
if r:
print(r.key,end=' ')
self.preOrderRec(r.left)
self.preOrderRec(r.right)

#后根遍历递归版
def postOrderRec(self,r):
if r:
self.postOrderRec(r.left)
self.postOrderRec(r.right)
print(r.key,end=' ')

#层级遍历，借用队列
def levelOrder(self):
q = Queue()
p = self.getRoot()
while p:
print(p.key, end=' ')
if p.left:
q.enqueue(p.left)
if p.right:
q.enqueue(p.right)
if q.isEmpty():
p = None
else:
p = q.dequeue()

## 查询

①：如果i结点有右子树，那么i结点的后继就是i结点的右子树的最小关键字结点。比如15的后继是17，7的后继是9，等等。
②：如果i结点没有右子树，那么需要从i开始沿树而上直到遇到这样一个结点，该结点是其父结点的左孩子，那这个父结点就是i的后继。请仔细体会这个过程。

    def search(self,key):
p = self.getRoot()
while p and key is not p.key:
if key < p.key:
p = p.left
else:
p = p.right
return p

def minMum(self,p):
while p.left:
p = p.left
return p

def maxMum(self,p):
while p.right:
p = p.right
return p

def successor(self,p):
if p.right:
return self.minMum(p.right)
x = p.parent
while x and p is x.right:
p = x
x = x.parent
return x

def predecessor(self,p):
if p.left:
return self.maxMum(p.left)
x = p.parent
while x and p is x.left:
p = x
x = x.parent
return x

## 插入和构建

    def insert(self,key):
node = TreeNode(key)
x = None
p = self.getRoot()
while p:
x = p
if node.key < p.key:
p = p.left
else:
p = p.right
node.parent = x
if not x:
self.root = node
elif node.key < x.key:
x.left = node
else:
x.right = node
self.nodeNum += 1

    #datalist = [key1,key2,...,keyn]
def build(self,datalist):
for key in datalist:
self.insert(key)

## 删除

①：p没有左孩子，用p的右孩子去代替p。这里其实包括了p有右孩子和p没有右孩子两种情况，用p的右孩子去代替p对于两种情况都是符合要求的。
②：p没有右孩子，即这种情况下，p有且仅有左孩子，把p的左孩子去代替p即可。
③：p有左孩子也有右孩子，找到p的后继psu(一定有)，psu的关键字和卫星数据(如果有)复制给p，然后把问题转化为删除psu结点，而根据性质，psu一定没有左孩子，那又回到了情况①，按照①的处理方式即可。

    #结点替换，v结点替换p结点
def _transplant(self,p,v):
if not p.parent:
self.root = v
elif p is p.parent.left:
p.parent.left = v
else:
p.parent.right = v
if v:
v.parent = p.parent

def delete(self,key):
p = self.search(key) #找到所要删除的关键字的结点，可能没有
if p:
if not p.left: #case 1
self._transplant(p, p.right)
elif not p.right: #case 2
self._transplant(p, p.left)
else: #case 3
x = self.minMum(p.right) #x是p的后继
p.key = x.key
self._transplant(x, x.right) #问题退化到case 1
self.nodeNum -= 1

• 本文已收录于以下专栏：

举报原因： 您举报文章：查找(1) 二叉搜索树 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)