- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在致力于在 Swift 中实现一种名为霍夫曼编码的无损压缩算法。我从使用 "1"
和 "0"
字符串的版本开始,但后来了解到单个字符串,例如 "0"
本身占用整个字节。现在,我已将字符串转换为 [UInt8]
(请参阅 packBits
函数)。似乎有些人通过编写 BitWriter 和 BitReader 来实现它,我最终可以重构它们,但我认为我的方法至少最终得到相同的 [UInt8]
结果,这肯定会减少HuffData.code
的大小与文本字节的大小,但是我需要存储要遍历的树以及用于解码的垫。由于 encode
func 返回 HuffData
(一个包含所有三个的结构),我注意到该大小实际上大于我传递给编码的文本。
例如,一个 paragraph.utf8.count
等于 8959 字节,编码后的总数据约为 21099 字节!其中2763是树,5050是代码,2是pad。我认为剩下的来自结构?为什么这些不加起来?
let huff = try? Huffman.encode(paragraph)
huff.count
= 总数据字节
我希望了解为什么这些字节计数没有相加,以及我的代码中的什么原因导致总数明显大于文本。我是否需要使用更大的文本才能看到真正的结果?我可以以更节省内存的方式存储树、代码和填充吗?为什么总数不等于树+代码+垫?序列化数据会增加更多字节吗?谢谢您的建议!
import Foundation
struct HuffData: Codable {
var code: [UInt8]
var tree: Node
var pad: Int
}
class Huffman {
static func decode(_ data: Data) throws -> String {
let huff = try JSONDecoder().decode(HuffData.self, from: data)
var bits: String = ""
// return bits to a string O and 1
for i in huff.code {
var str = String(i, radix: 2)
// if bits originally started with zeros, that was removed e.g. 32
if str.count < 8 {
str = String(repeating: "0", count: 8 - str.count) + str
}
bits += str
}
return Huffman.traverse(tree: huff.tree, with: String(bits.dropLast(huff.pad)))
}
static func encode(_ input: String) throws -> Data {
// count letter frequency
let sortedFrequency = input.reduce(into: [String: Int](), { freq, char in
freq[String(char), default: 0] += 1
})
// create queue of initial Nodes
let queue = sortedFrequency.map{ Node(name: $0.key, value: $0.value)}
// create tree
let tree = Huffman.createTree(with: queue)
// generate key by traversing tree
let key = Huffman.generateKey(for: tree, prefix: "")
// bit packed code
let code = input.compactMap({key[String($0)]}).joined()
let buffer = Huffman.packBits(for: code)
// save data
let huff = HuffData(code: buffer.code, tree: tree, pad: buffer.pad)
let data = try JSONEncoder().encode(huff)
return data
}
static private func generateKey(for node: Node, prefix: String) -> [String: String] {
var key = [String: String]()
if let left = node.left, let right = node.right {
key.merge(generateKey(for: left, prefix: prefix + "0"), uniquingKeysWith: {current,_ in current})
key.merge(generateKey(for: right, prefix: prefix + "1"), uniquingKeysWith: {current,_ in current})
}else {
key[node.name] = prefix
}
return key
}
static private func createTree(with queue: [Node]) -> Node {
// initialize queue that sorts by decreasing count
var queue = PriorityQueue(queue: queue)
// until we have 1 root node, join subtrees of least frequency
while queue.count > 1 {
let node1 = queue.dequeue()
let node2 = queue.dequeue()
let rootNode = Huffman.createRoot(with: node1, and: node2)
queue.enqueue(node: rootNode)
}
return queue.queue[0]
}
static private func traverse(tree: Node, with code: String) -> String {
var result = ""
var node = tree
for bit in code {
if bit == "0", let left = node.left {
node = left
} else if bit == "1", let right = node.right {
node = right
}
if node.left == nil && node.right == nil {
result += node.name
node = tree
}
}
return result
}
static private func createRoot(with first: Node, and second: Node) -> Node {
return Node(name: "\(first.name)\(second.name)", value: first.value + second.value, left: first, right: second)
}
static private func packBits(for s: String) -> (pad: Int, code: [UInt8]) {
var result = [UInt8]()
// pad with extra "0"'s to a length that is exact multiple of 8
let padding = 8 - (s.count % 8)
var bits = s + String(repeating: "0", count: padding)
// convert 8 bits at a time to a byte
while !bits.isEmpty {
result.append(UInt8(bits.prefix(8), radix: 2)!)
bits = String(bits.dropFirst(8))
}
return (pad: padding, code: result)
}
}
struct PriorityQueue {
var queue: [Node]
var count: Int {
return queue.count
}
mutating func enqueue(node: Node) {
queue.insert(node, at: queue.index(where: {$0.value <= node.value}) ?? 0)
}
mutating func dequeue() -> Node {
return queue.removeLast()
}
init(queue: [Node]){
// assumes queue will always be sorted by decreasing count
self.queue = queue.sorted(by: {$0.value > $1.value})
}
}
class Node: CustomStringConvertible, Codable {
var description: String {
return "\(name): \(value)"
}
let name: String
let value: Int
let left: Node?
let right: Node?
init(name: String, value: Int, left: Node? = nil, right: Node? = nil) {
self.name = name
self.value = value
self.left = left
self.right = right
}
}
最佳答案
您正在使用一个 Uint8 = 1 字节 = 每比特 8 位来编码比特序列。所以你的“压缩”比需要的要差 8 倍。
首先创建一个每个字节可以存储 8 位的数据结构。
关于swift - 霍夫曼压缩不会导致存储树和填充编码为 0's and 1' 的字节数减少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54152202/
我正在运行一个辅助角色,并检查 Azure 上托管的存储中是否存在数据。当我将连接字符串用于经典类型的存储时,我的代码可以正常工作,但是当我连接到 V2 Azure 存储时,它会抛出此异常。 “远程服
在我的应用程序的主页上,我正在进行 AJAX 调用以获取应用程序各个部分所需的大量数据。该调用如下所示: var url = "/Taxonomy/GetTaxonomyList/" $.getJSO
大家好,我正在尝试将我的商店导入我的 Vuex Route-Gard。 路由器/auth-guard.js import {store} from '../store' export default
我正在使用 C# 控制台应用程序 (.NET Core 3.1) 从 Azure Blob 存储读取大量图像文件并生成这些图像的缩略图。新图像将保存回 Azure,并将 Blob ID 存储在我们的数
我想将 Mlflow 设置为具有以下组件: 后端存储(本地):在本地使用 SQLite 数据库存储 Mlflow 实体(run_id、params、metrics...) 工件存储(远程):使用 Az
我正在使用 C# 控制台应用程序 (.NET Core 3.1) 从 Azure Blob 存储读取大量图像文件并生成这些图像的缩略图。新图像将保存回 Azure,并将 Blob ID 存储在我们的数
我想将 Mlflow 设置为具有以下组件: 后端存储(本地):在本地使用 SQLite 数据库存储 Mlflow 实体(run_id、params、metrics...) 工件存储(远程):使用 Az
我的 Windows 计算机上的本地文件夹中有一些图像。我想将所有图像上传到同一容器中的同一 blob。 我知道如何使用 Azure Storage SDKs 上传单个文件BlockBlobServi
我尝试发出 GET 请求来获取我的 Azure Blob 存储帐户的帐户详细信息,但每次都显示身份验证失败。谁能判断形成的 header 或签名字符串是否正确或是否存在其他问题? 代码如下: cons
这是用于编写 JSON 的 NeutralinoJS 存储 API。是否可以更新 JSON 文件(推送数据),而不仅仅是用新的 JS 对象覆盖数据。怎么做到的??? // Javascript
我有一个并行阶段设置,想知道是否可以在嵌套阶段之前运行脚本,所以像这样: stage('E2E-PR-CYPRESS') { when { allOf {
我想从命令行而不是从GUI列出VirtualBox VM的详细信息。我对存储细节特别感兴趣。 当我在GUI中单击VM时,可以看到包括存储部分在内的详细信息: 但是到目前为止,我还没有找到通过命令行执行
我有大约 3500 个防洪设施,我想将它们表示为一个网络来确定流动路径(本质上是一个有向图)。我目前正在使用 SqlServer 和 CTE 来递归检查所有节点及其上游组件,只要上游路径没有 fork
谁能告诉我 jquery data() 在哪里存储数据以及何时删除以及如何删除? 如果我用它来存储ajax调用结果,会有性能问题吗? 例如: $("body").data("test", { myDa
有人可以建议如何为 Firebase 存储中的文件设置备份。我能够备份数据库,但不确定如何为 firebase 存储中的文件(我有图像)设置定期备份。 最佳答案 如何进行 Firebase 存储的本地
我最近开始使用 firebase 存储和 firebase 功能。现在我一直在开发从功能到存储的文件上传。 我已经让它工作了(上传完成并且文件出现在存储部分),但是,图像永远保持这样(永远在右侧加载)
我想只允许用户将文件上传到他们自己的存储桶中,最大文件大小为 1MB,仍然允许他们删除文件。我添加了以下内容: match /myusers/{userId}/{allPaths=**} { al
使用生命周期管理策略将容器的内容从冷访问层移动到存档。我正在尝试以下策略,希望它能在一天后将该容器中的所有文件移动到存档层,但事实并非如此在职的。我设置了选择标准“一天未使用后”。 这是 json 代
对于连接到 Azure 存储端点,有 http 和 https 两个选项。 第一。 https 会带来开销,可能是 5%-10%,但我不支付同一个数据中心的费用。 第二。 http 更快,但 Auth
有人可以帮我理解这一点吗?我创建了Virtual Machine in Azure running Windows Server 2012 。我注意到 Azure 自动创建了一个存储帐户。当我进入该存
我是一名优秀的程序员,十分优秀!