首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Run-Length Encoding (RLE) 游程編碼 Java 實現:字符串壓縮與解壓

     編輯:Java 相關知識

算法原理

游程編碼 (Run-Length Encoding, RLE) 是最簡單的無損壓縮算法:將連續重複的字符替換為 計數 + 字符。適合含大量連續重複數據的場景 (如 BMP 圖像、簡單文本、日誌)。

示例

原文: "AAABBBCCCCCDD"  (12 字符)
編碼: "3A3B5C2D"      (8 字符, 壓縮率 33%)
解碼: 還原為原文

完整 Java 實現


public final class RleCodec {

    /** 編碼:字符串 -> RLE 壓縮字符串 */
    public static String encode(String source) {
        if (source == null || source.length() <= 1) return source;

        StringBuilder sb = new StringBuilder();
        int len = source.length();
        for (int i = 0; i < len; ) {
            char cur = source.charAt(i);
            int run = 1;
            while (i + run < len && source.charAt(i + run) == cur) run++;

            if (run > 1) sb.append(run).append(cur);
            else sb.append(cur);

            i += run;
        }
        return sb.toString();
    }

    /** 解碼:RLE 字符串 -> 原文字符串 */
    public static String decode(String encoded) {
        if (encoded == null || encoded.length() <= 1) return encoded;

        StringBuilder sb = new StringBuilder();
        int len = encoded.length();
        for (int i = 0; i < len; i++) {
            char ch = encoded.charAt(i);
            if (Character.isDigit(ch)) {
                // 讀取完整數字 (支援多位數計數)
                int j = i;
                while (j < len && Character.isDigit(encoded.charAt(j))) j++;
                int count = Integer.parseInt(encoded.substring(i, j));
                // 下一字符為重複字符
                if (j < len) {
                    char repeat = encoded.charAt(j);
                    sb.append(String.valueOf(repeat).repeat(Math.max(0, count)));
                    i = j; // 外層循環會 i++
                }
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    // 測試
    public static void main(String[] args) {
        String[] tests = {
            "AAABBBCCCCCDD",
            "Hello World",
            "111222333",
            "A",
            "",
            "12A3B"  // 包含數字字符的原文測試
        };

        for (String s : tests) {
            String enc = encode(s);
            String dec = decode(enc);
            System.out.printf("原文: %-15s 編碼: %-10s 解碼: %-15s %s%n", 
                "\"" + s + "\"", "\"" + enc + "\"", "\"" + dec + "\"", 
                s.equals(dec) ? "✓" : "✗ 失敗");
        }
    }
}

關鍵實現細節

點處理
多位數計數while (isdigit) j++ 解析完整整數,支援 >9 連續字符
原文含數字編碼時不對單個字符輸出計數 1,解碼時只有數字後緊跟字符才視為計數,避免歧義
空字符串/單字符直接返回
性能O(N) 時間,StringBuilder 避免字符串拼接開銷

變體與優化方向

  1. 位級 RLE:針對二進制圖像 (如傳真、BMP),按位編碼,壓縮率更高
  2. 帶符號 RLE:區分「字面長度」與「重複長度」,如 0-127: 字面長度; 128-255: 重複長度 (PCX 格式)
  3. 二維 RLE:掃描行間共享游程,用於 TIFF、PDF 圖像壓縮
  4. 硬件加速:GPU/ASIC 並行掃描計數

應用場景與局限

適合不適合
簡單圖像 (圖標、掃描件、漫畫)自然照片、加密數據、高熵文本
日誌文件 (大量重複時間戳/級別)已壓縮文件 (zip、jpg、mp4)
網絡傳輸帶寬受限、CPU 受限環境需要高壓縮比的通用存儲

現代替代品對比

算法壓縮率速度複雜度Java 實現
RLE低 (專用數據高)極快O(1)手寫 20 行
LZ4中極快 (GB/s)中lz4-java
Snappy中極快中snappy-java
Zstd高快高zstd-java
GZIP/Deflate高中高JDK 內建

總結

RLE 是壓縮算法入門的「Hello World」,代碼極簡、無狀態、流式友好。雖通用壓縮率低,但在特定數據模式 (長游程)、嵌入式設備、教學演示、簡單協議幀分隔 等場景仍具獨特價值。掌握其編碼/解碼對稱邏輯、數字歧義消解、邊界條件處理,有助於理解 LZ77、Huffman 等現代算法的基因。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved