96 lines
3.3 KiB
C
96 lines
3.3 KiB
C
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#define N 9 // 定义数组大小为9
|
|
|
|
// 计算一个整数在二进制中需要的位数
|
|
int length(int i) {
|
|
int k = 1; // 初始化位数计数器
|
|
i = i / 2; // 将整数除以2,开始计算
|
|
while (i > 0) { // 当i大于0时继续
|
|
k++; // 每次循环位数增加1
|
|
i = i / 2; // 继续除以2
|
|
}
|
|
return k; // 返回计算得到的位数
|
|
}
|
|
|
|
void Compress(int n, int p[], int s[], int l[], int b[]) {
|
|
int Lmax = 256, header = 11; // 定义最大段数和头部长度
|
|
s[0] = 0; // 初始化s数组
|
|
for (int i = 0; i <= n; i++) { // 遍历每个元素
|
|
b[i] = length(p[i]); // 计算当前元素的位数
|
|
int bmax = b[i]; // 记录当前最大位数
|
|
s[i] = (i > 0 ? s[i - 1] : 0) + bmax + header; //当前段的最小存储长度
|
|
l[i] = 1; // 初始段数为1
|
|
for (int j = 2; j <= i + 1 && j <= Lmax; j++) { // 遍历可能的段数
|
|
if (bmax < length(p[i - j + 1])) { // 更新最大位数
|
|
bmax = length(p[i - j + 1]);
|
|
}
|
|
// 判断是否需要更新存储长度
|
|
if (s[i] > s[i - j] + j * bmax + header) {
|
|
s[i] = s[i - j] + j * bmax + header; // 更新最小存储长度
|
|
l[i] = j; // 更新段数
|
|
b[i] = bmax; // 更新位数
|
|
}
|
|
}
|
|
printf("组 %d: L = %d, B = %d, S = %d\n", i, l[i], b[i], s[i]);
|
|
}
|
|
}
|
|
|
|
// 追溯函数,恢复最优分段信息
|
|
int TraceBack(int n, int l[], int b[]) {
|
|
int i = 0;
|
|
int temp_l[N], temp_b[N]; // 临时数组存储分段信息
|
|
|
|
// 从最后一个元素向前追溯
|
|
while (n >= 0) {
|
|
temp_l[i] = l[n]; // 记录段数
|
|
temp_b[i] = b[n]; // 记录位数
|
|
n = n - l[n]; // 更新n,向前移动
|
|
i++; // 增加索引
|
|
}
|
|
|
|
// 反转数组,恢复正确顺序
|
|
for (int j = 0; j < i; j++) {
|
|
b[j] = temp_b[i - j - 1]; // 反向赋值位数
|
|
l[j] = temp_l[i - j - 1]; // 反向赋值段数
|
|
}
|
|
return i; // 返回段数
|
|
}
|
|
|
|
// 输出函数,展示最终结果
|
|
void Out(int m, int min_len, int l[], int b[], int p[]) {
|
|
printf("最小长度:%d\n", min_len); // 输出最小存储长度
|
|
printf("共分成:%d段\n", m); // 输出段数
|
|
int index = 0; // 初始化索引
|
|
for (int i = 0; i < m; i++) {
|
|
// 输出每段的信息
|
|
printf("第%d段含有%d元素. 需要存储位数%d,", i + 1, l[i], b[i]);
|
|
printf("元素值:");
|
|
// 输出当前段的元素值
|
|
for (int j = 0; j < l[i]; j++) {
|
|
printf("%d ", p[index++]); // 逐个输出元素
|
|
}
|
|
printf("\n"); // 换行
|
|
}
|
|
}
|
|
|
|
// 主函数,程序入口
|
|
int main() {
|
|
int p[] = {4, 6,5, 7, 129, 138, 1,2,3}; // 输入的灰度序列
|
|
int s[N] = {0}, l[N] = {0}, b[N] = {0}; // 初始化存储长度、段数和位数的数组
|
|
|
|
// 输出输入序列
|
|
printf("图像的灰度序列为:\n");
|
|
for (int i = 0; i < N; i++) {
|
|
printf("%d ", p[i]);
|
|
}
|
|
printf("\n");
|
|
|
|
// 调用压缩函数
|
|
Compress(N - 1, p, s, l, b);
|
|
int m = TraceBack(N - 1, l, b); // 调用追溯函数获取段数
|
|
Out(m, s[N - 1], l, b, p); // 输出结果
|
|
return 0;
|
|
}
|