バイナリ・ソート、バイナリツリー、バイナリ検索

二進木

  • ルート:ツリー内の上位ノード
  • 左リーフノード
  • 右葉ノード
  • サブツリー
    • 完全なサブツリー
      • 周りのルートノード、リーフノード
    • 不完全なサブツリー
      • 根、葉ノードは、左
      • ルートノード、右葉ノード
      • ルート
        • 特長:各ノードは、ツリーのサブルートノードとして動作することができます

定義:

class Node(object):
    
    def __init__(self,item):
        self.item = item
        self.left = None
        self.right = None

class Tree(object):
    
    def __init__(self):  # 构建一颗空树
        self.root = None  # 永远指向二叉树中的根节点
        
    def insert(self,item):
        """按照自上到下,从左到右的准则插入新的节点"""
        node = Node(item)
        cur = self.root
        
        if not cur:  # 这里不设防的话,如果二叉树根节点为空,下面的obj.left就会报错
            self.root = node
            return
        
        q = [cur]  # 列表中存放需要迭代的根节点
        while q:
            obj = q.pop(0)  # 按顺序迭代取第一个元素,满足从上到下,从左到右
            if not obj.left:  # 如果存在就添加到列表中,分析他的子节点有没有空的
                obj.left = node
                break
            if not obj.right:
                obj.right = node
                break
            
            q.append(obj.left)
            q.append(obj.right)

    def travel(self):
        """广度遍历"""
        cur = self.root
        q = [cur]  # [None,None]这种情况是存在的
        
        if not cur:  # 这里不设防的话,如果二叉树根节点为空,下面的obj.left就会报错
            return
        
        while q:
            obj = q.pop(0)
            print(obj.item)
            if obj.left:
                q.append(obj.left)
            if obj.right:
                q.append(obj.right)
                

使用します。

tree = Tree()
tree.insert(1)
tree.insert(3)
tree.insert(2)
tree.insert(5)
tree.insert(6)
tree.insert(4)
tree.insert(7)

tree.travel()
1
3
2
5
6
4
7
tree = Tree()

tree.travel()  # 不报错就行,测试下

バイナリツリートラバーサル

  • 幅トラバーサル

    • トラバースのコード(トラベル)は、幅を横断しています。上から下へのトラバースプログレッシブ幅トラバーサルと呼ばれています。
    • 横トラバース1つのレベル出力
  • 深トラバーサル:縦横断。所望の形態の後順の前にサブツリーを演技。サブツリーのルートノードの位置を参照後のプリアンブルの前に

    • プリアンブル:ルートについて、最初のサブツリーのルートを横断する、左サブツリーのノードを横断する右ノードであります
    • 左と右のルート:ためには、
    • シーケンス後:ルートについて
  • トラバーサルの深さのアイデアを実現

    • 深トラバーサルは、すべての木の子供を達成するために必要です
    • サブツリー及びサブツリーの間の差は、ルートノードに反映しました。
    • ツリー内の子ノードとすることができる書き込み機能は、他のサブツリー内の関数の効果にトラバースされる場合ツリー全体の深さを横断することができます。

ここに画像を挿入説明

定義:

class Node(object):
    
    def __init__(self,item):
        self.item = item
        self.left = None
        self.right = None

class Tree(object):
    
    def __init__(self):  # 构建一颗空树
        self.root = None  # 永远指向二叉树中的根节点
        
    def insert(self,item):
        """按照自上到下,从左到右的准则插入新的节点"""
        node = Node(item)
        cur = self.root
        
        if not cur:  # 这里不设防的话,如果二叉树根节点为空,下面的obj.left就会报错
            self.root = node
            return
        
        q = [cur]  # 列表中存放需要迭代的根节点
        while q:
            obj = q.pop(0)  # 按顺序迭代取第一个元素,满足从上到下,从左到右
            if not obj.left:  # 如果存在就添加到列表中,分析他的子节点有没有空的
                obj.left = node
                break
            if not obj.right:
                obj.right = node
                break
            
            q.append(obj.left)
            q.append(obj.right)

    def travel(self):
        cur = self.root
        q = [cur]  # [None,None]这种情况是存在的
        
        if not cur:  # 这里不设防的话,如果二叉树根节点为空,下面的obj.left就会报错
            return
        
        while q:
            obj = q.pop(0)
            print(obj.item)
            if obj.left:
                q.append(obj.left)
            if obj.right:
                q.append(obj.right)
                
    def forward(self,root):  # 根左右
        if not root:
            return
        print(root.item)
        self.forward(root.left)  # 递归
        self.forward(root.right)
                    
    def middle(self,root):  # 左根右
        if not root:
            return
        self.middle(root.left)
        print(root.item)
        self.middle(root.right)
                    
    def back(self,root):  # 左右根
        if not root:
            return
        self.back(root.left)
        self.back(root.right)
        print(root.item)
        

使用します。

tree = Tree()
tree.insert(1)
tree.insert(3)
tree.insert(2)
tree.insert(5)
tree.insert(6)
tree.insert(4)
tree.insert(7)

tree.back(tree.root)
5
6
3
4
7
2
1

バイナリツリーの並べ替え

ここに画像を挿入説明

ソート個人的理解バイナリ***:

  • 前に深いを横断するために、バイナリツリーの常に感じてソート+は正の配列要素は、魔法のビットに配置されることになるが、私は突然、いくつかの認識を考え続け、この方法はとても魔法ではありません。
    • 上図間違いなく良い3大よりも、例えば、右(下の右の子ノードと)に3、どんなにどの要素、見つけるためにどのように関係なく、;絶対に8時間よりも左にある要素8、;絶対より右側の要素5 5大
    • これは右、理解することができますか?私は大の右の要素を持っていなかった場合5は、例えば、どのように彼は私の左の子になっていませんでした、または子ノードは、その下の左の子ノードになりますか?まず、それは私と一緒に渡します
    • だから、(順番に)、左に、右の発注の原則のルートに手段をソートバイナリツリー真ん中にそれを理解したいです。
      • 3横切る、左側2は、2トラバーサルは、左側は、トラバースは、出力2,2右トラバース権利が空である、に戻り、完了2,2左、出力1、空の右、空のまま左トラバーサルに3,3復帰完了し、出力3、右8,8 3左トラバース5、5,5トラバースは空のまま、出力5、7、7、右トラバーサル5、6を残し、トラバース6,6出力7に戻り、出力6,7に空、右側が空である、5に戻り、8出力8に戻り、右側が空である、3に戻り、の終わり
      • 早期上記5のようにわずか5〜6出力その質問の前に、私はそうでない場合、それはときにのみ、元の5追加されます、限り5よりも右に、右下のまたは6 5、彼は間違いなく大きくなると、理解したかったです左!

定義:

class Node(object):
    
    def __init__(self,item):
        self.item = item
        self.left = None
        self.right = None

class SortTree(object):
    
    def __init__(self):
        self.root = None
    
    def add(self,item):
        node = Node(item)
        cur = self.root
        
        if not cur:  # 排序二叉树根节点不存在,该元素就直接作为根节点
            self.root = node
            return
        
        while 1:
            if node.item > cur.item:  # 如果大于你,就作为你的右子节点
                if not cur.right:  # 不存在就直接赋值
                    cur.right = node
                    break
                else:    # 如果右子节点已经存在,就与右子节点再进行比较
                    cur = cur.right
            else:
                if not cur.left:
                    cur.left = node
                    break
                else:
                    cur = cur.left
    
    def middle(self,root):  # 左根右
        if not root:
            return
        self.middle(root.left)
        print(root.item)
        self.middle(root.right)

使用します。

alist = [3,8,5,7,6,2,1]
tree = SortTree()
for item in alist:
    tree.add(item)
tree.middle(tree.root)  # 排序二叉树+中序深层遍历 会得到正序排列的元素

# 上面的alist换成[3,8,6,7,5,2,1]结果依然是正序排列,因为如果先6后5,到时候5就会作为6的左子节点,还是会先输出5,这方法真他妈神奇
1
2
3
5
6
7
8

バイナリ検索

  • バイナリ検索にのみ有効にすることができ順序付けられたシーケンス、以下の用に定義されていますバイナリ整数関数のルックアップ

ここに画像を挿入説明

バイナリ整数関数のルックアップ

def find(items,item):
    """
    第一个参数items必须是 有序序列;
    item是我们要在item中查找的元素
    """
    low_index = 0
    high_index = len(items) - 1
    find = False
    
    # 因为是有序排列的list,所以如果都不在最小值最大值范围内,那循环查找不是浪费时间吗?
    if item < items[low_index] or item > items[high_index]:
        return find
    
#     while not find:  # 这种也可以,但是没有下面的严谨
    while low_index <= high_index:  # 这个=很重要,不然上图中的第一种情况就会查找失败
        middle_index = (high_index + low_index) // 2  # 取中间索引
        
        if items[middle_index] > item:
            high_index = middle_index - 1  
            # 是不是好奇为啥要-1,由于我们一直是通过中间索引对应值与目标值进行比较,这样漏掉一个值会不会导致这个数据逃过检验呢?在有序序列内的元素都是整数的情况下是不会的,考虑绝对情况,漏掉的这个数据最多也就是中间值左侧的这个数,而我们high-1也正好是那个数,而之后的中间值绝对只会<=目标值,也就是说以后变动的只会是low索引值,而我们允许最大索引值=最小索引值,那么在一次次low+1的情况下,早晚会查找到这个元素
        elif items[middle_index] < item:
            low_index = middle_index + 1  # 同理,如果要针对非整数,那这个+1/-1就需要做出变动
        else:  # 中间序列对应值正好就是目标值
            find = True
            break
    
    return find

使用します。

alist = [1,2,3,4,5,6,7,8,9]
print(find(alist,6))
print(find(alist,8))
True
True

おすすめ

転載: www.cnblogs.com/Guoxing-Z/p/12670267.html