算法概述:
可变字节码VB利用整数个字节对间距编码和解码,能够在时间和空间上达到一个非常好的平衡点。
算法设计:
编码辅助函数、编码函数、解码函数、间距计算函数和计算倒排记录表函数实现VB的编码和解码过程,当用户输入原始倒排记录表后,系统可以计算输出间距记录表、可变字节码,并通过解码函数对可变字节码进行解码得到原始倒排记录表。设计思路如下:
开始编码解码结束
编码过程:
解码过程:
代码实现:
# 编码辅助函数
def VBEncodeNumber(n):
by, byte = '', []
while True:
byte.insert(0, n % 128 + 128) # 向列表的第 0 位添加元素()
if n < 128:
break
n = n // 128
for i in range(len(byte)):
if i < len(byte) - 1:
by += bin(byte[i]).replace('0b1', '0') + ' '
else:
by += bin(byte[i]).replace('0b', '')
return by
# 编码函数
def VBEncode(numbers): # 输入一个差值列表
bytestream = [] # 定义一个空列表
for n in numbers: # 遍历距离差值列表元素
byte = VBEncodeNumber(n) # 将该值进行进制转换(10--2)
bytestream.append(byte) # 将该数据的二进制形式添加至列表中
return bytestream # 返回差值(二进制形式)列表
# 解码函数
def VBDecode(bytestream): # 输入编码后的列表
numbers = [] # 初始化空列表
n = 0
for i in range(len(bytestream)):
byte = bytestream[i].split(' ') # 将每个元素的各个八位二进制数进行切分
l = len(byte) # 记录有多少个八位二进制数
for j in range(l): # 遍历每八位个二进制数进行数值转换
if j < 1 - 1:
by = int('0b1' + byte[j][1: len(byte[j])], 2)
else:
by = int('0b' + byte[j], 2)
n = 128*n + by if by < 128 else 128*(n - 1) + by
numbers.append(n) # 将每个计算好的十进制数加入到列表中
n = 0
return numbers # 返回编码后十进制数的列表
# 计算倒排记录表间距函数
def countdaopaidis(daopai):
daopaidis = daopai.copy() # 初始化差值函数
for i in range(len(daopai)):
if i == 0:
daopaidis[i] = daopai[i] # 第 0 位设为原第 0 位的值
else:
daopaidis[i] = daopai[i] - daopai[i - 1] # 其余位设置为该位与其前一位的差值
return daopaidis # 返回间距列表
# 计算倒排记录表函数
def countdaopai(daopaidis): # 输入一个十进制数的列表
daopai = daopaidis.copy() # 初始化一个空列表,存放计算出的原始倒排表
for i in range(len(daopaidis)):
daopai[i] = sum(daopaidis[0: i + 1]) # 计算每个原始数据(分别是从第0为开始到该位元素之间各个元素的和)
return daopai # 返回解码之后的数据列表
# 主函数
if __name__ == '__main__':
daopai = [777, 17743, 294068, 31251336]
print('原始倒排记录表为:\n', daopai, '\n')
daopaidis = countdaopaidis(daopai)
print('间距记录表为:\n', daopaidis, '\n')
bytestream = VBEncode(daopaidis) # 编码
print('可变字节码为:\n', bytestream, '\n')
daopaidis = VBDecode(bytestream) # 解码
daopai = countdaopai(daopaidis)
print('解码得到的倒排记录表为:\n', daopai, '\n')