二叉查找树、二叉平衡树--python

代码仅供参考!

#coding:utf-8
import scrapy
import xlwt, lxml
import re, json
import matplotlib.pyplot as plt
import numpy as np
import pylab
from scipy import linalg
import sys
#树
#二叉查找树

'''
给定一颗二叉查找树,查找某节点p的过程就是递归过程
    若当前节点cur的值小于p的值,查找cur的左子树
    若当前节点cur的值不小于p的值,查找cur的右子树
    递归上述过程,直到cur==p或者cur为空
    
'''
class Node:
    def __init__(self,data):
        self.data=data
        self.lchild=None
        self.rchild=None
        self.height=None
        self.freq=None
    def search(self,node,data):
        if node is None:
            return False,node
        if node.data==data:
            return True,node
        if datanode.data:
                node.rchild=self.insert(node.rchild,data)
            else:
                node.lchild=self.insert(node.lchild,data)
        return node

#删除
    #记待删除节点为p,分三种情况进行处理:
        # p为叶子节点:直接删除该节点,再修改p的父节点的指针
        # p为单支节点:将p的子树与p的父亲节点相连,删除p即可
        # p的左子树和右子树均不空:找到p的直接后继d(p的右孩子的最左子孙【确保找到的是大于待删除节点的最小值,即确保依然是二叉查找树】);因d一定没有左子树,所以使用删除单支节点的方法:删除d,并让d的父亲节点dp称为d的右子树的父亲节点;同时,用d的值替换p的值
        # 相对的,可以找p的直接前驱x(p的左孩子的最右子孙),x一定没有右子树,所以可删除x,并让x的父亲节点成为x的左子树的父亲节点
    def delete(self,node,data):
        flag,n=self.search(node,data)
        if not flag:
            print('无该关键字,删除失败')
        else:
            if n.lchild and n.rchild:#左右子树均有[找直接后继]
                temp=n.rchild
                while temp.lchild:
                    temp=temp.lchild
                n.data=temp.data
                del temp
            else:
                temp = n
                if n.lchild is None:  # 没有左子树
                    n = n.rchild
                    del temp
                elif n.rchild is None:  # 没有右子树
                    n = n.lchild
                    del temp
        return

#二叉树的遍历
    #前序/中序/后序遍历

    #前序遍历:根、左、右
    def preOrder(self,node):
        if node is not None:

            print(node.data)
            self.preOrder(node.lchild)
            self.preOrder(node.rchild)

    #中序遍历:左、根、右【数组的升序】
    def inOrder(self,node):
        if node is not None:
            self.inOrder(node.lchild)
            print(node.data)
            self.inOrder(node.rchild)

    #后序遍历:左、右、根
    def postOrder(self,node):
        if node is not None:
            self.postOrder(node.lchild)
            self.postOrder(node.rchild)
            print(node.data)

    #根据前序中序,计算后序
        #如:已知某二叉树的遍历结果如下,求它的后序遍历
            # pre:GDAFEMHZ
            # mid:ADEFGHMZ
        #两个步骤:
            # 1.根据前序中序构造二叉树
            # 2.后序遍历二叉树
    def inPre2Post(self,inOrder,preOrder,a):
        if len(preOrder)==0:
            return
        node=preOrder[0]
        nroot=inOrder.index(node)#找到前序遍历的节点在中序遍历的位置
        # nroot=0
        # for nroot in range(0,length):
        #     if(inOrder[nroot]==node):
        #         break
        #
        self.inPre2Post(inOrder,preOrder[1:nroot+1],a)#左孩子部分
        self.inPre2Post(inOrder[nroot+1:],preOrder[nroot+1:],a)#右孩子部分
        # print(node)
        a.append(node)
        print(a)
        return a

    #已知中序后序,求前序遍历,同理
# node=Node('G')
# inOrder=['A','D','E','F','G','H','M','Z']
# preOrder=['G','D','A','F','E','M','H','Z']
#
# node.inPre2Post(inOrder,preOrder,[])

#平衡二叉树

# 高度不平衡:单旋转:左左,右右| 右左,左右:双旋转
    '''
    k2为根节点,k1左孩子节点
    左左,左子树节点k1向上旋转为根节点,k1的右孩子变换为k2左孩子
    '''
    def height(self,node):#递归求深度
        if node==None:
            return 0
        else:
            lh=self.height(node.lchild)
            rh=self.height(node.rchild)
            node.height=max(lh,rh)+1
            return node.height
    def singleRotateLeft(self,k2):#左左
        k1=k2.lchild
        k2.lchild=k1.rchild
        k1.rchild=k2
        k2.height=max(self.height(k2.lchild),self.height(k2.rchild))+1
        k1.height=max(self.height(k1.lchild),k2.height)+1
        return k1

    def singleRotateRight(self, k2):#右右
        k1 = k2.rchild
        k2.rchild = k1.lchild
        k1.lchild = k2
        k2.height = max(self.height(k2.lchild), self.height(k2.rchild)) + 1
        k1.height = max(self.height(k1.rchild), k2.height) + 1
        return k1

    #左右:k3为根节点,它的左子树k1比右子树D深2层,且k1子树更深的是其右子树k2
    def rotateLR(self,k3):#画图更加明了

        self.singleRotateRight(k3.lchild)
        self.singleRotateLeft(k3)

    #右左;
    def rotateRL(self,k3):
        self.singleRotateLeft(k3.rchild)
        self.singleRotateRight(k3)

    '''
    #平衡二叉树的插入:
        插入方法和二叉查找树基本一样,区别是,插入完成后需要从插入的节点开始维护一个到根节点的路径【递归压入栈的过程】,每经过一个节点都要维持树的平衡。维持树的平衡需要根据高度差的特点选择不同的旋转算法
    '''
    def insertOfAVL(self,node,data):
        if node is None:#节点为空,则在此节点插入data
            node=Node(data)
            return node

        if data>node.data:#如果小于当前节点值,则遍历当前节点的左子树插入data
            self.insertOfAVL(node.rchild,data)
            if(2==self.height(node.rchild)-self.height(node.lchild)):#高度差=2则不平衡,且前提已是右不平衡
                if data>node.rchild.data:#右右
                    self.singleRotateRight(node)
                else:
                    self.rotateRL(node)
        elif dataself.height(node.rchild.rchild)):
                    self.rotateRL(node)
                else:
                    self.singleRotateRight(node)
        elif data>node.data:
            self.deleteOfAVL(node.rchild,data)
            if 2==self.height(node.lchild)-self.height(node.rchild):
                if node.lchild.rchild is not None and (self.height(node.lchild.rchild)>self.height(node.lchild.lchild)):
                    self.rotateLR(node)
                else:
                    self.singleRotateLeft(node)
        else:
            if node.lchild and node.rchild:
                temp = node.rchild
                #找到其直接后继
                while temp.lchild:
                    temp=temp.lchild
                node.data =temp.data
                node.freq=temp.freq
                # pre.lchild = next.rchild
                self.deleteOfAVL(node.rchild,temp.data)  #???????????   
                del temp
                if 2==self.height(node.lchild)-self.height(node.rchild):
                    if node.lchild.rchild is not None and (
                            self.height(node.lchild.rchild) > self.height(node.lchild.lchild)):
                        self.rotateLR(node)
                    else:
                        self.singleRotateLeft(node)
            else:
                temp=node
                if node.lchild is None:
                    node=node.rchild
                elif node.rchild is None:
                    node=node.lchild
                    del temp
        node.height=max(self.height(node.lchild),self.height(node.rchild))+1



 

 

你可能感兴趣的:(Python,二叉查找树)