用一维数组f[N]存贮通信符号的使用频率,用求最优二叉树的方法求得每个通信符号的前缀码。 (2)用链表保存最优二叉树,输出前缀码时可用树的遍历方法。
时间: 2024-03-23 11:36:51 浏览: 81
(1)使用一维数组f[N]存储通信符号的使用频率,可以按照下面的步骤来求得每个通信符号的前缀码:
1. 将每个符号看成一个节点,并给出它们的权值,存储在f数组中。
2. 对f数组进行排序,得到权值从小到大的顺序。
3. 依次选取两个权值最小的节点,将它们合并为一个新节点,并将新节点的权值设为这两个节点的权值之和。将新节点插入到f数组中,并将f数组中这两个节点的权值设为0。
4. 不断重复步骤3,直到f数组中只剩下一个节点,这个节点即为哈夫曼树的根节点。
5. 根据哈夫曼树的结构,给出每个通信符号对应的前缀码。从根节点开始遍历哈夫曼树,每次向左走为0,向右走为1。当到达一个叶子节点时,即得到该叶子节点对应的通信符号的前缀码。
具体实现可以参考下面的代码:
```python
def huffman(f):
# 将符号权值作为节点权值存储在f数组中
n = len(f)
nodes = [(f[i], i) for i in range(n)]
# 对节点按照权值从小到大排序
nodes.sort()
# 循环合并节点,直到只剩下一个节点
while len(nodes) > 1:
# 取权值最小的两个节点
w1, i1 = nodes.pop(0)
w2, i2 = nodes.pop(0)
# 合并为一个新节点
nodes.append((w1 + w2, i1, i2))
# 将新节点插入到正确的位置
for i in range(len(nodes) - 1, 0, -1):
if nodes[i][0] < nodes[i - 1][0]:
nodes[i], nodes[i - 1] = nodes[i - 1], nodes[i]
else:
break
# 将合并的节点的权值设为0,表示已合并
f[i1] = 0
f[i2] = 0
# 根据哈夫曼树的结构,给出每个符号对应的前缀码
codes = [''] * n
root = nodes[0][1:]
stack = [(root, '')]
while stack:
node, code = stack.pop()
if isinstance(node, int):
codes[node] = code
else:
stack.append((node[1], code + '0'))
stack.append((node[2], code + '1'))
return codes
```
(2)使用链表保存最优二叉树,可以按照下面的步骤来输出每个通信符号的前缀码:
1. 定义一个二叉树节点类Node,包含节点值val和左右子节点left、right。
2. 定义一个链表节点类ListNode,包含节点值val、前驱节点prev和后继节点next。
3. 构造哈夫曼树,并将每个节点存储在链表中。具体实现可以参考下面的代码:
```python
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
class ListNode:
def __init__(self, val, prev=None, next=None):
self.val = val
self.prev = prev
self.next = next
def huffman(f):
# 将符号权值作为节点权值存储在f数组中
n = len(f)
nodes = [Node(f[i]) for i in range(n)]
# 对节点按照权值从小到大排序
nodes.sort(key=lambda x: x.val)
# 构造哈夫曼树
while len(nodes) > 1:
# 取权值最小的两个节点
node1, node2 = nodes.pop(0), nodes.pop(0)
# 合并为一个新节点
new_node = Node(node1.val + node2.val, node1, node2)
# 将新节点插入到正确的位置
for i in range(len(nodes)):
if nodes[i].val > new_node.val:
nodes.insert(i, new_node)
break
else:
nodes.append(new_node)
# 将哈夫曼树的每个节点存储在链表中
head = ListNode(nodes[0])
cur = head
stack = [nodes[0]]
while stack:
node = stack.pop()
if node.right:
cur.next = ListNode(node.right)
cur.next.prev = cur
cur = cur.next
stack.append(node.right)
if node.left:
cur.next = ListNode(node.left)
cur.next.prev = cur
cur = cur.next
stack.append(node.left)
# 根据哈夫曼树的结构,给出每个符号对应的前缀码
codes = [''] * n
cur = head
while cur:
if cur.val.left is None and cur.val.right is None:
node, code = cur.val, ''
while node != head.val:
if node == node.parent.left:
code = '0' + code
else:
code = '1' + code
node = node.parent
codes[cur.val.index] = code
cur = cur.next
return codes
```
其中,Node类表示二叉树节点,val表示节点值,left和right表示左右子节点;ListNode类表示链表节点,val表示哈夫曼树节点,prev和next表示前驱和后继节点。在构造哈夫曼树时,需要将每个节点存储在链表中,并设置节点的前驱和后继节点。在输出前缀码时,可以利用每个叶子节点的祖先节点来获取该叶子节点对应的前缀码。
阅读全文