108 lines
3.8 KiB
C
108 lines
3.8 KiB
C
#include <stdio.h>
|
||
#include <math.h>
|
||
|
||
#define N 10 // 定义数组大小为10,包括占位符0
|
||
|
||
// 计算一个整数在二进制中需要的位数
|
||
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 = 1; i <= n; i++) {
|
||
b[i] = length(p[i]); // 计算当前元素的位数
|
||
int bmax = b[i]; // 记录当前最大位数
|
||
s[i] = (i > 1 ? s[i - 1] : 0) + bmax + header; // 计算当前段的最小存储长度
|
||
l[i] = 1; // 初始段数为1
|
||
printf("mid==%d\n",s[i]);
|
||
// 遍历可能的段数
|
||
for (int j = 2; j <= i && j <= Lmax; j++) {
|
||
// 更新最大位数
|
||
printf("bmax前**=%d",bmax);
|
||
if (bmax < length(p[i - j + 1])) {
|
||
bmax = length(p[i - j + 1]);
|
||
printf("bmax后**=%d",bmax);
|
||
}
|
||
// 判断是否需要更新存储长度
|
||
printf("\nmid=%d\n",s[i - j] + j * bmax + header);
|
||
if (s[i] > s[i - j] + j * bmax + header) {
|
||
|
||
s[i] = s[i - j] + j * bmax + header; // 更新最小存储长度
|
||
l[i] = j; // 更新段数
|
||
b[i] = bmax; // 更新位数
|
||
// printf("s[i]=%d,mid=%d\n",s[i],s[i - j] + j * bmax + header);
|
||
}
|
||
}
|
||
// 输出当前组的信息
|
||
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 >= 1) { // 只从1开始追溯,跳过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 = 1; // 从1开始,跳过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++]); // 逐个输出元素,跳过第一个0
|
||
}
|
||
printf("\n"); // 换行
|
||
}
|
||
}
|
||
|
||
// 主函数,程序入口
|
||
int main() {
|
||
int p[] = {0, 4, 6, 5, 7, 129, 138, 1, 2, 3}; // 输入的灰度序列(加了0)
|
||
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;
|
||
}
|