【實驗目的與要求】
1、熟練掌握指令操作碼採用等長碼、哈夫曼碼、擴展碼的編碼方法。
2、在已知指令個數和頻度的基礎上,要求用程序實現等長碼、哈夫曼碼、擴展碼的編碼,實驗結束後提交源程序和實驗說明書。
【實驗內容】
瞭解和掌握指令編碼的基本原理和要求,在已知指令個數和頻度的前提上,要求用程序實現等長碼、哈夫曼碼(選做)、擴展碼的編碼,並計算出平均碼長。
【實驗步驟】
1.按提示輸入處理機的指令條數和使用頻度。
3.求出等長碼的編碼,並計算出平均碼長。
4.使用哈夫曼編碼方法,求出編碼和平均碼長(選做)。
5.根據指令個數和使用頻度,分析擴展碼的擴展格式,並求出編碼和平均碼長。
6.要設計出簡潔、直觀、易於操作的界面。
【源代碼】
// Test1.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//編碼方式
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
static int n;//記錄指令條數
static char Data[50];//記錄需要編碼的字符
static float Freq[50];//記錄使用頻度
static int Bin[50];//保存二進制編碼
void Binary(int t) {//求解二進制編碼
int i = 0;
while (t) {
int p = t % 2;
t /= 2;
Bin[i++] = p;
}
}
void Binary(int t,int n) {//求解二進制編碼
int i = n;
if (t == 0) {
Bin[i++] = 0;
}
while (t) {
int p = t % 2;
t /= 2;
Bin[i++] = p;
}
}
void EquL() {//等長編碼
int num = ceil(log(n) / log(2));//對指令條數進行對數運算向上取整。
cout << endl << "等長編碼的結果爲:" << endl;
for (int i = 0; i < n; i++) {
Binary(i);
cout << Freq[i] << " ";
for (int j = num - 1; j >= 0; j--) {
cout << Bin[j];
}
cout << endl;
}
cout << "平均碼長爲:" << num << endl << endl;
}
bool cmp(float x, float y) {//從大到小
return x > y;
}
void Extend() {//擴展編碼
cout << "=============擴展編碼:============\n\n";
for (int i = 0; i < n; i++) {
Bin[i] = 0;
}
sort(Freq, Freq + n, cmp);
for (int i = 0; i < n; i++) {
cout << Freq[i] << " ";
}
cout << endl;
int t = 0;
int w;
int num = ceil(log(n) / log(2));//最多需要的位數
float max = 100;
int d, c, dn, cn;
d = c = dn = cn = 0;
for (int i = 1; i < num; i++) {//i記錄短碼的位數
w = pow(2, i);//短碼最多可表示的個數
for (int j = 1; j < w; j++) {//j表示短碼錶示的個數
float sum = 0;
int surplus = 0;
int num1 = 0;
surplus = n - j;//短碼錶示後剩餘需要編碼的個數
int pt = surplus / (w - j);//需要擴展的位數
num1 = ceil(log(pt) / log(2));//最少需要的位數
if (num1 == 0) {
num1 += 1;
}
num1 += i;//這裏的num1表示長碼的位數
for (int k = 0; k < n; k++) {
if (k < j) {
sum += Freq[k] * i;
}
else {
sum += Freq[k] * num1;
}
}
if (sum < max) {
max = sum;
d = i;
c = num1;
dn = j;
cn=surplus;
}
cout <<"短碼位數:"<<i<<"\t長碼位數:"<<num1<<"\t平均碼長:"<< sum<<"\t\t";
cout << "短碼個數:" << j << "\t長碼個數:" << surplus << endl;
}
}
cout << "\n=============最優結果爲:=========" << endl << endl;
cout << "短碼位數:" << d << "\t長碼位數:" << c << "\t短碼編碼個數:" << dn << "\t長碼編碼個數:" << cn << "\t平均碼長:" << max << endl;
cout << "編碼結果:" << endl;
w= pow(2, d);//短碼位數最多可表示的數
int numc = 0;
for (int i = 0; i < dn; i++) {
Binary(i);
cout << Freq[i] << " ";
for (int j = d - 1; j >= 0; j--) {
cout << Bin[j];
}
cout << endl;
}
numc = dn;
for (int i = dn; i < w; i++) {
Binary(i);
if (numc <= n) {
for (int j = 0; j < pow(2, c - d); j++) {
Binary(j,d);
cout << Freq[numc++] << " ";
for (int k = d -1; k >= 0; k--) {
cout << Bin[k];
}
for (int k = c - 1; k >= d; k--) {
cout << Bin[k];
}
cout << endl;
}
}
}
}
int main()
{
cout << "請輸入指令條數:";
cin >> n;
cout << "請輸入使用頻度:" << endl;
for (int i = 0; i < n; i++) {
cin >> Freq[i];
}
EquL();//等長編碼
Extend();//擴展編碼
}
運行結果: