Python算法入门day9——二叉树

  • Post author:
  • Post category:python


1. 二叉树的性质

1.具有n个节点的非空二叉树共有n-1个分支。

证明:除了根节点以外,每个节点有且仅有一个双亲节点,即每个结点与其双亲节点之间仅有一个分支存在,因此,具有n个节点的非空二叉树的分支总数为n-1。

2. 非空二叉树的第i层最多有2^(i-1)个结点(i>=1)

3. 深度为h的非空二叉树最多有2^h-1个结点。

(深度为h且具有2^h-1个结点的二叉树为满二叉树。)

4. 若非空二叉树有n0个叶结点,有n2个度为2的结点,则 n0=n2+1

例:具有1102个结点的完全二叉树一定有__叶子节点。A:79 B:551 C:550 D:552

答案:B

完全二叉树一定存在1度结点,只需要除2向上取整即可,如果是奇数个结点,则存在0个一度结点,如果是偶数个结点,则存在1个一度结点。

5. 具有n个结点的非空完全二叉树的深度为h=(log2^n)+1

2. 二叉树的定义

二叉树的链式存储:将二叉树的节点定义为一个对象,节点之间通过类似链表的链接方式来连接。

#二叉树
class BiTreeNode:
    def __init__(self,data):
        self.data=data #存储节点中的数据
        self.lchild=None #左孩子
        self.rchild=None #右孩子
#案例
a=BiTreeNode("A")
b=BiTreeNode("B")
c=BiTreeNode("C")
d=BiTreeNode("D")
e=BiTreeNode("E")
f=BiTreeNode("F")
g=BiTreeNode("G")
e.rchild=g
e.lchild=a
a.rchild=c
c.lchild=b
c.rchild=d
g.rchild=f

root=e
#想找c
print(root.lchild.rchild.data)#C

3. 二叉树的遍历

二叉树的遍历方式一共有四种常用的,即前序遍历,中序遍历,后序遍历以及层次遍历。

1.前序遍历 :EACBDGF

【代码实现】

class BiTreeNode:
    def __init__(self,data):
        self.data=data #存储节点中的数据
        self.lchild=None #左孩子
        self.rchild=None #右孩子
#案例
a=BiTreeNode("A")
b=BiTreeNode("B")
c=BiTreeNode("C")
d=BiTreeNode("D")
e=BiTreeNode("E")
f=BiTreeNode("F")
g=BiTreeNode("G")
e.rchild=g
e.lchild=a
a.rchild=c
c.lchild=b
c.rchild=d
g.rchild=f
root=e #根

def pre_order(root):
    if root: #当root不为空时
        print(root.data,end=" ") #先输出
        pre_order(root.lchild) #再递归左孩子
        pre_order(root.rchild) #最后递归右孩子
pre_order(root) #E A C B D G F


2.中序遍历:A B C D E G F

def in_order(root):
    if root:
        in_order(root.lchild)
        print(root.data,end=" ")
        in_order(root.rchild)
in_order(root) #A B C D E G F


3.后序遍历:B D C A F G E

def end_order(root):
    if root:
        end_order(root.lchild) #先遍历左孩子
        end_order(root.rchild) #再遍历右孩子
        print(root.data,end=" ") #最后输出
end_order(root) #B D C A F G E


4.层次遍历:E A G C F B D

一层一层的从左往右遍历(广义优先,BFS)

1.定义队列,存放E

2.E出队,A,G进队

3.A出队,C进队

4.G出队,F进队

5.C出队,B,D进队

6.然后依次出队就得到了E A G C F B D

from collections import deque
#层次遍历BFS
def level_order(root):
    queue=deque()
    queue.append(root)
    while len(queue)>0:#只要队列不空
        node=queue.popleft()#删除第一个元素
        print(node.data,end=' ')
        #判断左右节点是否存在,如果存在,存放到队列中
        if node.lchild:#表示左孩子存在
            queue.append(node.lchild)
        if node.rchild:#表示右孩子存在
            queue.append(node.rchild)
level_order(root)#E A G C F B D

4. 二叉搜索树

1.二叉搜索树的定义

二叉搜索树是一颗二叉树且满足性质:设x是二叉树的一个节点。如果y是x的左子树的一个节点,那么y.key<=x.key;如果y是x的右子数的一个节点,那么y.key>=x.key

这个定义什么意思呢?

比如17这个节点 ,左边的子节点比自身小,右边的字节点比自身大

再比如5这个点,左边的2比5小,右边的11比5大

大概就是这么个意思

2.二叉搜索树的操作:插入,搜索

创建一个BST类,比节点小的放左边遍历,大的放右边遍历

class BiTreeNode:
    def __init__(self,data):
        self.data=data
        self.lchild=None #左孩子
        self.rchild=None #右孩子
        self.parent=None #父节点

class BST:
    def __init__(self,li=None):
        self.root=None
        if li:
            for val in li:
                self.insert_no_rec(val)
    #方法一:递归
    def insert(self,Node,val):#节点,插入的值
        if not Node: #如果node为空
            Node=BiTreeNode(val)
        #如果不为空,分三种情况,大于小于等于
        elif val<Node.data: #如果插入的值小于节点(左孩子)
            Node.lchild=self.insert(Node.lchild,val)
            Node.lchild.parent=Node
        elif val>Node.data:
            Node.rchild=self.insert(Node.lchild,val)
            Node.rchild.parent=Node
        #等于先不与考虑
        return Node
    
    #方法二:非递归
    def insert_no_rec(self,val):
        p=self.root #先定义一个p表示根节点,再进来的数与p做比较,左小右大
        #首先判断p是否为none
        if not p:
            #如果p是空的话,直接给根节点赋值
            self.root=BiTreeNode(val)
            return
        while True:
            if val<p.data: #如果小于节点,往左子树上走
                #判断是否有左子树
                if p.lchild: #如果p的左子树存在
                    p=p.lchild #往左子树上走一下
                else: #如果左子树不存在
                    p.lchild=BiTreeNode(val)
                    p.lchild.paren=p
                    return
            elif val>p.data:
                if p.rchild:
                    p=p.rchild
                else:
                    p.rchild=BiTreeNode(val)
                    p.rchild.parent=p
                    return
            else: #等于的时候什么都不敢
                return
    def pre_order(self,root):
        if root:
            print(root.data,end=' ')
            self.pre_order(root.lchild)
            self.pre_order(root.rchild)
    def in_order(self,root):
        if root:
            self.in_order(root.lchild)
            print(root.data,end=" ")
            self.in_order(root.rchild)
    def end_order(self,root):
        if root:
            self.end_order(root.lchild)
            self.end_order(root.rchild)
            print(root.data,end=" ")

    #查询 方法一:递归 
    #递归是需要node值的,非递归不需要
    def query(self,node,val):
        if not node:#如果没有节点
            return None
        if node.data<val:#从右边找
            return self.query(node.rchild,val)
        elif node.data>val:#从左找
            return self.query(node.lchild,val)
        else: #等于
            return node

    #查询 方法二:非递归
    def query_no_rec(self,val):
        p=self.root
        while p:
            if p.data<val:
                p=p.rchild
            elif p.data>val:
                p=p.lchild
            else: #如果等于
                return p
        return p
        
#案例
tree=BST([2,3,6,1,9,8,4,5,7])

tree.pre_order(tree.root)
print(" ")
tree.in_order(tree.root)
print(" ")
tree.end_order(tree.root)
print(" ")

#查找
print(tree.query_no_rec(1).data)#1 

【运行结果】

2 1 3 6 4 5 9 8 7

1 2 3 4 5 6 7 8 9

1 5 4 7 8 9 6 3 2

1



版权声明:本文为m0_48936146原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。