树和二叉树:源代码

本文详细介绍了二叉树的链表实现,包括创建、遍历和操作节点的方法。此外,还讨论了两种优先队列的实现方式,一种是用有序列表,另一种是用堆。接着,模拟了海关检查站的运作,使用优先队列优化等待时间。最后,介绍了哈夫曼树的构造方法,用于高效的数据压缩。这些内容涵盖了数据结构和算法的基础知识,对于理解和实现相关算法至关重要。
摘要由CSDN通过智能技术生成

目录

1. 二叉树的 list 实现和表达式树

2. 优先队列的两种实现

3. 海关检查站模拟

4. 二叉树遍历和二叉树类

5. 哈夫曼算法


1. 二叉树的 list 实现和表达式树

""" Implementing binary trees as embedded list
"""

def BiTree(data, left, right):
    return [data, left, right]

def is_empty_BiTree(bitree):
    return bitree == []

def root(bitree):
    return bitree[0]

def leftch(bitree):
    return bitree[1]

def rightch(bitree):
    return bitree[2]

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

def set_leftch(bitree, left):
    bitree[1] = left

def set_rightch(bitree, right):
    bitree[2] = right

###############################################
#### Functions for ############################
#### building and manipulating ################
#### mathematical expressions  ################
from numbers import Number

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, list)

def is_compose_exp(a):
    return isinstance(a, list)

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("Unknown operator:", op)
        
def eval_sum(a, b):
    if isinstance(a, Number) and isinstance(b, Number):
        return a + b
    if isinstance(a, Number) and a == 0:
        return b
    if isinstance(b, Number) and b == 0:
        return a
    return make_sum(a, b)

def eval_diff(a, b):
    if isinstance(a, Number) and isinstance(b, Number):
        return a - b
    if isinstance(a, Number) and a == 0:
        return -b
    if isinstance(b, Number) and b == 0:
        return a
    return make_diff(a, b)

def eval_prod(a, b):
    if isinstance(a, Number) and isinstance(b, Number):
        return a * b
    if (isinstance(a, Number) and a == 0 or
        isinstance(b, Number) and b == 0):
        return 0
    if isinstance(a, Number) and a == 1:
        return b
    if isinstance(b, Number) and b == 1:
        return a
    return make_prod(a, b)

def eval_div(a, b):
    if isinstance(a, Number) and isinstance(b, Number):
        return a / b
    if isinstance(a, Number) and a == 0:
        return 0
    if isinstance(b, Number) and b == 0:
        raise ZeroDivisionError
    if isinstance(b, Number) and b == 1:
        return a
    return make_div(a, b)
    
   
if __name__ == '__main__':
##    t1 = BiTree(2, BiTree(4, [], []), BiTree(8, [], []))
##    print(t1)
##    set_leftch(leftch(t1), BiTree(5, [], []))
##    print(t1)

    e1 = make_prod(make_sum(2, 3), make_diff(4, 5))
    e2 = make_prod(make_diff(make_prod(2, 'a'), 3), make_diff(4, 5))
    e3 = make_div(make_sum(make_prod(2, 7), make_div(0, 'b')), make_div('a', 1))

#    eval_exp(['$', 2, 3]) # This will cause an exception because $ is not a valid operator
    

2. 优先队列的两种实现

# This file contains two
# implementations of priority queues:
# 1, as sorted list
# 2, as heap stored in a list
# and in addition,
# an implementation of heap sort function

class PrioQueueError(ValueError):
    pass

class PrioQue:
    """ Implementing binary trees as sorted list
    """
    def __init__(self, elist = []):
        self.elems = list(elist)
        self.elems.sort()

    def is_empty(self):
        return self.elems == []

    def peek(self):
        if self.is_empty():
            raise PrioQueueError("in top")
        return self.elems[len(self.elems)-1]

    def dequeue(self):
        if self.is_empty():
            raise PrioQueueError("in pop")
        return self.elems.pop()

    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)

class PrioQueue:
    """ Implementing binary trees as heaps
    """
    def __init__(self, elist = []):
        self.elems = list(elist)
        if elist != []:
            self.buildheap()

    def is_empty(self):
        return self.elems == []

    def peek(self):
        if self.is_empty():
            raise PrioQueueError("in top")
        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 PrioQueueError("in pop")
        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: # invariant: j == 2*i+1
            if j+1 < end and elems[j+1] < elems[j]:
                j += 1 # elems[j] <= its brother
            if e < elems[j]: # e is the smallest of the three
                break
            elems[i] = elems[j] # elems[j] is the smallest, move it up
            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)

def heap_sort(elems):
    def siftdown(elems, e, begin, end):
        i, j = begin, begin*2+1
        while j < end: # invariant: j == 2*i+1
            if j+1 < end and elems[j+1] < elems[j]:
                j += 1 # elems[j] <= its brother
            if e < elems[j]: # e is the smallest of the three
                break
            elems[i] = elems[j] # elems[j] is the smallest, move it up
            i, j = j, 2*j+1
        elems[i] = e
        
    end = len(elems)
    for i in range(end//2, -1, -1):
        siftdown(elems, elems[i], i, end)
    for i in range((end-1), 0, -1):
        e = elems[i]
        elems[i] = elems[0]
        siftdown(elems, e, 0, i)

from random import randint, random

def test1():
    print("Test class PrioQue:")
    pq = PrioQue()
    for i in range(12):
        pq.enqueue(randint(0, 30))
    while not pq.is_empty():
        print(pq.dequeue())

def test2():
    print("Test class PrioQueue:")
    pq = PrioQueue()
    for i in range(12):
        pq.enqueue(randint(0, 30))
    while not pq.is_empty():
        print(pq.dequeue())

def test3():
    print("Test function heap_sort:")
    lst = [randint(1, 30) for i in range(15)]
    print(lst)
    heap_sort(lst)
    print(lst)

if __name__ == '__main__':
    test1()

    test2()

    test3()
        
    pass
    

3. 海关检查站模拟

""" Implementing binary trees as embedded list
"""

from random import randint, random
from PrioQueue import PrioQueue, PrioQueueError
from SQueue import SQueue, QueueUnderflow

car_arrive_interval = (1, 2)
car_check_time = (3, 5)

class Simulation:
    def __init__(self, duration):
        self._eventq = PrioQueue()
        self._time = 0
        self._duration = duration

    def run(self):
        while not self._eventq.is_empty():
            event = self._eventq.dequeue()
            self._time = event.time()
            if self._time > self._duration:
                break
            event.run() # may cause new event(s)

    def add_event(self, event): self._eventq.enqueue(event)
    def cur_time(self): return self._time
        
class Customs:
    def __init__(self, gate_num, duration):
        self.simulation = Simulation(duration)
        self.waitline = SQueue()
        self.duration = duration
        self.gates = [0]*gate_num
        self.total_wait_time = 0
        self.total_used_time = 0
        self.car_num = 0

    def wait_time_acc(self, n): self.total_wait_time += n
    def total_time_acc(self, n): self.total_used_time += n
    def car_count_1(self): self.car_num += 1
    def add_event(self, event): self.simulation.add_event(event)

    def cur_time(self): return self.simulation.cur_time()
    def enqueue(self, car): self.waitline.enqueue(car)
    def has_queued_car(self): return not self.waitline.is_empty()
    def next_car(self) : return self.waitline.dequeue()

    def find_gate(self):
        for i in range(len(self.gates)):
            if self.gates[i] == 0:
                self.gates[i] = 1
                return i
        return None
    def free_gate(self, i):
        if self.gates[i] == 1:
            self.gates[i] = 0
        else:
            raise ValueError("Clear gate error.")

    def simulate(self):
        Arrive(0, self) # initially generate one car
        self.simulation.run()
        self.statistics()
        
    def statistics(self):
        print("Simulate " + str(self.duration) + " minutes, for "
              + str(len(self.gates)) + " gates")
        print(self.car_num, "cars pass the customs")
        print("Avarage waiting time:",
              self.total_wait_time/self.car_num)
        print("Avarage passing time:",
              self.total_used_time/self.car_num)
        i = 0
        while not self.waitline.is_empty():
            self.waitline.dequeue()
            i += 1
        print(i, "cars are in waiting line.")

class Car:
    def __init__(self, arrive_time):
        self.time = arrive_time
    def arrive_time(self):
        return self.time

def event_log(time, name): pass
#    print("Event: " + name + ", happens at " + str(time)) 

class Event:
    def __init__(self, event_time, customs):
        self.ctime = event_time
        self.customs = customs

    def __lt__(self, other_event):
        return self.ctime < other_event.ctime
    def __le__(self, other_event):
        return self.ctime <= other_event.ctime

    def time(self): return self.ctime
    def run(self, time, event_name): pass

# a run of coming event will enter the next coming event and
# maybe a check and leave event
class Arrive(Event):
    def __init__(self, arrive_time, customs):
        Event.__init__(self, arrive_time, customs)
        self.customs.add_event(self)

    def run(self):
        time, customs = self.ctime, self.customs
        event_log(time, "car arrive")
        # We genarate the next Arrive event
        Arrive(time + randint(*car_arrive_interval), customs)
        # dealing with current Arrive car
        car = Car(time)
        i = customs.find_gate()
        if i is not None:
            event_log(time, "car check")
            Leave(time + randint(*car_check_time), i, car, customs)
        else:
            customs.enqueue(car)
            
# a run of leaving event will cause some calculations
class Leave(Event):
    def __init__(self, leave_time, gate_num, car, customs):
        Event.__init__(self, leave_time, customs)
        self.car = car
        self.gate_num = gate_num
        self.customs.add_event(self)

    def run(self):
        time, customs = self.ctime, self.customs
        event_log(time, "car leave")
        customs.free_gate(self.gate_num)
        customs.car_count_1()
        customs.total_time_acc(time - self.car.arrive_time())
        if customs.has_queued_car():
            car = customs.next_car()
            i = customs.find_gate()
            event_log(time, "car check")
            customs.wait_time_acc(time - car.arrive_time())
            Leave(time + randint(*car_check_time), i, car, customs)

if __name__ == '__main__':

    cus = Customs(2, 480)
    cus.simulate()
    pass
    

4. 二叉树遍历和二叉树类

""" classes and functions for binary trees 
"""

class BiTNodeError(ValueError):
    pass

class BiTNode:
    def __init__(self, dat, left, right):
        self.data = dat
        self.left = left
        self.right = right

def count_BiTNodes(t):
    if t is None:
        return 0
    else:
        return 1 + count_BiTNodes(t.left) + count_BiTNode(t.right)

def sum_BiTNodes(t):
    if t is None:
        return 0
    else:
        return t.dat + sum_BiTNodes(t.left) + sum_BiTNodes(t.right)

def preorder(t, proc):
    if t is None: return
    assert(isinstence(t, BiTNode))
    proc(t.data)
    preorder(t.left)
    preorder(t.right)

def inorder(t, proc):
    if t is None: return
    inorder(t.left)
    proc(t.data)
    inorder(t.right)

def postorder(t, proc):
    if t is None: return
    postorder(t.left)
    postorder(t.right)
    proc(t.data)

from SQueue import *

def levelorder(t, proc):
    q = SQueue()
    q.enqueue(t)
    while not q.is_empty():
        n = q.dequeue()
        if t is None: continue
        q.enqueue(t.left)
        q.enqueue(t.right)
        proc(t.data)

from SStack import *

def preorder_nonrec(t, proc):
    s = SStack()
    while t is not None or not s.is_empty():
        while t is not None: # go down along left chain
            s.push(t.right)  # push right branch into stack
            proc(t.data)
            t = t.left
        t = s.pop()          # left chain ends, backtrack

def preorder_iter(t):
    s = SStack()
    while t is not None or not s.is_empty():
        while t is not None: 
            s.push(t.right)
            yield t.data
            t = t.left
        t = s.pop()

def inorder_nonrec(t, proc):
    s = SStack()
    while t is not None or not s.is_empty():
        while t is not None:
            s.push(t)
            t = t.left
        t = s.pop()
        proc(t.data)
        t = t.right

def postorder_nonrec(t, proc):
    s = SStack()
    while t is not None or not s.is_empty():
        while t is not None:  # iterate until top has no child
            s.push(t)
            t = t.left if t.left is not None else t.right
            # if we can go left, go, otherwise, go right
        t = s.pop()  # get the node to be access
        proc(t.data)
        if not s.is_empty() and s.top().left == t:
            t = s.top().right # end of left visit, turn right
        else:
            t = None # end of right visit, force to backtrack

def print_BiTNodes(t):
    if t is None:
        print("^", end="")
        return
    print("(" + str(t.data), end="")
    print_BiTNodes(t.left)
    print_BiTNodes(t.right)
    print(")", end="")

class BiTree:
    def __init__(self):
        self._root = None

    def is_empty(self):
        return self._root == None

    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

    def root(self): return self._root
    def leftchild(self): return self._root.left
    def rightchild(self): return self._root.right

    def preorder_iter(self):
        t, s = self._root, SStack()
        while t is not None or not s.is_empty():
            while t is not None: 
                s.push(t.right)
                yield t.data
                t = t.left
            t = s.pop()
    
if __name__ == '__main__':
    pass

5. 哈夫曼算法

""" classes and functions for binary trees 
"""

from PrioQueue import PrioQueue, PrioQueueError
from BiTree1 import BiTNode, print_BiTNodes

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

class HuffmanPrioQ(PrioQueue):
    def number(self): return self.num

def HuffmanTree(weights):
    trees = HuffmanPrioQ()
    for w in weights:
        trees.enqueue(HTNode(w, None, None))
    while trees.number() > 1:
        t1 = trees.dequeue()
        t2 = trees.dequeue()
        x = t1.data + t2.data
        trees.enqueue(HTNode(x, t1, t2))
    return trees.dequeue()

if __name__ == '__main__':

##    t = BiTNode(1, BiTNode(2, None, None), BiTNode(3, None, None))
##    print_BiTNodes(t)
##    print("\n")

    h = HuffmanTree([2, 3, 7, 10, 4, 2, 5])
    print_BiTNodes(h)

    pass

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值