概述
相對編碼是另一種資料壓縮演算法。遊程編碼、點陣圖編碼以及圖編碼和模式替換都基於減少重複資料實現,而相對編碼目標略有不同。的確,遊程編碼要查詢連續重複出現的元素,模式替換和點陣圖編碼要“對映”重複出現的位置。
這些演算法的唯一問題在於輸入資料並非總是由重複元素組成。很明顯,如果輸入資料流包含許多重複元素,必定能減少。然而,這並不意味著沒有重複元素的資料就不能壓縮。這取決於資料。假設我們要壓縮的資料如下。
1 |
1, 2, 3, 4, 5, 6, 7 |
難以想象這個資料流能被壓縮。壓縮字母時可能存在同樣的問題。的確,字母是構成單詞的基礎,是構成單詞的最小單元而且很難再壓縮。
幸運的是,事實並非如此。相對編碼可以處理非重複資料。讓我們看看下面的輸入流——一段給定的年份(90年的)。
1 |
1991,1991,1999,1998,1991,1993,1992,1992 |
這裡有39個字元,我們能夠壓縮它們。我們通常使用的方法是去掉前面的“19”。
1 |
91,91,99,98,91,93,92,92 |
現在我們得到一個更短的字串,但在保留第一個年份的基礎上可以更進一步的壓縮。其餘的年份均相對於該年份。
1 |
91,0,8,7,0,2,1,1 |
此時傳輸的資料量減少了很多(從39降至16——超過50%)。然而,我們首先需要考慮一些問題,因為資料流的格式不會總是如此巧合。下面字元流會怎樣?
1 |
91,94,95,95,98,100,101,102,105,110 |
我們看到數值100在區間的中間,使用該值作為相對編碼的基準很方便。那麼上面的資料流就變成如下:
1 |
-9,-6,-5,-5,-2,100,1,2,5,10 |
問題在於決定哪一個數值作為基準值並不容易。如果資料以不同方式排列會怎樣。
1 |
96,97,98,99,100,101,102,103,999,1000,1001,1002 |
此時,數值“100”不能作為基準值,因為以該值為基準將得到如下結果:
1 |
-4,-3,-2,-1,100,1,2,3,899,900,901,902 |
對某基準值附近的相對值分組將會更加方便。
1 |
(-4,-3,-2,-1,100,1,2,3)(-1,1000,1,2) |
然而,找出基準值並不那麼容易。編碼格式也並不那麼重要。但是下面提到的這種情況,這種編碼卻很有用。
實現
該演算法的實現取決於特定的任務和資料流格式。假設我們要使用JSON從web伺服器傳輸年份資料流到瀏覽器,下面是一段簡單的PHP片段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// JSON: [1991,1991,1999,1998,1999,1998,1995,1997,1994,1993] $years = array(1991,1991,1999,1998,1999,1998,1995,1997,1994,1993); function relative_encoding($input) { $output = array(); $inputLength = count($input); $base = $input[0]; $output[] = $base; for ($i = 1; $i < $inputLength; $i++) { $output[] = $input[$i] - $base; } return $output; } // JSON: [1991,0,8,7,8,7,4,6,3,2] echo json_encode(relative_encoding($years)); |
應用
該演算法在很多情況都很有效,以下是其中一例。網路上有很多地圖應用。例如谷歌地圖,雅虎地圖,必應地圖就是非常有名的應用,同時也有非常有用的開源專案OpenStreetMap。成千上萬的網站使用這些應用。
典型的使用案例是使用JSON從伺服器傳輸大量地理座標到瀏覽器。的確,地球上任何地理座標點都相對於非洲西海岸附近的(0,0)點而言,在一定範圍內,當有大量標記時,我們可以使用相對編碼來傳輸資訊。
例如,下圖為標識了一些點的舊金山地圖。它們的座標都是相對於地球的(0,0)點而言。
地圖示記相對於地球的(0,0)點而言,有時沒什麼效果。
更加有效方式是相對市中心對那些標記進行編碼,這樣可以節省空間。
在一定範圍內對地圖示記使用相對編碼非常有效!
然而,這種壓縮型別可能會非常棘手,比如拖動地圖和更新座標陣列時。此外,如果需要載入多個城市,我們必須對座標進行分組。所以,在實現時必須謹慎。但另一方面,這也會很有用——例如在初始化載入地圖時可以減少資料量,縮短載入時間。
使用相對編碼,我們只要儲存相對基準值(資料)的偏移量——就像版本控制系統一樣,這樣可以降低傳輸和載入的資料。這裡有一個圖形的例子。第一種情況下,我們看到以下圖示中的每一項都是單獨儲存。它與相鄰元素無關,可以獨立與其他元素存在。
我們能只儲存第一個元素,其餘元素都相對與該元素,如下圖示所示。