日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

小量压缩简单算法

發布時間:2024/4/11 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 小量压缩简单算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本方介紹一種簡單的數據壓縮算法:SB (simple block)

作者:realxie

在對文檔進行倒排的時候經常涉及到對倒排文檔的壓縮,例如假設有單詞instance 出現的文檔有<1,3 ,4 , 6 ,9 ,10,... >,即倒排表以升充排列,這樣我們就可以在倒排文件中只保存前后兩個文檔位置的差量,即轉變之后結果為<1 ,2 , 1 , 2 , 3 , 1 , ...>,因此在遍歷的時候可以累積得到每個文檔位置。分析轉變后的倒排文件我們可知 (不失一般性)保存了更多的小量。如果在內存中我們以一個int類型來保存更多類似于1-10這樣的小量就會造成更多的浪費,這是因為1-10可以不超過 4bit的空間來進行存儲,而int占用32bit,因此會造成大量浪費。如何壓縮數據來節約更多的存儲空間有待我們解決。

目前已經有各種各樣的算法來解決不量問題:

全局方法:Unary , Binary , r ...

局部方法:Bernoulli , ...其它

縱觀各種各樣的方法實現起來都是相當的困難,并且具有較高的時間復雜度。

下面我來介紹一種我自己開發,相當簡單的一個算法,思想簡單,實現簡單,運行高效,并且具有相當好的壓縮效果,當然不是最后,畢竟簡單的背后肯定會 做出一定的犧牲。

算法思想:

首先說明該算法采用不定長編碼,設編碼的基本塊長度為BIT,則每個數字的編碼長度為BIT的整數倍。

每個基本塊的最后一位為標志位,當最后一位為0時說明編碼結束,此時我們可以得到一個整數,相反當最后一位不為0時,則要與后面的基本塊一起構成一 個更大的整數。

例如:設BIT = 5;則基本塊所能表示的最大值為15,下面給出一些例子

15:-> 11110

7 : -> 01110

現在你可能會問,如果要表示的數大于15怎么辦,那我們就使用多個基本塊來表示一個數據,此時前面(非最后)基本塊的最后一位必須為1,設基本塊的 數量為b , 那么最大可以表示的數據為2^(b*(BIT-1))-1,這就是說所有基本塊的位除了標志位之外都參與數據的二進制表示。如此:

255:-> 11111 11110

2099: ->10001 00111? 00110

解碼的時候只需要順序讀入每個基本塊就可以確定能否得到一個數據。

本代碼高亮顯示

??

#include<iostream>
#include<stdlib.h>
#include<string.h>
using?namespace?std;

#define?MAX?0xFFFFFF
#define?BIT?4


int?buff[MAX];//保存差量數據
int?temp[MAX];//保存解碼后的結果
char?code[MAX];//保存壓縮后的結果

int?cmp(const?void?*?a?,?const?void?*?b)
{
???????return?*(int*)a?-?*(int*)b;
}


//編碼,壓縮?
//data,待壓縮數據,len侍壓縮數據個數
//返回值:壓縮后所占位數
int?encode(int?*?data?,?int?len);

//解碼
//code?,壓縮后的數據?,?len:壓縮后占用的位數
//data:保存解碼后的數據,返回值:解碼后數據個數
int?decode(char?*?code?,?int?len?,?int?*?data);

//測試數據data需要要多少位可以表示
int?bsize(int?data);

//將data轉換成基本塊,b表示data需要b位方可表示出
//return?:轉換后的數據
int?block(int?data?,?int?b);

//將一個數據以二進制的形式打印
int?print(unsigned?int?data);

int?main()
{

???????//init
???????int?t?=?MAX?<<?2;
?????? memset(buff?,0?,?sizeof(buff));
???????for(int?i=0;i<MAX;i++){
?????? ???????int?temp?=?rand()%t;
?????? ?????? buff[temp>>2]?=?temp;
?????? }
?????? qsort(buff?,MAX?,?sizeof(int)?,?cmp);
???????int?num(0)?,?i(0);
???????while(!buff[i])i++;
?????? buff[num++]?=?buff[i++];?
???????for(;i<MAX;i++?,?num++)buff[num]?=?buff[i]?-?buff[i-1];
???????//init?上部分只是得到差量數據

???????
???????int?sum?=?encode(buff?,?num);
???????
???????//測試平均所需位數
?????? cout<<sum?*?1.0?/?num<<endl;
???????int?tnum?=??decode(code?,?sum?,?temp);

???????//測試解碼后數據是否正確
???????for(int?i=0;i<num;i++)
?????? ???????if(temp[i]?!=?buff[i]){
?????? ?????? ?????? cout<<"error:\t"<<i<<"\t"<<buff[i]<<"\t\t"<<temp[i]<<endl;
?????? ?????? ???????break;
?????? ?????? }
???????
???????return?0;
}


//計算data需要的字節數
int?bsize(int?data)
{
???????int?b?=?0;
???????while(data)?data?>>=?1?,?b++;
???????return?b;
}

int?block(int?data?,?int?b)
{
???????int?t?=?(1<<(BIT-1))-1;
???????int?res?=?0;
???????for(int?i?=?0;?i<b;i++){
?????? ???????if(i)t?<<=?(BIT-1);
?????? ???????int?tmp?=?data?&?t;
?????? ?????? tmp?<<=?(i+1);
?????? ?????? res?|=?tmp;
?????? }
???????for(int?i=b-1;i>0;i--)
?????? ?????? res?|=?(1<<(BIT*i));
?????? res?<<=?(32?-?BIT?*?b);
???????return?res;???????
}

int?encode(int?*?data?,?int?len)
{
???????int?sum?=?0;???????
?????? memset(code?,?0?,?sizeof(code));
???????for(int?i=0;i<len;i++){
?????? ???????int?b?=?bsize(data[i]);
?????? ???????int?l?=?b/(BIT-1);
?????? ???????if(?b?%?(BIT-1))?l++;
?????? ???????int?tl?=?sum?>>?3;
?????? ???????int?tm?=?sum?&?7;
?????? ???????unsigned?int?tmp?=?block(data[i]?,?l);
?????? ???????if(tm?==?0){
?????? ?????? ???????while(tmp){
?????? ?????? ?????? ?????? code[tl]?=?0;
?????? ?????? ?????? ?????? code[tl]?|=?tmp?>>?24;
?????? ?????? ?????? ?????? tmp?<<=?8;
?????? ?????? ?????? ?????? tl++;
?????? ?????? ?????? }
?????? ?????? ?????? sum?+=?l?*?BIT;???????
?????? ?????? }?else?{
?????? ?????? ?????? code[tl]?|=?(tmp?>>?(24?+?tm));
?????? ?????? ?????? tl++;
?????? ?????? ?????? tmp?<<=?(8-tm);
?????? ?????? ???????while(tmp){
?????? ?????? ?????? ?????? code[tl]?=?0;
?????? ?????? ?????? ?????? code[tl]?|=?tmp?>>?24;
?????? ?????? ?????? ?????? tmp?<<=?8;
?????? ?????? ?????? ?????? tl++;
?????? ?????? ?????? }
?????? ?????? ?????? sum?+=?l?*?BIT;
?????? ?????? }
?????? }
???????return?sum;
}


int?decode(char?*?code?,?int?sum?,?int?*?data)
{
???????int?p?=?0?,?res?=?0?,?bsize?=?0?,?num?=?0;
?????? num?=?0;
???????while(p<sum){
?????? ???????int?tb?=?p?>>?3;
?????? ???????int?tm?=?p?&?7;
?????? ???????int?bit?=?(code[tb]>>(7-tm))?&?1;
?????? ?????? res?=?(res<<1)?+?bit;
?????? ?????? bsize?++;p++;
?????? ???????if(bsize?%?BIT?==?0){
?????? ?????? ?????? res?>>=?1;
?????? ?????? ???????if(bit)?continue;
?????? ?????? ???????else?{
?????? ?????? ?????? ?????? data[num++]?=?res;
?????? ?????? ?????? ?????? bsize?=?0;
?????? ?????? ?????? ?????? res?=?0;
?????? ?????? ?????? }
?????? ?????? }
?????? }
???????return?num;
}

int?print(unsigned?int?data)
{
???????if(data?==?0)return?0;
?????? print(data/2);
?????? cout<<data%2;
???????return?0;
}

總結

以上是生活随笔為你收集整理的小量压缩简单算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。