二叉树相关算法实现

二叉树算法实现

一:二叉链表的建立和遍历

例,建立如图所示二叉链表:

二叉树相关算法实现

# 定义结点类
class BNode:
	def __init__(self,data=None,lchild=None,rchild=None):
		self.data = data
		self.lchild = lchild
		self.rchild = rchild

# 先序遍历函数
def preorder(T):
	if T == None:
		return 
	print(T.data, end="")
	preorder(T.lchild)
	preorder(T.rchild)

# 中序遍历
def inorder(T):
	if T == None:
		return
	inorder(T.lchild)
	print(T.data, end="")
	inorder(T.rchild)

# 后序遍历
def finalorder(T):
	if T == None:
		return
	finalorder(T.lchild)
	finalorder(T.rchild)
	print(T.data, end="")

if __name__ == '__main__':
	# 实例化结点
	a = BNode("A")
	b = BNode("B")
	c = BNode("C")
	d = BNode("D")
	a.lchild = b
	a.rchild = c
	b.rchild = d
    # 先序遍历二叉树
	preorder(a)
	print()
    # 中序遍历二叉树
	inorder(a)
	print()
    # 后序遍历二叉树
	finalorder(a)

如果结点很多,我们可以通过循环或递归的方式来创建结点

# 定义结点类
class BNode:
	def __init__(self,data=None,lchild=None,rchild=None):
		self.data = data
		self.lchild = lchild
		self.rchild = rchild

# 先序遍历函数
def preorder(T):
	if T == None:
		return 
	print(T.data, end="")
	preorder(T.lchild)
	preorder(T.rchild)

# 中序遍历
def inorder(T):
	if T == None:
		return
	inorder(T.lchild)
	print(T.data, end="")
	inorder(T.rchild)

# 后序遍历
def finalorder(T):
	if T == None:
		return
	finalorder(T.lchild)
	finalorder(T.rchild)
	print(T.data, end="")

# 递归创建二叉树
def createBT():
	ch = input("输入一个结点数据,*表示空")
	if ch == "*":
		return None
	else:
		T = BNode(ch)
		T.lchild = createBT()
		T.rchild = createBT()
	return T

if __name__ == '__main__':
	# 创建二叉树,如上图二叉树,输入顺序为:A B * D * * C * *
	T = createBT()
	# 先序遍历二叉树
	preorder(T)
	print()
	# 中序遍历二叉树
	inorder(T)
	print()
	# 后序遍历二叉树
	finalorder(T)

统计叶子结点数

# 定义结点类
class BNode:
	def __init__(self,data=None,lchild=None,rchild=None):
		self.data = data
		self.lchild = lchild
		self.rchild = rchild
	
    
# 递归创建二叉树
def createBT():
	ch = input("输入一个结点数据,*表示空")
	if ch == "*":
		return None
	else:
		T = BNode(ch)
		T.lchild = createBT()
		T.rchild = createBT()
	return T
	
	
# 统计叶子结点数
def countleaf(T):
	if T == None:
		return None
	else:
		if T.lchild == None and T.rchild == None:
			global n
			n += 1
		countleaf(T.lchild)
		countleaf(T.rchild)
		
		
if __name__ == '__main__':
	# 创建二叉树,如上图二叉树,输入顺序为:A B * D * * C * *
	T = createBT()
	# 定义计数器
	n = 0
	countleaf(T)
	print(n)

查找元素

# 定义结点类
class BNode:
	def __init__(self,data=None,lchild=None,rchild=None):
		self.data = data
		self.lchild = lchild
		self.rchild = rchild
		
# 递归创建二叉树
def createBT():
	ch = input("输入一个结点数据,*表示空")
	if ch == "*":
		return None
	else:
		T = BNode(ch)
		T.lchild = createBT()
		T.rchild = createBT()
	return T

# 查找元素
def searchdata(T, ch):
	if T == None:
		return None
	if T.data == ch:
		return T
	else:
		p = searchdata(T.lchild, ch)
		if p != None:
			return p
		p = searchdata(T.rchild, ch)
		if p != None:
			return p


if __name__ == '__main__':
	# 创建二叉树
	T = createBT()
	# 查找元素
	ch = input("请输入查找元素:")
	ret = searchdata(T, ch)
	if ret != None:
		print("元素存在")
	else:
		print("元素不存在")

二:二叉树的类表存储

为什么可以使用列表来存放二叉树?

  • 二叉树是递归定义的
  • python列表也是递归定义的

步骤如下:

  • 空树用None表示
  • 非空树用包含三个元素的列表[data,lchild,rchild]表示

把一棵树映射到一种分层的list结构,每棵二叉树都有与之对应的列表

以如下二叉树为例:

二叉树相关算法实现

它的list结构为:[“A”,[“B”,None,“D”,None,None]],[“C”,None,None]]

# 先序遍历
def preorder(T):
    if T == None:
        return
    print(T[0])
    preorder(T[1])
    preorder(T[2])

# 中序遍历
def inorder(T):
    if T == None:
        return
    inorder(T[1])
    print(T[0])
    inorder(T[2])
    
# 后序遍历
def finalorder(T):
    if T == None:
        return
    finalorder(T[1])
    finalorder(T[2])
    print(T[0])

if __name__ == '__main__':
    t = ["A",["B",None,["D",None,None]],["C",None,None]]
    preorder(t)
    inorder(t)
    finalorder(t)

创建二叉列表,以上图为例:

class BinTreeLink:
    def __init__(self, data, lchild=None, rchild=None):
        self.btree = [data, lchild, rchild]

    # 判断是否为空
    def is_empty(self):
        return self.btree[0] is None

    # 建立左子树
    def set_lchild(self, lchild):
        if self.is_empty():
            return
        self.btree[1] = lchild.btree

    # 建立右子树
    def set_rchild(self, rchild):
        if self.is_empty():
            return
        self.btree[2] = rchild.btree

if __name__ == '__main__':
    a = BinTreeLink("A")
    b = BinTreeLink("B")
    c = BinTreeLink("C")
    d = BinTreeLink("D")
    a.set_lchild(b)
    a.set_rchild(c)
    b.set_rchild(d)
    print(a.btree)

三:二叉树非递归中序遍历

​ 要实现非递归中序遍历算法,二叉树的列表存储方式必须为为链表存储。首先要建立二叉链表,然后利用栈来进行中序遍历。

以下图为例:

二叉树相关算法实现

# 定义栈
class sstack:
    def __init__(self):
        self.slist = []

    # 判断栈是否为空
    def is_empty(self):
        if self.slist == []:
            return 1
        else:
            return 0

    # 压栈
    def pushstack(self, item):
        self.slist.append(item)

    # 出栈
    def popstack(self):
        return self.slist.pop()

class BNode:
    def __init__(self, data=None, lchild=None, rchild=None):
        self.data = data
        self.lchild = lchild
        self.rchild = rchild

# 中序遍历
def inOrder(T):
    p = T
    s = sstack()
    while p != None or s.is_empty() != 1:
        while p != None:
            s.pushstack(p)
            p = p.lchild
        if s.is_empty() != 1:
            p = s.popstack()
            print(p.data)
            p = p.rchild


if __name__ == '__main__':
    a = BNode("A")
    b = BNode("B")
    c = BNode("C")
    d = BNode("D")
    a.lchild = b
    a.rchild = c
    b.rchild = d
    inOrder(a)

四:哈夫曼树的建立

构建如下哈夫曼树:

二叉树相关算法实现

# 节点创建
class HuffmanNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None
        self.rchild = None
        self.parent = None

# 构建哈夫曼树
def creatHuffmanTree(hufnode):
    nodelist = hufnode[:]
    while len(nodelist) > 1:
        nodelist.sort(key=lambda item:item.data)
        left = nodelist.pop(0)
        right = nodelist.pop(0)
        father = HuffmanNode(left.data + right.data)
        father.lchild = left
        father.rchild = right
        left.parent = father
        right.parent = father
        nodelist.append(father)
    return nodelist[0]

# 先序遍历
def preorder(T):
    if T == None:
        return
    print(T.data)
    preorder(T.lchild)
    preorder(T.rchild)

if __name__ == '__main__':
    hufnode = []
    while True:
        a = int(input("请输入叶子节点的权值,输入-1结束"))
        if a == -1:
            break
        hufnode.append(HuffmanNode(a))
    bt = creatHuffmanTree(hufnode)
    preorder(bt)

五:哈夫曼编码的实现

例:已知一段码文出现4个字符{T,;,A,C},出现的概率为{7,5,2,4},使用哈夫曼编码的方式对这4个字符进行编码。

过程:

​ (1) 遍历nodelis,从第一个叶子结点开始回退

​ (2) 遇到左分支设置为0,遇到右分支设置为1

​ (3) 直到回退到根结点,再去找下一个叶子结点。

class HuffmanNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None
        self.rchild = None
        self.parent = None

def creatHuffmanTree(hufnode):
    nodelist = hufnode[:]
    while len(nodelist) > 1:
        nodelist.sort(key=lambda item:item.data)
        left = nodelist.pop(0)
        right = nodelist.pop(0)
        father = HuffmanNode(left.data + right.data)
        father.lchild = left
        father.rchild = right
        left.parent = father
        right.parent = father
        nodelist.append(father)
    return nodelist[0]

# 哈夫曼编码
def hufEncode(hufnode, root):
    encode = [""] * len(hufnode)
    for i in range(len(hufnode)):
        node = hufnode[i]
        while node != root:
            if node.parent.lchild == node:
                encode[i] = "0" + encode[i]
            else:
                encode[i] = "1" + encode[i]
            node = node.parent
    return encode
上一篇:二叉树创建、前中后序遍历、节点数、叶子节点数、深度、交换左右子树代码实现


下一篇:线索二叉树(C语言)