这本书的结构,先写概念,再写抽象数据类型,再写如何实现,再写应用。
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)