Files
2026-06-15 09:00:38 +08:00

108 lines
3.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}