第六章二叉树和树(二叉树)

这本书的结构,先写概念,再写抽象数据类型,再写如何实现,再写应用。

1.1二叉树抽象数据类型

'''
ADT BinTree:                           #一个二叉树抽象数据类型
    BinTree(self,data,left,right):      #构造操作,创建一个新二叉树
    is_empty(self):                     #判断self是否为一个空二叉树
    num_nodes(self):                    #求二叉树的结点个数
    data(self):                         #获取二叉树根存储的数据
    left(self):                         #获取二叉树的左子树
    right(self):                        #获取二叉树的右子树
    set_left(self,btree):               #用btree取代原来的左子树
    set_right(self,btree):              #用btree取代原来的右子树
    traversal(self):                    #遍历二叉树中各结点数据的迭代器
    forall(self):                       #对二叉树中的每个结点的数据执行操作op
'''    

1.2二叉树的list实现

def BinTree(data,left=None,right=None):
    return [data,left,right]

def is_empty_BinTree(btree):
    return btree is None

def root(btree):
    return btree[0]

def left(btree):
    return btree[1]

def right(btree):
    return btree[2]

def set_root(btree,data):
    btree[0]=data

def set_left(btree,left):
    btree[1]=left
    
def set_right(btree,right):
    btree[2]=right
    
t1=BinTree(2,BinTree(4),BinTree(8))

1.3二叉树的简单应用:表达式树

#二叉树的简单应用:表达式树

#表达式构造函数
def make_sum(a,b):
    return ('+',a,b)

def make_prod(a,b):
    return ('*',a,b)

def make_diff(a,b):
    return ('-',a,b)

def make_div(a,b):
    return ('/',a,b)

#判别是否为基本表达式的函数
def is_basic_exp(a):
    return not isinstance(a,tuple)

#判断是否为数值的函数
def is_number(x):
    return (isinstance(x,int) or isinstance(x,float) or isinstance(x,complex))

#求值函数的基本部分
def eval_exp(e):
    if is_basic_exp(e):
        return e
    
    op,a,b = e[0],eval_exp(e[1]),eval_exp(e[2])
    if op=='+':
        return eval_sum(a,b)
    elif op=='-':
        return eval_diff(a,b)
    elif op=='*':
        return eval_prod(a,b)
    elif op=='/':
        return eval_div(a,b)
    else:
        raise ValueError('Unknow operator:',op)

#加
def eval_sum(a,b):
    if is_number(a) and is_number(b):
        return a+b
    if is_number(a) and a==0:
        return b
    if is_number(b) and b==0:
        return a
    return make_sum(a,b)

#减
def eval_diff(a,b):
    if is_number(a) and is_number(b):
        return a-b
    if is_number(a) and a==0:
        return -b
    if is_number(b) and b==0:
        return a
    return make_diff(a,b)

#乘
def eval_prod(a,b):
    if is_number(a) and is_number(b):
        return a*b
    if is_number(a) and a==0:
        return 0
    if is_number(b) and b==0:
        return 0
    return make_prod(a,b)

#除
def eval_div(a,b):
    if is_number(a) and is_number(b):
        return a/b
    if is_number(a) and a==0:
        return 0
    if is_number(b) and b==0:
        raise ZeroDivisionError
    return make_div(a,b)


e=('*',('-',5,'b'),('+',5,3))
result = eval_exp(e)

1.4优先队列

'''
优先队列
'''

'''
基于线性表的实现,用list表实现优先队列,下面实现这种功能的代码中,前提是:假设有n个信息,
对这n个信息用1,2,3,4,······,n表示,数值大小表示其优先程度
'''
class PrioQueueErroe(ValueError):
    pass

class PrioQue:
    def __init__(self,elist=[]):
        self._elems=list(elist)
        self._elems.sort(reverse=True)
        
    def enqueue(self,e):
        i=len(self._elems)-1
        while i>=0:
            if self._elems[i]<=e:
                i-=1
            else:
                break
        self._elems.insert(i+1,e)
        
    def is_empty(self):
        return not self._elems
    
    def peek(self):
        if self.is_empty():
            raise PrioQueueErroe()
        return self._elems[-1]
    
    def dequeue(self):
        if self.is_empty():
            raise PrioQueueErroe()
        return self._elems.pop()

prioque = PrioQue(elist=[1,4,8,25,39])
prioque._elems
'''
采用线性表技术实现优先队列,无论采用怎样的具体实现技术,在插入元素与取出元素的操作中总有
一种是具有线性复杂度的操作
'''

1.5基于堆的优先队列

        class PrioQueue:
    #Implementing priority queues using heaps
    
    def __init__(self,elist=[]):
        self._elems = list(elist)              #类似于复制,针对可变变量
        if elist:
            self.buildheap()
            
    def is_empty(self):
        return not self._elems
    
    def peek(self):
        if self.is_empty():
            raise PrioQueueErroe('in peek')
            
        return self._elems[0]
    
    def enqueue(self,e):
        self._elems.append(None)              #add a dummy element
        self.siftup(e,len(self._elems)-1)
        
    def siftup(self,e,last):
        elems,i,j = self._elems,last,(last-1)//2              #父结点索引
        while i>0 and e<elems[j]:
            elems[i] = elems[j]
            i,j = j,(j-1)//2
        elems[i] = e
    
    def dequeue(self):
        if self.is_empty():
            raise PrioQueueErroe('in dequeue')
        elems = self._elems
        e0 = elems[0]
        e = elems.pop()
        if len(elems)>0:
            self.siftdown(e,0,len(elems))
        return e0
    
    def siftdown(self,e,begin,end):
        elems,i,j = self._elems,begin,begin*2+1
        while j < end:
            if j+1 < end and elems[j+1] < elems[j]:
                j+=1                         #elems[j]不大于其兄弟结点的数据
            if e < elems[j]:                 #e在三者中最小,已找到位置
                break
            elems[i] = elems[j]              #elems[j]在三者中最小,上移
            i,j = j,2*j+1
        elems[i]=e
        
    def buildheap(self):
        end = len(self._elems)
        for i in range(end//2,-1,-1):
            self.siftdown(self._elems[i],i,end)
    
prioqueue = PrioQueue(elist=[6,3,4,7,9,2])
prioqueue._elems

1.6二叉树结点类

#定义二叉树结点类
class BinTNode:
    def __init__(self,dat,left=None,right=None):
        self.data = dat
        self.left = left
        self.right = right
        
t = BinTNode(1,BinTNode(2),BinTNode(3))

#统计树中结点个数
def count_BinTNodes(t):
    if t is None:
        return 0
    else:
        return 1 + count_BinTNodes(t.left)+count_BinTNodes(t.right)
    
#假设结点中保存数值,求这种二叉树里的所有数值和:
def sum_BinTNode(t):
    if t is None:
        return 0
    else:
        return t.data + sum_BinTNode(t.left) + sum_BinTNode(t.right)

#递归定义的遍历函数
def preorder(t,proc):
    if t is None:
        return 
    proc(t.data)
    preorder(t.left)
    preorder(t.right)

1.7非递归遍历算法

#宽度优先遍历
def levelorder(t):
    qu = SQueue()
    qu.enqueue(t)
    while not qu.is_empty():
        t = qu.dequeue()
        if t is None:         #弹出的树为空直接跳过
            continue
        qu.enqueue(t.left)
        qu.enqueue(t.right)
        print(t.data)
        
class SQueue():
    def __init__(self,init_len=8):
        self._len = init_len                 #存储区长度
        self._elems = [0]*init_len           #元素存储
        self._head = 0                       #表头元素下标
        self._num = 0                        #元素个数
        
    def is_empty(self):
        return self._num ==0                 
    
    def peek(self):
        if self._num == 0:
            raise StackUnderflow
        return self._elems[self._head]
    
    def dequeue(self):
        if self._num == 0:
            raise StackUnderflow
        e = self._elems[self._head]
        self._head = (self._head+1) % self._len
        self._num -= 1
        return e
    
    def enqueue(self,e):
        if self._num == self._len:
            self.__extend()
        self._elems[(self._head+self._num) % self._len] = e
        self._num +=1
        
    def __extend(self):
        old_len = self._len
        self._len *= 2
        new_elems = [0]*self._len
        for i in range(old_len):
            new_elems[i] =self._elems[(self._head+1)%old_len]
        self._elems,self._head = new_elems,0    

levelorder(t) 

 

#深度优先的非递归先根序遍历函数
class StackUnderflow(ValueError):                #空栈访问
    pass

class SStack():                                  #基于顺序表技术实现的栈类
    def __init__(self):                          #用list对象_elems存储栈元素
        self._elems = []                         #所有栈操作都映射到list操作
                                  
    def is_emply(self):
        return  self._elems == []
    
    def top(self):
        if self._elems == []:
            raise StackUnderflow('in SStack.top()')
        return self._elems[-1]
    
    def push(self,elem):
        self._elems.append(elem)
        
    def pop(self):
        if self._elems == []:
            raise StackUnderflow('in SStack.top()')
        return self._elems.pop()
    
def preorder_nonrec(t):
    s = SStack()        
    while t is not None or not s.is_emply():
        while t is not None:            #沿左分支下行
            print(t.data)                #先根序先处理根数据
            s.push(t.right)             #右分支入栈
            t = t.left
        t = s.pop()                     #遇到空树,回溯

preorder_nonrec(t)

 

1.8二叉树类

#二叉树类
class BinTree_01:
    
    def __init__(self):
        self._root = None

    def is_empty(self):
        return self._root is None
    
    def root(self):
        return self._root
    
    def leftchild(self):
        return self._root.left
    
    def rightchild(self):
        return self._root.right
    
    def set_root(self,rootnode):
        self._root = rootnode
        
    def set_left(self,leftchild):
        self._root.left = leftchild
        
    def set_right(self,rightchild):
        self._root.right = rightchild

1.9哈夫曼算法实现

#哈夫曼算法实现

class HTNode(BinTNode):
    def __lt__(self,othernode):
        return self.data < othernode.data

class HuffmanPrioQ(PrioQueue):
    def number(self):
        return len(self._elems)
    
def HuffmanTree(weights):
    trees = HuffmanPrioQ()
    for w in weights:
        trees.enqueue(HTNode(w))

    while trees.number() > 1:
        t1 = trees.dequeue()
        t2 = trees.dequeue()
        x = t1.data + t2.data
        trees.enqueue(HTNode(x,t1,t2))
    return trees.dequeue()

t2 = HuffmanTree([2,3,7,10,4,2,5])
levelorder(t2)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值