計算機演算法:資料壓縮之點陣圖(2)

湯曉發表於2014-11-18

概述

在之前的文章中,我們知道了如何壓縮一段重複元素組成的資料。這種壓縮稱為“遊程編碼”,該演算法在無損資料壓縮傳輸時非常方便。但問題是資料必須遵循特定格式。比如,字串“aaaaaaaabbbbbbbb”可以被壓縮成“a8b8”。此時,16個字元的字串被壓縮成4個字元,沒有丟失任何資訊,而長度卻只有原始長度的25%。但當字元(元素)以不同方式分散時,問題就會出現。如果字元不變,但是沒有連續出現,會是什麼情況?如果字串是“abababababababab”會如何?長度一樣,字元一樣,但是我們不能使用遊程編碼!確實,使用遊程演算法在最優情況下只能得到相同的字串。

然而在這種情況下,我們看到另一個事實。該字串有太多重複元素組成,儘管不是一個接著另一個。我可以使用點陣圖壓縮該字串。也就是說我們可以使用序列中的位來儲存給定元素出現的位置,這個序列可以簡單地轉換成一個十進位制值。上例中的字串“abababababababab”可以壓縮成“1010101010101010”,即十進位制數43690,甚至表示成十六進位制的AAAA更好。由此這個長字串就被壓縮了。當解壓(解碼)訊息時,我們再從十進位制/十六進位制轉化成二進位制,匹配字元的出現次數。當然,上面這個例程非常簡單,假設只有一個重複字元,其餘組成字元不同,像這樣:“abacadaeafagahai”。那麼,我們可以使用對字元“a”使用點陣圖-“1010101010101010”,壓縮後為“AAAA bcdefghi”。正如你所看到的,所有例子字串只有16字元,這是一個限制。對變長資料使用點陣圖有些棘手,它的解碼不太容易。

從根本上來說,點陣圖壓縮儲存了訊息中頻繁出現元素的位置!

此外,點陣圖壓縮不僅適用於字串。也能壓縮陣列,物件以及任何資料。我之前帖子中的例程就很合適。我們需要使用JSON從伺服器傳輸一個很大的陣列到客戶機(瀏覽器)。該資料非常適合於“遊程編碼”。假設資料不一樣——不同年份的集合,這些時間以不同方式分散。

JSON將會對訊息進行編碼,編碼後的訊息如下(一個簡單但很大的javascript陣列)。

然而,如果使用點陣圖壓縮,我們將得到一個更短的陣列。

此時的JSON如下:

很明顯,隨著待壓縮資料增加,壓縮率會變得越來越好。事實上,大部分人都是從影象瞭解了點陣圖壓縮,因為該演算法主要用於影象壓縮。可想而知,在壓縮黑白影象時效果會多麼好(因為黑色和白色可以視為0和1)。實際上,它也被用於超過兩種顏色(例如256色),壓縮的程度就非常高。

實現

下面基於PHP的實現僅僅是為了闡明點陣圖壓縮演算法。這個演算法適用於任何資料結構。

應用

當資料中有元素頻繁出現時,該演算法效果很好,所以你需要研究待壓縮資料的本質。實際上因為這個原因,該演算法通常用於PNG8或GIF影象的壓縮。

相關文章